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_uint64(&c
->xendev
, "page-ref", &mfn
) == -1)
100 assert(mfn
== (xen_pfn_t
)mfn
);
102 if (xenstore_read_fe_int(&c
->xendev
, "event-channel", &c
->xendev
.remote_port
) == -1)
105 c
->page
= xc_map_foreign_range(xen_xc
, c
->xendev
.dom
,
107 PROT_READ
| PROT_WRITE
, mfn
);
111 xen_be_bind_evtchn(&c
->xendev
);
112 xen_be_printf(&c
->xendev
, 1, "ring mfn %"PRIx64
", remote-port %d, local-port %d\n",
113 mfn
, c
->xendev
.remote_port
, c
->xendev
.local_port
);
118 static void common_unbind(struct common
*c
)
120 xen_be_unbind_evtchn(&c
->xendev
);
122 munmap(c
->page
, XC_PAGE_SIZE
);
127 /* -------------------------------------------------------------------- */
131 * These two tables are not needed any more, but left in here
132 * intentionally as documentation, to show how scancode2linux[]
135 * Tables to map from scancode to Linux input layer keycode.
136 * Scancodes are hardware-specific. These maps assumes a
137 * standard AT or PS/2 keyboard which is what QEMU feeds us.
139 const unsigned char atkbd_set2_keycode
[512] = {
141 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
142 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
143 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
144 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
145 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
146 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
147 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
148 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
151 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
152 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
153 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
154 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
155 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
156 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
157 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
161 const unsigned char atkbd_unxlate_table
[128] = {
163 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
164 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
165 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
166 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
167 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
168 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
169 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
170 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
176 * for (i = 0; i < 128; i++) {
177 * scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
178 * scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
181 static const unsigned char scancode2linux
[512] = {
182 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
183 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
184 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
185 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
186 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
187 80, 81, 82, 83, 99, 0, 86, 87, 88,117, 0, 0, 95,183,184,185,
188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
189 93, 0, 0, 89, 0, 0, 85, 91, 90, 92, 0, 94, 0,124,121, 0,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 165, 0, 0, 0, 0, 0, 0, 0, 0,163, 0, 0, 96, 97, 0, 0,
193 113,140,164, 0,166, 0, 0, 0, 0, 0,255, 0, 0, 0,114, 0,
194 115, 0,150, 0, 0, 98,255, 99,100, 0, 0, 0, 0, 0, 0, 0,
195 0, 0, 0, 0, 0,119,119,102,103,104, 0,105,112,106,118,107,
196 108,109,110,111, 0, 0, 0, 0, 0, 0, 0,125,126,127,116,142,
197 0, 0, 0,143, 0,217,156,173,128,159,158,157,155,226, 0,112,
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 /* Send an event to the keyboard frontend driver */
202 static int xenfb_kbd_event(struct XenInput
*xenfb
,
203 union xenkbd_in_event
*event
)
205 struct xenkbd_page
*page
= xenfb
->c
.page
;
208 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
213 prod
= page
->in_prod
;
214 if (prod
- page
->in_cons
== XENKBD_IN_RING_LEN
) {
219 xen_mb(); /* ensure ring space available */
220 XENKBD_IN_RING_REF(page
, prod
) = *event
;
221 xen_wmb(); /* ensure ring contents visible */
222 page
->in_prod
= prod
+ 1;
223 return xen_be_send_notify(&xenfb
->c
.xendev
);
226 /* Send a keyboard (or mouse button) event */
227 static int xenfb_send_key(struct XenInput
*xenfb
, bool down
, int keycode
)
229 union xenkbd_in_event event
;
231 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
232 event
.type
= XENKBD_TYPE_KEY
;
233 event
.key
.pressed
= down
? 1 : 0;
234 event
.key
.keycode
= keycode
;
236 return xenfb_kbd_event(xenfb
, &event
);
239 /* Send a relative mouse movement event */
240 static int xenfb_send_motion(struct XenInput
*xenfb
,
241 int rel_x
, int rel_y
, int rel_z
)
243 union xenkbd_in_event event
;
245 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
246 event
.type
= XENKBD_TYPE_MOTION
;
247 event
.motion
.rel_x
= rel_x
;
248 event
.motion
.rel_y
= rel_y
;
249 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
250 event
.motion
.rel_z
= rel_z
;
253 return xenfb_kbd_event(xenfb
, &event
);
256 /* Send an absolute mouse movement event */
257 static int xenfb_send_position(struct XenInput
*xenfb
,
258 int abs_x
, int abs_y
, int z
)
260 union xenkbd_in_event event
;
262 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
263 event
.type
= XENKBD_TYPE_POS
;
264 event
.pos
.abs_x
= abs_x
;
265 event
.pos
.abs_y
= abs_y
;
266 #if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207
269 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208
273 return xenfb_kbd_event(xenfb
, &event
);
277 * Send a key event from the client to the guest OS
278 * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
279 * We have to turn this into a Linux Input layer keycode.
281 * Extra complexity from the fact that with extended scancodes
282 * (like those produced by arrow keys) this method gets called
283 * twice, but we only want to send a single event. So we have to
284 * track the '0xe0' scancode state & collapse the extended keys
287 * Wish we could just send scancodes straight to the guest which
288 * already has code for dealing with this...
290 static void xenfb_key_event(void *opaque
, int scancode
)
292 struct XenInput
*xenfb
= opaque
;
295 if (scancode
== 0xe0) {
298 } else if (scancode
& 0x80) {
302 if (xenfb
->extended
) {
306 xenfb_send_key(xenfb
, down
, scancode2linux
[scancode
]);
310 * Send a mouse event from the client to the guest OS
312 * The QEMU mouse can be in either relative, or absolute mode.
313 * Movement is sent separately from button state, which has to
314 * be encoded as virtual key events. We also don't actually get
315 * given any button up/down events, so have to track changes in
318 static void xenfb_mouse_event(void *opaque
,
319 int dx
, int dy
, int dz
, int button_state
)
321 struct XenInput
*xenfb
= opaque
;
322 DisplaySurface
*surface
= qemu_console_surface(xenfb
->c
.con
);
323 int dw
= surface_width(surface
);
324 int dh
= surface_height(surface
);
327 if (xenfb
->abs_pointer_wanted
)
328 xenfb_send_position(xenfb
,
329 dx
* (dw
- 1) / 0x7fff,
330 dy
* (dh
- 1) / 0x7fff,
333 xenfb_send_motion(xenfb
, dx
, dy
, dz
);
335 for (i
= 0 ; i
< 8 ; i
++) {
336 int lastDown
= xenfb
->button_state
& (1 << i
);
337 int down
= button_state
& (1 << i
);
338 if (down
== lastDown
)
341 if (xenfb_send_key(xenfb
, down
, BTN_LEFT
+i
) < 0)
344 xenfb
->button_state
= button_state
;
347 static int input_init(struct XenDevice
*xendev
)
349 xenstore_write_be_int(xendev
, "feature-abs-pointer", 1);
353 static int input_initialise(struct XenDevice
*xendev
)
355 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
359 xen_be_printf(xendev
, 1, "ds not set (yet)\n");
363 rc
= common_bind(&in
->c
);
367 qemu_add_kbd_event_handler(xenfb_key_event
, in
);
371 static void input_connected(struct XenDevice
*xendev
)
373 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
375 if (xenstore_read_fe_int(xendev
, "request-abs-pointer",
376 &in
->abs_pointer_wanted
) == -1) {
377 in
->abs_pointer_wanted
= 0;
381 qemu_remove_mouse_event_handler(in
->qmouse
);
383 in
->qmouse
= qemu_add_mouse_event_handler(xenfb_mouse_event
, in
,
384 in
->abs_pointer_wanted
,
388 static void input_disconnect(struct XenDevice
*xendev
)
390 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
393 qemu_remove_mouse_event_handler(in
->qmouse
);
396 qemu_add_kbd_event_handler(NULL
, NULL
);
397 common_unbind(&in
->c
);
400 static void input_event(struct XenDevice
*xendev
)
402 struct XenInput
*xenfb
= container_of(xendev
, struct XenInput
, c
.xendev
);
403 struct xenkbd_page
*page
= xenfb
->c
.page
;
405 /* We don't understand any keyboard events, so just ignore them. */
406 if (page
->out_prod
== page
->out_cons
)
408 page
->out_cons
= page
->out_prod
;
409 xen_be_send_notify(&xenfb
->c
.xendev
);
412 /* -------------------------------------------------------------------- */
414 static void xenfb_copy_mfns(int mode
, int count
, xen_pfn_t
*dst
, void *src
)
416 uint32_t *src32
= src
;
417 uint64_t *src64
= src
;
420 for (i
= 0; i
< count
; i
++)
421 dst
[i
] = (mode
== 32) ? src32
[i
] : src64
[i
];
424 static int xenfb_map_fb(struct XenFB
*xenfb
)
426 struct xenfb_page
*page
= xenfb
->c
.page
;
427 char *protocol
= xenfb
->c
.xendev
.protocol
;
429 xen_pfn_t
*pgmfns
= NULL
;
430 xen_pfn_t
*fbmfns
= NULL
;
434 /* default to native */
436 mode
= sizeof(unsigned long) * 8;
440 * Undefined protocol, some guesswork needed.
442 * Old frontends which don't set the protocol use
443 * one page directory only, thus pd[1] must be zero.
444 * pd[1] of the 32bit struct layout and the lower
445 * 32 bits of pd[0] of the 64bit struct layout have
446 * the same location, so we can check that ...
448 uint32_t *ptr32
= NULL
;
449 uint32_t *ptr64
= NULL
;
450 #if defined(__i386__)
451 ptr32
= (void*)page
->pd
;
452 ptr64
= ((void*)page
->pd
) + 4;
453 #elif defined(__x86_64__)
454 ptr32
= ((void*)page
->pd
) - 4;
455 ptr64
= (void*)page
->pd
;
466 #if defined(__x86_64__)
467 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_32
) == 0) {
468 /* 64bit dom0, 32bit domU */
470 pd
= ((void*)page
->pd
) - 4;
471 #elif defined(__i386__)
472 } else if (strcmp(protocol
, XEN_IO_PROTO_ABI_X86_64
) == 0) {
473 /* 32bit dom0, 64bit domU */
475 pd
= ((void*)page
->pd
) + 4;
480 munmap(xenfb
->pixels
, xenfb
->fbpages
* XC_PAGE_SIZE
);
481 xenfb
->pixels
= NULL
;
484 xenfb
->fbpages
= (xenfb
->fb_len
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
485 n_fbdirs
= xenfb
->fbpages
* mode
/ 8;
486 n_fbdirs
= (n_fbdirs
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
488 pgmfns
= g_malloc0(sizeof(xen_pfn_t
) * n_fbdirs
);
489 fbmfns
= g_malloc0(sizeof(xen_pfn_t
) * xenfb
->fbpages
);
491 xenfb_copy_mfns(mode
, n_fbdirs
, pgmfns
, pd
);
492 map
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
493 PROT_READ
, pgmfns
, n_fbdirs
);
496 xenfb_copy_mfns(mode
, xenfb
->fbpages
, fbmfns
, map
);
497 munmap(map
, n_fbdirs
* XC_PAGE_SIZE
);
499 xenfb
->pixels
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
500 PROT_READ
, fbmfns
, xenfb
->fbpages
);
501 if (xenfb
->pixels
== NULL
)
504 ret
= 0; /* all is fine */
512 static int xenfb_configure_fb(struct XenFB
*xenfb
, size_t fb_len_lim
,
513 int width
, int height
, int depth
,
514 size_t fb_len
, int offset
, int row_stride
)
516 size_t mfn_sz
= sizeof(*((struct xenfb_page
*)0)->pd
);
517 size_t pd_len
= sizeof(((struct xenfb_page
*)0)->pd
) / mfn_sz
;
518 size_t fb_pages
= pd_len
* XC_PAGE_SIZE
/ mfn_sz
;
519 size_t fb_len_max
= fb_pages
* XC_PAGE_SIZE
;
520 int max_width
, max_height
;
522 if (fb_len_lim
> fb_len_max
) {
523 xen_be_printf(&xenfb
->c
.xendev
, 0, "fb size limit %zu exceeds %zu, corrected\n",
524 fb_len_lim
, fb_len_max
);
525 fb_len_lim
= fb_len_max
;
527 if (fb_len_lim
&& fb_len
> fb_len_lim
) {
528 xen_be_printf(&xenfb
->c
.xendev
, 0, "frontend fb size %zu limited to %zu\n",
532 if (depth
!= 8 && depth
!= 16 && depth
!= 24 && depth
!= 32) {
533 xen_be_printf(&xenfb
->c
.xendev
, 0, "can't handle frontend fb depth %d\n",
537 if (row_stride
<= 0 || row_stride
> fb_len
) {
538 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend stride %d\n", row_stride
);
541 max_width
= row_stride
/ (depth
/ 8);
542 if (width
< 0 || width
> max_width
) {
543 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend width %d limited to %d\n",
547 if (offset
< 0 || offset
>= fb_len
) {
548 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend offset %d (max %zu)\n",
552 max_height
= (fb_len
- offset
) / row_stride
;
553 if (height
< 0 || height
> max_height
) {
554 xen_be_printf(&xenfb
->c
.xendev
, 0, "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_be_printf(&xenfb
->c
.xendev
, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
567 width
, height
, depth
, offset
, row_stride
);
571 /* A convenient function for munging pixels between different depths */
572 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \
573 for (line = y ; line < (y+h) ; line++) { \
574 SRC_T *src = (SRC_T *)(xenfb->pixels \
576 + (line * xenfb->row_stride) \
577 + (x * xenfb->depth / 8)); \
578 DST_T *dst = (DST_T *)(data \
579 + (line * linesize) \
582 const int RSS = 32 - (RSB + GSB + BSB); \
583 const int GSS = 32 - (GSB + BSB); \
584 const int BSS = 32 - (BSB); \
585 const uint32_t RSM = (~0U) << (32 - RSB); \
586 const uint32_t GSM = (~0U) << (32 - GSB); \
587 const uint32_t BSM = (~0U) << (32 - BSB); \
588 const int RDS = 32 - (RDB + GDB + BDB); \
589 const int GDS = 32 - (GDB + BDB); \
590 const int BDS = 32 - (BDB); \
591 const uint32_t RDM = (~0U) << (32 - RDB); \
592 const uint32_t GDM = (~0U) << (32 - GDB); \
593 const uint32_t BDM = (~0U) << (32 - BDB); \
594 for (col = x ; col < (x+w) ; col++) { \
595 uint32_t spix = *src; \
596 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \
597 (((spix << GSS) & GSM & GDM) >> GDS) | \
598 (((spix << BSS) & BSM & BDM) >> BDS); \
599 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \
600 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \
606 * This copies data from the guest framebuffer region, into QEMU's
607 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer
608 * uses something else we must convert and copy, otherwise we can
609 * supply the buffer directly and no thing here.
611 static void xenfb_guest_copy(struct XenFB
*xenfb
, int x
, int y
, int w
, int h
)
613 DisplaySurface
*surface
= qemu_console_surface(xenfb
->c
.con
);
615 int bpp
= surface_bits_per_pixel(surface
);
616 int linesize
= surface_stride(surface
);
617 uint8_t *data
= surface_data(surface
);
619 if (!is_buffer_shared(surface
)) {
620 switch (xenfb
->depth
) {
623 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5);
624 } else if (bpp
== 32) {
625 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8);
632 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5);
633 } else if (bpp
== 32) {
634 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8);
643 if (oops
) /* should not happen */
644 xen_be_printf(&xenfb
->c
.xendev
, 0, "%s: oops: convert %d -> %d bpp?\n",
645 __FUNCTION__
, xenfb
->depth
, bpp
);
647 dpy_gfx_update(xenfb
->c
.con
, x
, y
, w
, h
);
650 #ifdef XENFB_TYPE_REFRESH_PERIOD
651 static int xenfb_queue_full(struct XenFB
*xenfb
)
653 struct xenfb_page
*page
= xenfb
->c
.page
;
659 prod
= page
->in_prod
;
660 cons
= page
->in_cons
;
661 return prod
- cons
== XENFB_IN_RING_LEN
;
664 static void xenfb_send_event(struct XenFB
*xenfb
, union xenfb_in_event
*event
)
667 struct xenfb_page
*page
= xenfb
->c
.page
;
669 prod
= page
->in_prod
;
670 /* caller ensures !xenfb_queue_full() */
671 xen_mb(); /* ensure ring space available */
672 XENFB_IN_RING_REF(page
, prod
) = *event
;
673 xen_wmb(); /* ensure ring contents visible */
674 page
->in_prod
= prod
+ 1;
676 xen_be_send_notify(&xenfb
->c
.xendev
);
679 static void xenfb_send_refresh_period(struct XenFB
*xenfb
, int period
)
681 union xenfb_in_event event
;
683 memset(&event
, 0, sizeof(event
));
684 event
.type
= XENFB_TYPE_REFRESH_PERIOD
;
685 event
.refresh_period
.period
= period
;
686 xenfb_send_event(xenfb
, &event
);
691 * Periodic update of display.
692 * Also transmit the refresh interval to the frontend.
694 * Never ever do any qemu display operations
695 * (resize, screen update) outside this function.
696 * Our screen might be inactive. When asked for
697 * an update we know it is active.
699 static void xenfb_update(void *opaque
)
701 struct XenFB
*xenfb
= opaque
;
702 DisplaySurface
*surface
;
705 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
708 if (!xenfb
->feature_update
) {
709 /* we don't get update notifications, thus use the
710 * sledge hammer approach ... */
711 xenfb
->up_fullscreen
= 1;
714 /* resize if needed */
715 if (xenfb
->do_resize
) {
716 pixman_format_code_t format
;
718 xenfb
->do_resize
= 0;
719 switch (xenfb
->depth
) {
722 /* console.c supported depth -> buffer can be used directly */
723 format
= qemu_default_pixman_format(xenfb
->depth
, true);
724 surface
= qemu_create_displaysurface_from
725 (xenfb
->width
, xenfb
->height
, format
,
726 xenfb
->row_stride
, xenfb
->pixels
+ xenfb
->offset
);
729 /* we must convert stuff */
730 surface
= qemu_create_displaysurface(xenfb
->width
, xenfb
->height
);
733 dpy_gfx_replace_surface(xenfb
->c
.con
, surface
);
734 xen_be_printf(&xenfb
->c
.xendev
, 1, "update: resizing: %dx%d @ %d bpp%s\n",
735 xenfb
->width
, xenfb
->height
, xenfb
->depth
,
736 is_buffer_shared(surface
) ? " (shared)" : "");
737 xenfb
->up_fullscreen
= 1;
740 /* run queued updates */
741 if (xenfb
->up_fullscreen
) {
742 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: fullscreen\n");
743 xenfb_guest_copy(xenfb
, 0, 0, xenfb
->width
, xenfb
->height
);
744 } else if (xenfb
->up_count
) {
745 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: %d rects\n", xenfb
->up_count
);
746 for (i
= 0; i
< xenfb
->up_count
; i
++)
747 xenfb_guest_copy(xenfb
,
748 xenfb
->up_rects
[i
].x
,
749 xenfb
->up_rects
[i
].y
,
750 xenfb
->up_rects
[i
].w
,
751 xenfb
->up_rects
[i
].h
);
753 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: nothing\n");
756 xenfb
->up_fullscreen
= 0;
759 static void xenfb_update_interval(void *opaque
, uint64_t interval
)
761 struct XenFB
*xenfb
= opaque
;
763 if (xenfb
->feature_update
) {
764 #ifdef XENFB_TYPE_REFRESH_PERIOD
765 if (xenfb_queue_full(xenfb
)) {
768 xenfb_send_refresh_period(xenfb
, interval
);
773 /* QEMU display state changed, so refresh the framebuffer copy */
774 static void xenfb_invalidate(void *opaque
)
776 struct XenFB
*xenfb
= opaque
;
777 xenfb
->up_fullscreen
= 1;
780 static void xenfb_handle_events(struct XenFB
*xenfb
)
783 struct xenfb_page
*page
= xenfb
->c
.page
;
785 prod
= page
->out_prod
;
786 if (prod
== page
->out_cons
)
788 xen_rmb(); /* ensure we see ring contents up to prod */
789 for (cons
= page
->out_cons
; cons
!= prod
; cons
++) {
790 union xenfb_out_event
*event
= &XENFB_OUT_RING_REF(page
, cons
);
793 switch (event
->type
) {
794 case XENFB_TYPE_UPDATE
:
795 if (xenfb
->up_count
== UP_QUEUE
)
796 xenfb
->up_fullscreen
= 1;
797 if (xenfb
->up_fullscreen
)
799 x
= MAX(event
->update
.x
, 0);
800 y
= MAX(event
->update
.y
, 0);
801 w
= MIN(event
->update
.width
, xenfb
->width
- x
);
802 h
= MIN(event
->update
.height
, xenfb
->height
- y
);
803 if (w
< 0 || h
< 0) {
804 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update ignored\n");
807 if (x
!= event
->update
.x
||
808 y
!= event
->update
.y
||
809 w
!= event
->update
.width
||
810 h
!= event
->update
.height
) {
811 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update clipped\n");
813 if (w
== xenfb
->width
&& h
> xenfb
->height
/ 2) {
814 /* scroll detector: updated more than 50% of the lines,
815 * don't bother keeping track of the rectangles then */
816 xenfb
->up_fullscreen
= 1;
818 xenfb
->up_rects
[xenfb
->up_count
].x
= x
;
819 xenfb
->up_rects
[xenfb
->up_count
].y
= y
;
820 xenfb
->up_rects
[xenfb
->up_count
].w
= w
;
821 xenfb
->up_rects
[xenfb
->up_count
].h
= h
;
825 #ifdef XENFB_TYPE_RESIZE
826 case XENFB_TYPE_RESIZE
:
827 if (xenfb_configure_fb(xenfb
, xenfb
->fb_len
,
829 event
->resize
.height
,
832 event
->resize
.offset
,
833 event
->resize
.stride
) < 0)
835 xenfb_invalidate(xenfb
);
840 xen_mb(); /* ensure we're done with ring contents */
841 page
->out_cons
= cons
;
844 static int fb_init(struct XenDevice
*xendev
)
846 #ifdef XENFB_TYPE_RESIZE
847 xenstore_write_be_int(xendev
, "feature-resize", 1);
852 static int fb_initialise(struct XenDevice
*xendev
)
854 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
855 struct xenfb_page
*fb_page
;
859 if (xenstore_read_fe_int(xendev
, "videoram", &videoram
) == -1)
862 rc
= common_bind(&fb
->c
);
866 fb_page
= fb
->c
.page
;
867 rc
= xenfb_configure_fb(fb
, videoram
* 1024 * 1024U,
868 fb_page
->width
, fb_page
->height
, fb_page
->depth
,
869 fb_page
->mem_length
, 0, fb_page
->line_length
);
873 rc
= xenfb_map_fb(fb
);
877 #if 0 /* handled in xen_init_display() for now */
878 if (!fb
->have_console
) {
879 fb
->c
.ds
= graphic_console_init(xenfb_update
,
884 fb
->have_console
= 1;
888 if (xenstore_read_fe_int(xendev
, "feature-update", &fb
->feature_update
) == -1)
889 fb
->feature_update
= 0;
890 if (fb
->feature_update
)
891 xenstore_write_be_int(xendev
, "request-update", 1);
893 xen_be_printf(xendev
, 1, "feature-update=%d, videoram=%d\n",
894 fb
->feature_update
, videoram
);
898 static void fb_disconnect(struct XenDevice
*xendev
)
900 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
903 * FIXME: qemu can't un-init gfx display (yet?).
904 * Replacing the framebuffer with anonymous shared memory
905 * instead. This releases the guest pages and keeps qemu happy.
907 fb
->pixels
= mmap(fb
->pixels
, fb
->fbpages
* XC_PAGE_SIZE
,
908 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
,
910 if (fb
->pixels
== MAP_FAILED
) {
911 xen_be_printf(xendev
, 0,
912 "Couldn't replace the framebuffer with anonymous memory errno=%d\n",
915 common_unbind(&fb
->c
);
916 fb
->feature_update
= 0;
920 static void fb_frontend_changed(struct XenDevice
*xendev
, const char *node
)
922 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
925 * Set state to Connected *again* once the frontend switched
926 * to connected. We must trigger the watch a second time to
927 * workaround a frontend bug.
929 if (fb
->bug_trigger
== 0 && strcmp(node
, "state") == 0 &&
930 xendev
->fe_state
== XenbusStateConnected
&&
931 xendev
->be_state
== XenbusStateConnected
) {
932 xen_be_printf(xendev
, 2, "re-trigger connected (frontend bug)\n");
933 xen_be_set_state(xendev
, XenbusStateConnected
);
934 fb
->bug_trigger
= 1; /* only once */
938 static void fb_event(struct XenDevice
*xendev
)
940 struct XenFB
*xenfb
= container_of(xendev
, struct XenFB
, c
.xendev
);
942 xenfb_handle_events(xenfb
);
943 xen_be_send_notify(&xenfb
->c
.xendev
);
946 /* -------------------------------------------------------------------- */
948 struct XenDevOps xen_kbdmouse_ops
= {
949 .size
= sizeof(struct XenInput
),
951 .initialise
= input_initialise
,
952 .connected
= input_connected
,
953 .disconnect
= input_disconnect
,
954 .event
= input_event
,
957 struct XenDevOps xen_framebuffer_ops
= {
958 .size
= sizeof(struct XenFB
),
960 .initialise
= fb_initialise
,
961 .disconnect
= fb_disconnect
,
963 .frontend_changed
= fb_frontend_changed
,
966 static const GraphicHwOps xenfb_ops
= {
967 .invalidate
= xenfb_invalidate
,
968 .gfx_update
= xenfb_update
,
969 .update_interval
= xenfb_update_interval
,
973 * FIXME/TODO: Kill this.
974 * Temporary needed while DisplayState reorganization is in flight.
976 void xen_init_display(int domid
)
978 struct XenDevice
*xfb
, *xin
;
985 main_loop_wait(true);
986 xfb
= xen_be_find_xendev("vfb", domid
, 0);
987 xin
= xen_be_find_xendev("vkbd", domid
, 0);
993 xen_be_printf(NULL
, 1, "displaystate setup failed\n");
998 fb
= container_of(xfb
, struct XenFB
, c
.xendev
);
999 fb
->c
.con
= graphic_console_init(NULL
, 0, &xenfb_ops
, fb
);
1000 fb
->have_console
= 1;
1003 in
= container_of(xin
, struct XenInput
, c
.xendev
);
1004 in
->c
.con
= fb
->c
.con
;
1006 /* retry ->init() */
1007 xen_be_check_state(xin
);
1008 xen_be_check_state(xfb
);