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>
40 #include <xen/event_channel.h>
41 #include <xen/io/xenbus.h>
42 #include <xen/io/fbif.h>
43 #include <xen/io/kbdif.h>
44 #include <xen/io/protocols.h>
48 #include "qemu-char.h"
49 #include "xen_backend.h"
52 #define BTN_LEFT 0x110 /* from <linux/input.h> */
55 /* -------------------------------------------------------------------- */
58 struct XenDevice xendev
; /* must be first */
65 int abs_pointer_wanted
; /* Whether guest supports absolute pointer */
66 int button_state
; /* Last seen pointer button state */
68 QEMUPutMouseEntry
*qmouse
;
96 /* -------------------------------------------------------------------- */
98 static int common_bind(struct common
*c
)
102 if (xenstore_read_fe_int(&c
->xendev
, "page-ref", &mfn
) == -1)
104 if (xenstore_read_fe_int(&c
->xendev
, "event-channel", &c
->xendev
.remote_port
) == -1)
107 c
->page
= xc_map_foreign_range(xen_xc
, c
->xendev
.dom
,
109 PROT_READ
| PROT_WRITE
, mfn
);
113 xen_be_bind_evtchn(&c
->xendev
);
114 xen_be_printf(&c
->xendev
, 1, "ring mfn %d, remote-port %d, local-port %d\n",
115 mfn
, c
->xendev
.remote_port
, c
->xendev
.local_port
);
120 static void common_unbind(struct common
*c
)
122 xen_be_unbind_evtchn(&c
->xendev
);
124 munmap(c
->page
, XC_PAGE_SIZE
);
129 /* -------------------------------------------------------------------- */
133 * These two tables are not needed any more, but left in here
134 * intentionally as documentation, to show how scancode2linux[]
137 * Tables to map from scancode to Linux input layer keycode.
138 * Scancodes are hardware-specific. These maps assumes a
139 * standard AT or PS/2 keyboard which is what QEMU feeds us.
141 const unsigned char atkbd_set2_keycode
[512] = {
143 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
144 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
145 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
146 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
147 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
148 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
149 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
150 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
153 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
154 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
155 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
156 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
157 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
158 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
159 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
163 const unsigned char atkbd_unxlate_table
[128] = {
165 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
166 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
167 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
168 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
169 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
170 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
171 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
172 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
178 * for (i = 0; i < 128; i++) {
179 * scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
180 * scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
183 static const unsigned char scancode2linux
[512] = {
184 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
185 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
186 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
187 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
188 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
189 80, 81, 82, 83, 99, 0, 86, 87, 88,117, 0, 0, 95,183,184,185,
190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191 93, 0, 0, 89, 0, 0, 85, 91, 90, 92, 0, 94, 0,124,121, 0,
193 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
194 165, 0, 0, 0, 0, 0, 0, 0, 0,163, 0, 0, 96, 97, 0, 0,
195 113,140,164, 0,166, 0, 0, 0, 0, 0,255, 0, 0, 0,114, 0,
196 115, 0,150, 0, 0, 98,255, 99,100, 0, 0, 0, 0, 0, 0, 0,
197 0, 0, 0, 0, 0,119,119,102,103,104, 0,105,112,106,118,107,
198 108,109,110,111, 0, 0, 0, 0, 0, 0, 0,125,126,127,116,142,
199 0, 0, 0,143, 0,217,156,173,128,159,158,157,155,226, 0,112,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
203 /* Send an event to the keyboard frontend driver */
204 static int xenfb_kbd_event(struct XenInput
*xenfb
,
205 union xenkbd_in_event
*event
)
207 struct xenkbd_page
*page
= xenfb
->c
.page
;
210 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
215 prod
= page
->in_prod
;
216 if (prod
- page
->in_cons
== XENKBD_IN_RING_LEN
) {
221 xen_mb(); /* ensure ring space available */
222 XENKBD_IN_RING_REF(page
, prod
) = *event
;
223 xen_wmb(); /* ensure ring contents visible */
224 page
->in_prod
= prod
+ 1;
225 return xen_be_send_notify(&xenfb
->c
.xendev
);
228 /* Send a keyboard (or mouse button) event */
229 static int xenfb_send_key(struct XenInput
*xenfb
, bool down
, int keycode
)
231 union xenkbd_in_event event
;
233 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
234 event
.type
= XENKBD_TYPE_KEY
;
235 event
.key
.pressed
= down
? 1 : 0;
236 event
.key
.keycode
= keycode
;
238 return xenfb_kbd_event(xenfb
, &event
);
241 /* Send a relative mouse movement event */
242 static int xenfb_send_motion(struct XenInput
*xenfb
,
243 int rel_x
, int rel_y
, int rel_z
)
245 union xenkbd_in_event event
;
247 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
248 event
.type
= XENKBD_TYPE_MOTION
;
249 event
.motion
.rel_x
= rel_x
;
250 event
.motion
.rel_y
= rel_y
;
251 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
252 event
.motion
.rel_z
= rel_z
;
255 return xenfb_kbd_event(xenfb
, &event
);
258 /* Send an absolute mouse movement event */
259 static int xenfb_send_position(struct XenInput
*xenfb
,
260 int abs_x
, int abs_y
, int z
)
262 union xenkbd_in_event event
;
264 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
265 event
.type
= XENKBD_TYPE_POS
;
266 event
.pos
.abs_x
= abs_x
;
267 event
.pos
.abs_y
= abs_y
;
268 #if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207
271 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208
275 return xenfb_kbd_event(xenfb
, &event
);
279 * Send a key event from the client to the guest OS
280 * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
281 * We have to turn this into a Linux Input layer keycode.
283 * Extra complexity from the fact that with extended scancodes
284 * (like those produced by arrow keys) this method gets called
285 * twice, but we only want to send a single event. So we have to
286 * track the '0xe0' scancode state & collapse the extended keys
289 * Wish we could just send scancodes straight to the guest which
290 * already has code for dealing with this...
292 static void xenfb_key_event(void *opaque
, int scancode
)
294 struct XenInput
*xenfb
= opaque
;
297 if (scancode
== 0xe0) {
300 } else if (scancode
& 0x80) {
304 if (xenfb
->extended
) {
308 xenfb_send_key(xenfb
, down
, scancode2linux
[scancode
]);
312 * Send a mouse event from the client to the guest OS
314 * The QEMU mouse can be in either relative, or absolute mode.
315 * Movement is sent separately from button state, which has to
316 * be encoded as virtual key events. We also don't actually get
317 * given any button up/down events, so have to track changes in
320 static void xenfb_mouse_event(void *opaque
,
321 int dx
, int dy
, int dz
, int button_state
)
323 struct XenInput
*xenfb
= opaque
;
324 int dw
= ds_get_width(xenfb
->c
.ds
);
325 int dh
= ds_get_height(xenfb
->c
.ds
);
328 if (xenfb
->abs_pointer_wanted
)
329 xenfb_send_position(xenfb
,
330 dx
* (dw
- 1) / 0x7fff,
331 dy
* (dh
- 1) / 0x7fff,
334 xenfb_send_motion(xenfb
, dx
, dy
, dz
);
336 for (i
= 0 ; i
< 8 ; i
++) {
337 int lastDown
= xenfb
->button_state
& (1 << i
);
338 int down
= button_state
& (1 << i
);
339 if (down
== lastDown
)
342 if (xenfb_send_key(xenfb
, down
, BTN_LEFT
+i
) < 0)
345 xenfb
->button_state
= button_state
;
348 static int input_init(struct XenDevice
*xendev
)
350 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
353 xen_be_printf(xendev
, 1, "ds not set (yet)\n");
357 xenstore_write_be_int(xendev
, "feature-abs-pointer", 1);
361 static int input_connect(struct XenDevice
*xendev
)
363 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
366 if (xenstore_read_fe_int(xendev
, "request-abs-pointer",
367 &in
->abs_pointer_wanted
) == -1)
368 in
->abs_pointer_wanted
= 0;
370 rc
= common_bind(&in
->c
);
374 qemu_add_kbd_event_handler(xenfb_key_event
, in
);
375 in
->qmouse
= qemu_add_mouse_event_handler(xenfb_mouse_event
, in
,
376 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_be_send_notify(&xenfb
->c
.xendev
);
405 /* -------------------------------------------------------------------- */
407 static void xenfb_copy_mfns(int mode
, int count
, unsigned long *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 unsigned long *pgmfns
= NULL
;
423 unsigned long *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
= (xenfb
->fb_len
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
478 n_fbdirs
= xenfb
->fbpages
* mode
/ 8;
479 n_fbdirs
= (n_fbdirs
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
481 pgmfns
= qemu_mallocz(sizeof(unsigned long) * n_fbdirs
);
482 fbmfns
= qemu_mallocz(sizeof(unsigned long) * xenfb
->fbpages
);
484 xenfb_copy_mfns(mode
, n_fbdirs
, pgmfns
, pd
);
485 map
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
486 PROT_READ
, pgmfns
, n_fbdirs
);
489 xenfb_copy_mfns(mode
, xenfb
->fbpages
, fbmfns
, map
);
490 munmap(map
, n_fbdirs
* XC_PAGE_SIZE
);
492 xenfb
->pixels
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
493 PROT_READ
| PROT_WRITE
, fbmfns
, xenfb
->fbpages
);
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_be_printf(&xenfb
->c
.xendev
, 0, "fb size limit %zu exceeds %zu, corrected\n",
517 fb_len_lim
, fb_len_max
);
518 fb_len_lim
= fb_len_max
;
520 if (fb_len_lim
&& fb_len
> fb_len_lim
) {
521 xen_be_printf(&xenfb
->c
.xendev
, 0, "frontend fb size %zu limited to %zu\n",
525 if (depth
!= 8 && depth
!= 16 && depth
!= 24 && depth
!= 32) {
526 xen_be_printf(&xenfb
->c
.xendev
, 0, "can't handle frontend fb depth %d\n",
530 if (row_stride
<= 0 || row_stride
> fb_len
) {
531 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend stride %d\n", row_stride
);
534 max_width
= row_stride
/ (depth
/ 8);
535 if (width
< 0 || width
> max_width
) {
536 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend width %d limited to %d\n",
540 if (offset
< 0 || offset
>= fb_len
) {
541 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend offset %d (max %zu)\n",
545 max_height
= (fb_len
- offset
) / row_stride
;
546 if (height
< 0 || height
> max_height
) {
547 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend height %d limited to %d\n",
551 xenfb
->fb_len
= fb_len
;
552 xenfb
->row_stride
= row_stride
;
553 xenfb
->depth
= depth
;
554 xenfb
->width
= width
;
555 xenfb
->height
= height
;
556 xenfb
->offset
= offset
;
557 xenfb
->up_fullscreen
= 1;
558 xenfb
->do_resize
= 1;
559 xen_be_printf(&xenfb
->c
.xendev
, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
560 width
, height
, depth
, offset
, row_stride
);
564 /* A convenient function for munging pixels between different depths */
565 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \
566 for (line = y ; line < (y+h) ; line++) { \
567 SRC_T *src = (SRC_T *)(xenfb->pixels \
569 + (line * xenfb->row_stride) \
570 + (x * xenfb->depth / 8)); \
571 DST_T *dst = (DST_T *)(data \
572 + (line * linesize) \
575 const int RSS = 32 - (RSB + GSB + BSB); \
576 const int GSS = 32 - (GSB + BSB); \
577 const int BSS = 32 - (BSB); \
578 const uint32_t RSM = (~0U) << (32 - RSB); \
579 const uint32_t GSM = (~0U) << (32 - GSB); \
580 const uint32_t BSM = (~0U) << (32 - BSB); \
581 const int RDS = 32 - (RDB + GDB + BDB); \
582 const int GDS = 32 - (GDB + BDB); \
583 const int BDS = 32 - (BDB); \
584 const uint32_t RDM = (~0U) << (32 - RDB); \
585 const uint32_t GDM = (~0U) << (32 - GDB); \
586 const uint32_t BDM = (~0U) << (32 - BDB); \
587 for (col = x ; col < (x+w) ; col++) { \
588 uint32_t spix = *src; \
589 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \
590 (((spix << GSS) & GSM & GDM) >> GDS) | \
591 (((spix << BSS) & BSM & BDM) >> BDS); \
592 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \
593 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \
599 * This copies data from the guest framebuffer region, into QEMU's
600 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer
601 * uses something else we must convert and copy, otherwise we can
602 * supply the buffer directly and no thing here.
604 static void xenfb_guest_copy(struct XenFB
*xenfb
, int x
, int y
, int w
, int h
)
607 int bpp
= ds_get_bits_per_pixel(xenfb
->c
.ds
);
608 int linesize
= ds_get_linesize(xenfb
->c
.ds
);
609 uint8_t *data
= ds_get_data(xenfb
->c
.ds
);
611 if (!is_buffer_shared(xenfb
->c
.ds
->surface
)) {
612 switch (xenfb
->depth
) {
615 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5);
616 } else if (bpp
== 32) {
617 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8);
624 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5);
625 } else if (bpp
== 32) {
626 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8);
635 if (oops
) /* should not happen */
636 xen_be_printf(&xenfb
->c
.xendev
, 0, "%s: oops: convert %d -> %d bpp?\n",
637 __FUNCTION__
, xenfb
->depth
, bpp
);
639 dpy_update(xenfb
->c
.ds
, x
, y
, w
, h
);
642 #ifdef XENFB_TYPE_REFRESH_PERIOD
643 static int xenfb_queue_full(struct XenFB
*xenfb
)
645 struct xenfb_page
*page
= xenfb
->c
.page
;
651 prod
= page
->in_prod
;
652 cons
= page
->in_cons
;
653 return prod
- cons
== XENFB_IN_RING_LEN
;
656 static void xenfb_send_event(struct XenFB
*xenfb
, union xenfb_in_event
*event
)
659 struct xenfb_page
*page
= xenfb
->c
.page
;
661 prod
= page
->in_prod
;
662 /* caller ensures !xenfb_queue_full() */
663 xen_mb(); /* ensure ring space available */
664 XENFB_IN_RING_REF(page
, prod
) = *event
;
665 xen_wmb(); /* ensure ring contents visible */
666 page
->in_prod
= prod
+ 1;
668 xen_be_send_notify(&xenfb
->c
.xendev
);
671 static void xenfb_send_refresh_period(struct XenFB
*xenfb
, int period
)
673 union xenfb_in_event event
;
675 memset(&event
, 0, sizeof(event
));
676 event
.type
= XENFB_TYPE_REFRESH_PERIOD
;
677 event
.refresh_period
.period
= period
;
678 xenfb_send_event(xenfb
, &event
);
683 * Periodic update of display.
684 * Also transmit the refresh interval to the frontend.
686 * Never ever do any qemu display operations
687 * (resize, screen update) outside this function.
688 * Our screen might be inactive. When asked for
689 * an update we know it is active.
691 static void xenfb_update(void *opaque
)
693 struct XenFB
*xenfb
= opaque
;
696 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
699 if (xenfb
->feature_update
) {
700 #ifdef XENFB_TYPE_REFRESH_PERIOD
701 struct DisplayChangeListener
*l
;
702 int period
= 99999999;
705 if (xenfb_queue_full(xenfb
))
708 for (l
= xenfb
->c
.ds
->listeners
; l
!= NULL
; l
= l
->next
) {
712 if (!l
->gui_timer_interval
) {
713 if (period
> GUI_REFRESH_INTERVAL
)
714 period
= GUI_REFRESH_INTERVAL
;
716 if (period
> l
->gui_timer_interval
)
717 period
= l
->gui_timer_interval
;
721 period
= XENFB_NO_REFRESH
;
723 if (xenfb
->refresh_period
!= period
) {
724 xenfb_send_refresh_period(xenfb
, period
);
725 xenfb
->refresh_period
= period
;
726 xen_be_printf(&xenfb
->c
.xendev
, 1, "refresh period: %d\n", period
);
732 /* we don't get update notifications, thus use the
733 * sledge hammer approach ... */
734 xenfb
->up_fullscreen
= 1;
737 /* resize if needed */
738 if (xenfb
->do_resize
) {
739 xenfb
->do_resize
= 0;
740 switch (xenfb
->depth
) {
743 /* console.c supported depth -> buffer can be used directly */
744 qemu_free_displaysurface(xenfb
->c
.ds
);
745 xenfb
->c
.ds
->surface
= qemu_create_displaysurface_from
746 (xenfb
->width
, xenfb
->height
, xenfb
->depth
,
747 xenfb
->row_stride
, xenfb
->pixels
+ xenfb
->offset
);
750 /* we must convert stuff */
751 qemu_resize_displaysurface(xenfb
->c
.ds
, xenfb
->width
, xenfb
->height
);
754 xen_be_printf(&xenfb
->c
.xendev
, 1, "update: resizing: %dx%d @ %d bpp%s\n",
755 xenfb
->width
, xenfb
->height
, xenfb
->depth
,
756 is_buffer_shared(xenfb
->c
.ds
->surface
) ? " (shared)" : "");
757 dpy_resize(xenfb
->c
.ds
);
758 xenfb
->up_fullscreen
= 1;
761 /* run queued updates */
762 if (xenfb
->up_fullscreen
) {
763 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: fullscreen\n");
764 xenfb_guest_copy(xenfb
, 0, 0, xenfb
->width
, xenfb
->height
);
765 } else if (xenfb
->up_count
) {
766 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: %d rects\n", xenfb
->up_count
);
767 for (i
= 0; i
< xenfb
->up_count
; i
++)
768 xenfb_guest_copy(xenfb
,
769 xenfb
->up_rects
[i
].x
,
770 xenfb
->up_rects
[i
].y
,
771 xenfb
->up_rects
[i
].w
,
772 xenfb
->up_rects
[i
].h
);
774 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: nothing\n");
777 xenfb
->up_fullscreen
= 0;
780 /* QEMU display state changed, so refresh the framebuffer copy */
781 static void xenfb_invalidate(void *opaque
)
783 struct XenFB
*xenfb
= opaque
;
784 xenfb
->up_fullscreen
= 1;
787 static void xenfb_handle_events(struct XenFB
*xenfb
)
790 struct xenfb_page
*page
= xenfb
->c
.page
;
792 prod
= page
->out_prod
;
793 if (prod
== page
->out_cons
)
795 xen_rmb(); /* ensure we see ring contents up to prod */
796 for (cons
= page
->out_cons
; cons
!= prod
; cons
++) {
797 union xenfb_out_event
*event
= &XENFB_OUT_RING_REF(page
, cons
);
800 switch (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_be_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_be_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 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
855 fb
->refresh_period
= -1;
857 #ifdef XENFB_TYPE_RESIZE
858 xenstore_write_be_int(xendev
, "feature-resize", 1);
863 static int fb_connect(struct XenDevice
*xendev
)
865 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
866 struct xenfb_page
*fb_page
;
870 if (xenstore_read_fe_int(xendev
, "videoram", &videoram
) == -1)
873 rc
= common_bind(&fb
->c
);
877 fb_page
= fb
->c
.page
;
878 rc
= xenfb_configure_fb(fb
, videoram
* 1024 * 1024U,
879 fb_page
->width
, fb_page
->height
, fb_page
->depth
,
880 fb_page
->mem_length
, 0, fb_page
->line_length
);
884 rc
= xenfb_map_fb(fb
);
888 #if 0 /* handled in xen_init_display() for now */
889 if (!fb
->have_console
) {
890 fb
->c
.ds
= graphic_console_init(xenfb_update
,
895 fb
->have_console
= 1;
899 if (xenstore_read_fe_int(xendev
, "feature-update", &fb
->feature_update
) == -1)
900 fb
->feature_update
= 0;
901 if (fb
->feature_update
)
902 xenstore_write_be_int(xendev
, "request-update", 1);
904 xen_be_printf(xendev
, 1, "feature-update=%d, videoram=%d\n",
905 fb
->feature_update
, videoram
);
909 static void fb_disconnect(struct XenDevice
*xendev
)
911 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
914 * FIXME: qemu can't un-init gfx display (yet?).
915 * Replacing the framebuffer with anonymous shared memory
916 * instead. This releases the guest pages and keeps qemu happy.
918 fb
->pixels
= mmap(fb
->pixels
, fb
->fbpages
* XC_PAGE_SIZE
,
919 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
,
921 common_unbind(&fb
->c
);
922 fb
->feature_update
= 0;
926 static void fb_frontend_changed(struct XenDevice
*xendev
, const char *node
)
928 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
931 * Set state to Connected *again* once the frontend switched
932 * to connected. We must trigger the watch a second time to
933 * workaround a frontend bug.
935 if (fb
->bug_trigger
== 0 && strcmp(node
, "state") == 0 &&
936 xendev
->fe_state
== XenbusStateConnected
&&
937 xendev
->be_state
== XenbusStateConnected
) {
938 xen_be_printf(xendev
, 2, "re-trigger connected (frontend bug)\n");
939 xen_be_set_state(xendev
, XenbusStateConnected
);
940 fb
->bug_trigger
= 1; /* only once */
944 static void fb_event(struct XenDevice
*xendev
)
946 struct XenFB
*xenfb
= container_of(xendev
, struct XenFB
, c
.xendev
);
948 xenfb_handle_events(xenfb
);
949 xen_be_send_notify(&xenfb
->c
.xendev
);
952 /* -------------------------------------------------------------------- */
954 struct XenDevOps xen_kbdmouse_ops
= {
955 .size
= sizeof(struct XenInput
),
957 .connect
= input_connect
,
958 .disconnect
= input_disconnect
,
959 .event
= input_event
,
962 struct XenDevOps xen_framebuffer_ops
= {
963 .size
= sizeof(struct XenFB
),
965 .connect
= fb_connect
,
966 .disconnect
= fb_disconnect
,
968 .frontend_changed
= fb_frontend_changed
,
972 * FIXME/TODO: Kill this.
973 * Temporary needed while DisplayState reorganization is in flight.
975 void xen_init_display(int domid
)
977 struct XenDevice
*xfb
, *xin
;
984 main_loop_wait(true);
985 xfb
= xen_be_find_xendev("vfb", domid
, 0);
986 xin
= xen_be_find_xendev("vkbd", domid
, 0);
992 xen_be_printf(NULL
, 1, "displaystate setup failed\n");
997 fb
= container_of(xfb
, struct XenFB
, c
.xendev
);
998 fb
->c
.ds
= graphic_console_init(xenfb_update
,
1003 fb
->have_console
= 1;
1006 in
= container_of(xin
, struct XenInput
, c
.xendev
);
1007 in
->c
.ds
= fb
->c
.ds
;
1009 /* retry ->init() */
1010 xen_be_check_state(xin
);
1011 xen_be_check_state(xfb
);