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>
49 #include "qemu-char.h"
50 #include "xen_backend.h"
53 #define BTN_LEFT 0x110 /* from <linux/input.h> */
56 /* -------------------------------------------------------------------- */
59 struct XenDevice xendev
; /* must be first */
66 int abs_pointer_wanted
; /* Whether guest supports absolute pointer */
67 int button_state
; /* Last seen pointer button state */
69 QEMUPutMouseEntry
*qmouse
;
97 /* -------------------------------------------------------------------- */
99 static int common_bind(struct common
*c
)
103 if (xenstore_read_fe_int(&c
->xendev
, "page-ref", &mfn
) == -1)
105 if (xenstore_read_fe_int(&c
->xendev
, "event-channel", &c
->xendev
.remote_port
) == -1)
108 c
->page
= xc_map_foreign_range(xen_xc
, c
->xendev
.dom
,
110 PROT_READ
| PROT_WRITE
, mfn
);
114 xen_be_bind_evtchn(&c
->xendev
);
115 xen_be_printf(&c
->xendev
, 1, "ring mfn %d, remote-port %d, local-port %d\n",
116 mfn
, c
->xendev
.remote_port
, c
->xendev
.local_port
);
121 static void common_unbind(struct common
*c
)
123 xen_be_unbind_evtchn(&c
->xendev
);
125 munmap(c
->page
, XC_PAGE_SIZE
);
130 /* -------------------------------------------------------------------- */
134 * These two tables are not needed any more, but left in here
135 * intentionally as documentation, to show how scancode2linux[]
138 * Tables to map from scancode to Linux input layer keycode.
139 * Scancodes are hardware-specific. These maps assumes a
140 * standard AT or PS/2 keyboard which is what QEMU feeds us.
142 const unsigned char atkbd_set2_keycode
[512] = {
144 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
145 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
146 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
147 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
148 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
149 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
150 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
151 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
154 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
155 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
156 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
157 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
158 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
159 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
160 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
164 const unsigned char atkbd_unxlate_table
[128] = {
166 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
167 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
168 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
169 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
170 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
171 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
172 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
173 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
179 * for (i = 0; i < 128; i++) {
180 * scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
181 * scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
184 static const unsigned char scancode2linux
[512] = {
185 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
186 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
187 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
188 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
189 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
190 80, 81, 82, 83, 99, 0, 86, 87, 88,117, 0, 0, 95,183,184,185,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 93, 0, 0, 89, 0, 0, 85, 91, 90, 92, 0, 94, 0,124,121, 0,
194 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
195 165, 0, 0, 0, 0, 0, 0, 0, 0,163, 0, 0, 96, 97, 0, 0,
196 113,140,164, 0,166, 0, 0, 0, 0, 0,255, 0, 0, 0,114, 0,
197 115, 0,150, 0, 0, 98,255, 99,100, 0, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0,119,119,102,103,104, 0,105,112,106,118,107,
199 108,109,110,111, 0, 0, 0, 0, 0, 0, 0,125,126,127,116,142,
200 0, 0, 0,143, 0,217,156,173,128,159,158,157,155,226, 0,112,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 /* Send an event to the keyboard frontend driver */
205 static int xenfb_kbd_event(struct XenInput
*xenfb
,
206 union xenkbd_in_event
*event
)
208 struct xenkbd_page
*page
= xenfb
->c
.page
;
211 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
216 prod
= page
->in_prod
;
217 if (prod
- page
->in_cons
== XENKBD_IN_RING_LEN
) {
222 xen_mb(); /* ensure ring space available */
223 XENKBD_IN_RING_REF(page
, prod
) = *event
;
224 xen_wmb(); /* ensure ring contents visible */
225 page
->in_prod
= prod
+ 1;
226 return xen_be_send_notify(&xenfb
->c
.xendev
);
229 /* Send a keyboard (or mouse button) event */
230 static int xenfb_send_key(struct XenInput
*xenfb
, bool down
, int keycode
)
232 union xenkbd_in_event event
;
234 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
235 event
.type
= XENKBD_TYPE_KEY
;
236 event
.key
.pressed
= down
? 1 : 0;
237 event
.key
.keycode
= keycode
;
239 return xenfb_kbd_event(xenfb
, &event
);
242 /* Send a relative mouse movement event */
243 static int xenfb_send_motion(struct XenInput
*xenfb
,
244 int rel_x
, int rel_y
, int rel_z
)
246 union xenkbd_in_event event
;
248 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
249 event
.type
= XENKBD_TYPE_MOTION
;
250 event
.motion
.rel_x
= rel_x
;
251 event
.motion
.rel_y
= rel_y
;
252 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207
253 event
.motion
.rel_z
= rel_z
;
256 return xenfb_kbd_event(xenfb
, &event
);
259 /* Send an absolute mouse movement event */
260 static int xenfb_send_position(struct XenInput
*xenfb
,
261 int abs_x
, int abs_y
, int z
)
263 union xenkbd_in_event event
;
265 memset(&event
, 0, XENKBD_IN_EVENT_SIZE
);
266 event
.type
= XENKBD_TYPE_POS
;
267 event
.pos
.abs_x
= abs_x
;
268 event
.pos
.abs_y
= abs_y
;
269 #if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207
272 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208
276 return xenfb_kbd_event(xenfb
, &event
);
280 * Send a key event from the client to the guest OS
281 * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
282 * We have to turn this into a Linux Input layer keycode.
284 * Extra complexity from the fact that with extended scancodes
285 * (like those produced by arrow keys) this method gets called
286 * twice, but we only want to send a single event. So we have to
287 * track the '0xe0' scancode state & collapse the extended keys
290 * Wish we could just send scancodes straight to the guest which
291 * already has code for dealing with this...
293 static void xenfb_key_event(void *opaque
, int scancode
)
295 struct XenInput
*xenfb
= opaque
;
298 if (scancode
== 0xe0) {
301 } else if (scancode
& 0x80) {
305 if (xenfb
->extended
) {
309 xenfb_send_key(xenfb
, down
, scancode2linux
[scancode
]);
313 * Send a mouse event from the client to the guest OS
315 * The QEMU mouse can be in either relative, or absolute mode.
316 * Movement is sent separately from button state, which has to
317 * be encoded as virtual key events. We also don't actually get
318 * given any button up/down events, so have to track changes in
321 static void xenfb_mouse_event(void *opaque
,
322 int dx
, int dy
, int dz
, int button_state
)
324 struct XenInput
*xenfb
= opaque
;
325 int dw
= ds_get_width(xenfb
->c
.ds
);
326 int dh
= ds_get_height(xenfb
->c
.ds
);
329 if (xenfb
->abs_pointer_wanted
)
330 xenfb_send_position(xenfb
,
331 dx
* (dw
- 1) / 0x7fff,
332 dy
* (dh
- 1) / 0x7fff,
335 xenfb_send_motion(xenfb
, dx
, dy
, dz
);
337 for (i
= 0 ; i
< 8 ; i
++) {
338 int lastDown
= xenfb
->button_state
& (1 << i
);
339 int down
= button_state
& (1 << i
);
340 if (down
== lastDown
)
343 if (xenfb_send_key(xenfb
, down
, BTN_LEFT
+i
) < 0)
346 xenfb
->button_state
= button_state
;
349 static int input_init(struct XenDevice
*xendev
)
351 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
354 xen_be_printf(xendev
, 1, "ds not set (yet)\n");
358 xenstore_write_be_int(xendev
, "feature-abs-pointer", 1);
362 static int input_connect(struct XenDevice
*xendev
)
364 struct XenInput
*in
= container_of(xendev
, struct XenInput
, c
.xendev
);
367 if (xenstore_read_fe_int(xendev
, "request-abs-pointer",
368 &in
->abs_pointer_wanted
) == -1)
369 in
->abs_pointer_wanted
= 0;
371 rc
= common_bind(&in
->c
);
375 qemu_add_kbd_event_handler(xenfb_key_event
, in
);
376 in
->qmouse
= qemu_add_mouse_event_handler(xenfb_mouse_event
, in
,
377 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_be_send_notify(&xenfb
->c
.xendev
);
406 /* -------------------------------------------------------------------- */
408 static void xenfb_copy_mfns(int mode
, int count
, unsigned long *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 unsigned long *pgmfns
= NULL
;
424 unsigned long *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
= (xenfb
->fb_len
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
479 n_fbdirs
= xenfb
->fbpages
* mode
/ 8;
480 n_fbdirs
= (n_fbdirs
+ (XC_PAGE_SIZE
- 1)) / XC_PAGE_SIZE
;
482 pgmfns
= qemu_mallocz(sizeof(unsigned long) * n_fbdirs
);
483 fbmfns
= qemu_mallocz(sizeof(unsigned long) * xenfb
->fbpages
);
485 xenfb_copy_mfns(mode
, n_fbdirs
, pgmfns
, pd
);
486 map
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
487 PROT_READ
, pgmfns
, n_fbdirs
);
490 xenfb_copy_mfns(mode
, xenfb
->fbpages
, fbmfns
, map
);
491 munmap(map
, n_fbdirs
* XC_PAGE_SIZE
);
493 xenfb
->pixels
= xc_map_foreign_pages(xen_xc
, xenfb
->c
.xendev
.dom
,
494 PROT_READ
| PROT_WRITE
, fbmfns
, xenfb
->fbpages
);
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_be_printf(&xenfb
->c
.xendev
, 0, "fb size limit %zu exceeds %zu, corrected\n",
518 fb_len_lim
, fb_len_max
);
519 fb_len_lim
= fb_len_max
;
521 if (fb_len_lim
&& fb_len
> fb_len_lim
) {
522 xen_be_printf(&xenfb
->c
.xendev
, 0, "frontend fb size %zu limited to %zu\n",
526 if (depth
!= 8 && depth
!= 16 && depth
!= 24 && depth
!= 32) {
527 xen_be_printf(&xenfb
->c
.xendev
, 0, "can't handle frontend fb depth %d\n",
531 if (row_stride
<= 0 || row_stride
> fb_len
) {
532 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend stride %d\n", row_stride
);
535 max_width
= row_stride
/ (depth
/ 8);
536 if (width
< 0 || width
> max_width
) {
537 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend width %d limited to %d\n",
541 if (offset
< 0 || offset
>= fb_len
) {
542 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend offset %d (max %zu)\n",
546 max_height
= (fb_len
- offset
) / row_stride
;
547 if (height
< 0 || height
> max_height
) {
548 xen_be_printf(&xenfb
->c
.xendev
, 0, "invalid frontend height %d limited to %d\n",
552 xenfb
->fb_len
= fb_len
;
553 xenfb
->row_stride
= row_stride
;
554 xenfb
->depth
= depth
;
555 xenfb
->width
= width
;
556 xenfb
->height
= height
;
557 xenfb
->offset
= offset
;
558 xenfb
->up_fullscreen
= 1;
559 xenfb
->do_resize
= 1;
560 xen_be_printf(&xenfb
->c
.xendev
, 1, "framebuffer %dx%dx%d offset %d stride %d\n",
561 width
, height
, depth
, offset
, row_stride
);
565 /* A convenient function for munging pixels between different depths */
566 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \
567 for (line = y ; line < (y+h) ; line++) { \
568 SRC_T *src = (SRC_T *)(xenfb->pixels \
570 + (line * xenfb->row_stride) \
571 + (x * xenfb->depth / 8)); \
572 DST_T *dst = (DST_T *)(data \
573 + (line * linesize) \
576 const int RSS = 32 - (RSB + GSB + BSB); \
577 const int GSS = 32 - (GSB + BSB); \
578 const int BSS = 32 - (BSB); \
579 const uint32_t RSM = (~0U) << (32 - RSB); \
580 const uint32_t GSM = (~0U) << (32 - GSB); \
581 const uint32_t BSM = (~0U) << (32 - BSB); \
582 const int RDS = 32 - (RDB + GDB + BDB); \
583 const int GDS = 32 - (GDB + BDB); \
584 const int BDS = 32 - (BDB); \
585 const uint32_t RDM = (~0U) << (32 - RDB); \
586 const uint32_t GDM = (~0U) << (32 - GDB); \
587 const uint32_t BDM = (~0U) << (32 - BDB); \
588 for (col = x ; col < (x+w) ; col++) { \
589 uint32_t spix = *src; \
590 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \
591 (((spix << GSS) & GSM & GDM) >> GDS) | \
592 (((spix << BSS) & BSM & BDM) >> BDS); \
593 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \
594 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \
600 * This copies data from the guest framebuffer region, into QEMU's
601 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer
602 * uses something else we must convert and copy, otherwise we can
603 * supply the buffer directly and no thing here.
605 static void xenfb_guest_copy(struct XenFB
*xenfb
, int x
, int y
, int w
, int h
)
608 int bpp
= ds_get_bits_per_pixel(xenfb
->c
.ds
);
609 int linesize
= ds_get_linesize(xenfb
->c
.ds
);
610 uint8_t *data
= ds_get_data(xenfb
->c
.ds
);
612 if (!is_buffer_shared(xenfb
->c
.ds
->surface
)) {
613 switch (xenfb
->depth
) {
616 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5);
617 } else if (bpp
== 32) {
618 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8);
625 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5);
626 } else if (bpp
== 32) {
627 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8);
636 if (oops
) /* should not happen */
637 xen_be_printf(&xenfb
->c
.xendev
, 0, "%s: oops: convert %d -> %d bpp?\n",
638 __FUNCTION__
, xenfb
->depth
, bpp
);
640 dpy_update(xenfb
->c
.ds
, x
, y
, w
, h
);
643 #ifdef XENFB_TYPE_REFRESH_PERIOD
644 static int xenfb_queue_full(struct XenFB
*xenfb
)
646 struct xenfb_page
*page
= xenfb
->c
.page
;
652 prod
= page
->in_prod
;
653 cons
= page
->in_cons
;
654 return prod
- cons
== XENFB_IN_RING_LEN
;
657 static void xenfb_send_event(struct XenFB
*xenfb
, union xenfb_in_event
*event
)
660 struct xenfb_page
*page
= xenfb
->c
.page
;
662 prod
= page
->in_prod
;
663 /* caller ensures !xenfb_queue_full() */
664 xen_mb(); /* ensure ring space available */
665 XENFB_IN_RING_REF(page
, prod
) = *event
;
666 xen_wmb(); /* ensure ring contents visible */
667 page
->in_prod
= prod
+ 1;
669 xen_be_send_notify(&xenfb
->c
.xendev
);
672 static void xenfb_send_refresh_period(struct XenFB
*xenfb
, int period
)
674 union xenfb_in_event event
;
676 memset(&event
, 0, sizeof(event
));
677 event
.type
= XENFB_TYPE_REFRESH_PERIOD
;
678 event
.refresh_period
.period
= period
;
679 xenfb_send_event(xenfb
, &event
);
684 * Periodic update of display.
685 * Also transmit the refresh interval to the frontend.
687 * Never ever do any qemu display operations
688 * (resize, screen update) outside this function.
689 * Our screen might be inactive. When asked for
690 * an update we know it is active.
692 static void xenfb_update(void *opaque
)
694 struct XenFB
*xenfb
= opaque
;
697 if (xenfb
->c
.xendev
.be_state
!= XenbusStateConnected
)
700 if (xenfb
->feature_update
) {
701 #ifdef XENFB_TYPE_REFRESH_PERIOD
702 struct DisplayChangeListener
*l
;
703 int period
= 99999999;
706 if (xenfb_queue_full(xenfb
))
709 for (l
= xenfb
->c
.ds
->listeners
; l
!= NULL
; l
= l
->next
) {
713 if (!l
->gui_timer_interval
) {
714 if (period
> GUI_REFRESH_INTERVAL
)
715 period
= GUI_REFRESH_INTERVAL
;
717 if (period
> l
->gui_timer_interval
)
718 period
= l
->gui_timer_interval
;
722 period
= XENFB_NO_REFRESH
;
724 if (xenfb
->refresh_period
!= period
) {
725 xenfb_send_refresh_period(xenfb
, period
);
726 xenfb
->refresh_period
= period
;
727 xen_be_printf(&xenfb
->c
.xendev
, 1, "refresh period: %d\n", period
);
733 /* we don't get update notifications, thus use the
734 * sledge hammer approach ... */
735 xenfb
->up_fullscreen
= 1;
738 /* resize if needed */
739 if (xenfb
->do_resize
) {
740 xenfb
->do_resize
= 0;
741 switch (xenfb
->depth
) {
744 /* console.c supported depth -> buffer can be used directly */
745 qemu_free_displaysurface(xenfb
->c
.ds
);
746 xenfb
->c
.ds
->surface
= qemu_create_displaysurface_from
747 (xenfb
->width
, xenfb
->height
, xenfb
->depth
,
748 xenfb
->row_stride
, xenfb
->pixels
+ xenfb
->offset
);
751 /* we must convert stuff */
752 qemu_resize_displaysurface(xenfb
->c
.ds
, xenfb
->width
, xenfb
->height
);
755 xen_be_printf(&xenfb
->c
.xendev
, 1, "update: resizing: %dx%d @ %d bpp%s\n",
756 xenfb
->width
, xenfb
->height
, xenfb
->depth
,
757 is_buffer_shared(xenfb
->c
.ds
->surface
) ? " (shared)" : "");
758 dpy_resize(xenfb
->c
.ds
);
759 xenfb
->up_fullscreen
= 1;
762 /* run queued updates */
763 if (xenfb
->up_fullscreen
) {
764 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: fullscreen\n");
765 xenfb_guest_copy(xenfb
, 0, 0, xenfb
->width
, xenfb
->height
);
766 } else if (xenfb
->up_count
) {
767 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: %d rects\n", xenfb
->up_count
);
768 for (i
= 0; i
< xenfb
->up_count
; i
++)
769 xenfb_guest_copy(xenfb
,
770 xenfb
->up_rects
[i
].x
,
771 xenfb
->up_rects
[i
].y
,
772 xenfb
->up_rects
[i
].w
,
773 xenfb
->up_rects
[i
].h
);
775 xen_be_printf(&xenfb
->c
.xendev
, 3, "update: nothing\n");
778 xenfb
->up_fullscreen
= 0;
781 /* QEMU display state changed, so refresh the framebuffer copy */
782 static void xenfb_invalidate(void *opaque
)
784 struct XenFB
*xenfb
= opaque
;
785 xenfb
->up_fullscreen
= 1;
788 static void xenfb_handle_events(struct XenFB
*xenfb
)
791 struct xenfb_page
*page
= xenfb
->c
.page
;
793 prod
= page
->out_prod
;
794 if (prod
== page
->out_cons
)
796 xen_rmb(); /* ensure we see ring contents up to prod */
797 for (cons
= page
->out_cons
; cons
!= prod
; cons
++) {
798 union xenfb_out_event
*event
= &XENFB_OUT_RING_REF(page
, cons
);
801 switch (event
->type
) {
802 case XENFB_TYPE_UPDATE
:
803 if (xenfb
->up_count
== UP_QUEUE
)
804 xenfb
->up_fullscreen
= 1;
805 if (xenfb
->up_fullscreen
)
807 x
= MAX(event
->update
.x
, 0);
808 y
= MAX(event
->update
.y
, 0);
809 w
= MIN(event
->update
.width
, xenfb
->width
- x
);
810 h
= MIN(event
->update
.height
, xenfb
->height
- y
);
811 if (w
< 0 || h
< 0) {
812 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update ignored\n");
815 if (x
!= event
->update
.x
||
816 y
!= event
->update
.y
||
817 w
!= event
->update
.width
||
818 h
!= event
->update
.height
) {
819 xen_be_printf(&xenfb
->c
.xendev
, 1, "bogus update clipped\n");
821 if (w
== xenfb
->width
&& h
> xenfb
->height
/ 2) {
822 /* scroll detector: updated more than 50% of the lines,
823 * don't bother keeping track of the rectangles then */
824 xenfb
->up_fullscreen
= 1;
826 xenfb
->up_rects
[xenfb
->up_count
].x
= x
;
827 xenfb
->up_rects
[xenfb
->up_count
].y
= y
;
828 xenfb
->up_rects
[xenfb
->up_count
].w
= w
;
829 xenfb
->up_rects
[xenfb
->up_count
].h
= h
;
833 #ifdef XENFB_TYPE_RESIZE
834 case XENFB_TYPE_RESIZE
:
835 if (xenfb_configure_fb(xenfb
, xenfb
->fb_len
,
837 event
->resize
.height
,
840 event
->resize
.offset
,
841 event
->resize
.stride
) < 0)
843 xenfb_invalidate(xenfb
);
848 xen_mb(); /* ensure we're done with ring contents */
849 page
->out_cons
= cons
;
852 static int fb_init(struct XenDevice
*xendev
)
854 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
856 fb
->refresh_period
= -1;
858 #ifdef XENFB_TYPE_RESIZE
859 xenstore_write_be_int(xendev
, "feature-resize", 1);
864 static int fb_connect(struct XenDevice
*xendev
)
866 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
867 struct xenfb_page
*fb_page
;
871 if (xenstore_read_fe_int(xendev
, "videoram", &videoram
) == -1)
874 rc
= common_bind(&fb
->c
);
878 fb_page
= fb
->c
.page
;
879 rc
= xenfb_configure_fb(fb
, videoram
* 1024 * 1024U,
880 fb_page
->width
, fb_page
->height
, fb_page
->depth
,
881 fb_page
->mem_length
, 0, fb_page
->line_length
);
885 rc
= xenfb_map_fb(fb
);
889 #if 0 /* handled in xen_init_display() for now */
890 if (!fb
->have_console
) {
891 fb
->c
.ds
= graphic_console_init(xenfb_update
,
896 fb
->have_console
= 1;
900 if (xenstore_read_fe_int(xendev
, "feature-update", &fb
->feature_update
) == -1)
901 fb
->feature_update
= 0;
902 if (fb
->feature_update
)
903 xenstore_write_be_int(xendev
, "request-update", 1);
905 xen_be_printf(xendev
, 1, "feature-update=%d, videoram=%d\n",
906 fb
->feature_update
, videoram
);
910 static void fb_disconnect(struct XenDevice
*xendev
)
912 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
915 * FIXME: qemu can't un-init gfx display (yet?).
916 * Replacing the framebuffer with anonymous shared memory
917 * instead. This releases the guest pages and keeps qemu happy.
919 fb
->pixels
= mmap(fb
->pixels
, fb
->fbpages
* XC_PAGE_SIZE
,
920 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
,
922 common_unbind(&fb
->c
);
923 fb
->feature_update
= 0;
927 static void fb_frontend_changed(struct XenDevice
*xendev
, const char *node
)
929 struct XenFB
*fb
= container_of(xendev
, struct XenFB
, c
.xendev
);
932 * Set state to Connected *again* once the frontend switched
933 * to connected. We must trigger the watch a second time to
934 * workaround a frontend bug.
936 if (fb
->bug_trigger
== 0 && strcmp(node
, "state") == 0 &&
937 xendev
->fe_state
== XenbusStateConnected
&&
938 xendev
->be_state
== XenbusStateConnected
) {
939 xen_be_printf(xendev
, 2, "re-trigger connected (frontend bug)\n");
940 xen_be_set_state(xendev
, XenbusStateConnected
);
941 fb
->bug_trigger
= 1; /* only once */
945 static void fb_event(struct XenDevice
*xendev
)
947 struct XenFB
*xenfb
= container_of(xendev
, struct XenFB
, c
.xendev
);
949 xenfb_handle_events(xenfb
);
950 xen_be_send_notify(&xenfb
->c
.xendev
);
953 /* -------------------------------------------------------------------- */
955 struct XenDevOps xen_kbdmouse_ops
= {
956 .size
= sizeof(struct XenInput
),
958 .connect
= input_connect
,
959 .disconnect
= input_disconnect
,
960 .event
= input_event
,
963 struct XenDevOps xen_framebuffer_ops
= {
964 .size
= sizeof(struct XenFB
),
966 .connect
= fb_connect
,
967 .disconnect
= fb_disconnect
,
969 .frontend_changed
= fb_frontend_changed
,
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
.ds
= graphic_console_init(xenfb_update
,
1004 fb
->have_console
= 1;
1007 in
= container_of(xin
, struct XenInput
, c
.xendev
);
1008 in
->c
.ds
= fb
->c
.ds
;
1010 /* retry ->init() */
1011 xen_be_check_state(xin
);
1012 xen_be_check_state(xfb
);