2 * Xen para-virtual frame buffer device
4 * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
5 * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
7 * Based on linux/drivers/video/q40fb.c
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
17 * Switch to grant tables when they become capable of dealing with the
21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23 #include <linux/console.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/vmalloc.h>
32 #include <asm/xen/hypervisor.h>
35 #include <xen/events.h>
37 #include <xen/interface/io/fbif.h>
38 #include <xen/interface/io/protocols.h>
39 #include <xen/xenbus.h>
40 #include <xen/platform_pci.h>
44 struct fb_info
*fb_info
;
45 int x1
, y1
, x2
, y2
; /* dirty rectangle,
46 protected by dirty_lock */
47 spinlock_t dirty_lock
;
50 struct xenfb_page
*page
;
52 int update_wanted
; /* XENFB_TYPE_UPDATE wanted */
53 int feature_resize
; /* XENFB_TYPE_RESIZE ok */
54 struct xenfb_resize resize
; /* protected by resize_lock */
55 int resize_dpy
; /* ditto */
56 spinlock_t resize_lock
;
58 struct xenbus_device
*xbdev
;
61 #define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
63 enum { KPARAM_MEM
, KPARAM_WIDTH
, KPARAM_HEIGHT
, KPARAM_CNT
};
64 static int video
[KPARAM_CNT
] = { 2, XENFB_WIDTH
, XENFB_HEIGHT
};
65 module_param_array(video
, int, NULL
, 0);
66 MODULE_PARM_DESC(video
,
67 "Video memory size in MB, width, height in pixels (default 2,800,600)");
69 static void xenfb_make_preferred_console(void);
70 static int xenfb_remove(struct xenbus_device
*);
71 static void xenfb_init_shared_page(struct xenfb_info
*, struct fb_info
*);
72 static int xenfb_connect_backend(struct xenbus_device
*, struct xenfb_info
*);
73 static void xenfb_disconnect_backend(struct xenfb_info
*);
75 static void xenfb_send_event(struct xenfb_info
*info
,
76 union xenfb_out_event
*event
)
80 prod
= info
->page
->out_prod
;
81 /* caller ensures !xenfb_queue_full() */
82 mb(); /* ensure ring space available */
83 XENFB_OUT_RING_REF(info
->page
, prod
) = *event
;
84 wmb(); /* ensure ring contents visible */
85 info
->page
->out_prod
= prod
+ 1;
87 notify_remote_via_irq(info
->irq
);
90 static void xenfb_do_update(struct xenfb_info
*info
,
91 int x
, int y
, int w
, int h
)
93 union xenfb_out_event event
;
95 memset(&event
, 0, sizeof(event
));
96 event
.type
= XENFB_TYPE_UPDATE
;
99 event
.update
.width
= w
;
100 event
.update
.height
= h
;
102 /* caller ensures !xenfb_queue_full() */
103 xenfb_send_event(info
, &event
);
106 static void xenfb_do_resize(struct xenfb_info
*info
)
108 union xenfb_out_event event
;
110 memset(&event
, 0, sizeof(event
));
111 event
.resize
= info
->resize
;
113 /* caller ensures !xenfb_queue_full() */
114 xenfb_send_event(info
, &event
);
117 static int xenfb_queue_full(struct xenfb_info
*info
)
121 prod
= info
->page
->out_prod
;
122 cons
= info
->page
->out_cons
;
123 return prod
- cons
== XENFB_OUT_RING_LEN
;
126 static void xenfb_handle_resize_dpy(struct xenfb_info
*info
)
130 spin_lock_irqsave(&info
->resize_lock
, flags
);
131 if (info
->resize_dpy
) {
132 if (!xenfb_queue_full(info
)) {
133 info
->resize_dpy
= 0;
134 xenfb_do_resize(info
);
137 spin_unlock_irqrestore(&info
->resize_lock
, flags
);
140 static void xenfb_refresh(struct xenfb_info
*info
,
141 int x1
, int y1
, int w
, int h
)
147 xenfb_handle_resize_dpy(info
);
149 if (!info
->update_wanted
)
152 spin_lock_irqsave(&info
->dirty_lock
, flags
);
154 /* Combine with dirty rectangle: */
164 if (xenfb_queue_full(info
)) {
165 /* Can't send right now, stash it in the dirty rectangle */
170 spin_unlock_irqrestore(&info
->dirty_lock
, flags
);
174 /* Clear dirty rectangle: */
175 info
->x1
= info
->y1
= INT_MAX
;
176 info
->x2
= info
->y2
= 0;
178 spin_unlock_irqrestore(&info
->dirty_lock
, flags
);
180 if (x1
<= x2
&& y1
<= y2
)
181 xenfb_do_update(info
, x1
, y1
, x2
- x1
+ 1, y2
- y1
+ 1);
184 static void xenfb_deferred_io(struct fb_info
*fb_info
,
185 struct list_head
*pagelist
)
187 struct xenfb_info
*info
= fb_info
->par
;
189 unsigned long beg
, end
;
190 int y1
, y2
, miny
, maxy
;
194 list_for_each_entry(page
, pagelist
, lru
) {
195 beg
= page
->index
<< PAGE_SHIFT
;
196 end
= beg
+ PAGE_SIZE
- 1;
197 y1
= beg
/ fb_info
->fix
.line_length
;
198 y2
= end
/ fb_info
->fix
.line_length
;
199 if (y2
>= fb_info
->var
.yres
)
200 y2
= fb_info
->var
.yres
- 1;
206 xenfb_refresh(info
, 0, miny
, fb_info
->var
.xres
, maxy
- miny
+ 1);
209 static struct fb_deferred_io xenfb_defio
= {
211 .deferred_io
= xenfb_deferred_io
,
214 static int xenfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
215 unsigned blue
, unsigned transp
,
216 struct fb_info
*info
)
220 if (regno
> info
->cmap
.len
)
223 #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
224 red
= CNVT_TOHW(red
, info
->var
.red
.length
);
225 green
= CNVT_TOHW(green
, info
->var
.green
.length
);
226 blue
= CNVT_TOHW(blue
, info
->var
.blue
.length
);
227 transp
= CNVT_TOHW(transp
, info
->var
.transp
.length
);
230 v
= (red
<< info
->var
.red
.offset
) |
231 (green
<< info
->var
.green
.offset
) |
232 (blue
<< info
->var
.blue
.offset
);
234 switch (info
->var
.bits_per_pixel
) {
238 ((u32
*)info
->pseudo_palette
)[regno
] = v
;
245 static void xenfb_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
247 struct xenfb_info
*info
= p
->par
;
249 sys_fillrect(p
, rect
);
250 xenfb_refresh(info
, rect
->dx
, rect
->dy
, rect
->width
, rect
->height
);
253 static void xenfb_imageblit(struct fb_info
*p
, const struct fb_image
*image
)
255 struct xenfb_info
*info
= p
->par
;
257 sys_imageblit(p
, image
);
258 xenfb_refresh(info
, image
->dx
, image
->dy
, image
->width
, image
->height
);
261 static void xenfb_copyarea(struct fb_info
*p
, const struct fb_copyarea
*area
)
263 struct xenfb_info
*info
= p
->par
;
265 sys_copyarea(p
, area
);
266 xenfb_refresh(info
, area
->dx
, area
->dy
, area
->width
, area
->height
);
269 static ssize_t
xenfb_write(struct fb_info
*p
, const char __user
*buf
,
270 size_t count
, loff_t
*ppos
)
272 struct xenfb_info
*info
= p
->par
;
275 res
= fb_sys_write(p
, buf
, count
, ppos
);
276 xenfb_refresh(info
, 0, 0, info
->page
->width
, info
->page
->height
);
281 xenfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
283 struct xenfb_info
*xenfb_info
;
284 int required_mem_len
;
286 xenfb_info
= info
->par
;
288 if (!xenfb_info
->feature_resize
) {
289 if (var
->xres
== video
[KPARAM_WIDTH
] &&
290 var
->yres
== video
[KPARAM_HEIGHT
] &&
291 var
->bits_per_pixel
== xenfb_info
->page
->depth
) {
297 /* Can't resize past initial width and height */
298 if (var
->xres
> video
[KPARAM_WIDTH
] || var
->yres
> video
[KPARAM_HEIGHT
])
301 required_mem_len
= var
->xres
* var
->yres
* xenfb_info
->page
->depth
/ 8;
302 if (var
->bits_per_pixel
== xenfb_info
->page
->depth
&&
303 var
->xres
<= info
->fix
.line_length
/ (XENFB_DEPTH
/ 8) &&
304 required_mem_len
<= info
->fix
.smem_len
) {
305 var
->xres_virtual
= var
->xres
;
306 var
->yres_virtual
= var
->yres
;
312 static int xenfb_set_par(struct fb_info
*info
)
314 struct xenfb_info
*xenfb_info
;
317 xenfb_info
= info
->par
;
319 spin_lock_irqsave(&xenfb_info
->resize_lock
, flags
);
320 xenfb_info
->resize
.type
= XENFB_TYPE_RESIZE
;
321 xenfb_info
->resize
.width
= info
->var
.xres
;
322 xenfb_info
->resize
.height
= info
->var
.yres
;
323 xenfb_info
->resize
.stride
= info
->fix
.line_length
;
324 xenfb_info
->resize
.depth
= info
->var
.bits_per_pixel
;
325 xenfb_info
->resize
.offset
= 0;
326 xenfb_info
->resize_dpy
= 1;
327 spin_unlock_irqrestore(&xenfb_info
->resize_lock
, flags
);
331 static const struct fb_ops xenfb_fb_ops
= {
332 .owner
= THIS_MODULE
,
333 .fb_read
= fb_sys_read
,
334 .fb_write
= xenfb_write
,
335 .fb_setcolreg
= xenfb_setcolreg
,
336 .fb_fillrect
= xenfb_fillrect
,
337 .fb_copyarea
= xenfb_copyarea
,
338 .fb_imageblit
= xenfb_imageblit
,
339 .fb_check_var
= xenfb_check_var
,
340 .fb_set_par
= xenfb_set_par
,
343 static irqreturn_t
xenfb_event_handler(int rq
, void *dev_id
)
346 * No in events recognized, simply ignore them all.
347 * If you need to recognize some, see xen-kbdfront's
348 * input_handler() for how to do that.
350 struct xenfb_info
*info
= dev_id
;
351 struct xenfb_page
*page
= info
->page
;
353 if (page
->in_cons
!= page
->in_prod
) {
354 info
->page
->in_cons
= info
->page
->in_prod
;
355 notify_remote_via_irq(info
->irq
);
358 /* Flush dirty rectangle: */
359 xenfb_refresh(info
, INT_MAX
, INT_MAX
, -INT_MAX
, -INT_MAX
);
364 static int xenfb_probe(struct xenbus_device
*dev
,
365 const struct xenbus_device_id
*id
)
367 struct xenfb_info
*info
;
368 struct fb_info
*fb_info
;
373 info
= kzalloc(sizeof(*info
), GFP_KERNEL
);
375 xenbus_dev_fatal(dev
, -ENOMEM
, "allocating info structure");
379 /* Limit kernel param videoram amount to what is in xenstore */
380 if (xenbus_scanf(XBT_NIL
, dev
->otherend
, "videoram", "%d", &val
) == 1) {
381 if (val
< video
[KPARAM_MEM
])
382 video
[KPARAM_MEM
] = val
;
385 video
[KPARAM_WIDTH
] = xenbus_read_unsigned(dev
->otherend
, "width",
386 video
[KPARAM_WIDTH
]);
387 video
[KPARAM_HEIGHT
] = xenbus_read_unsigned(dev
->otherend
, "height",
388 video
[KPARAM_HEIGHT
]);
390 /* If requested res does not fit in available memory, use default */
391 fb_size
= video
[KPARAM_MEM
] * 1024 * 1024;
392 if (video
[KPARAM_WIDTH
] * video
[KPARAM_HEIGHT
] * XENFB_DEPTH
/ 8
394 pr_warn("display parameters %d,%d,%d invalid, use defaults\n",
395 video
[KPARAM_MEM
], video
[KPARAM_WIDTH
],
396 video
[KPARAM_HEIGHT
]);
397 video
[KPARAM_WIDTH
] = XENFB_WIDTH
;
398 video
[KPARAM_HEIGHT
] = XENFB_HEIGHT
;
399 fb_size
= XENFB_DEFAULT_FB_LEN
;
402 dev_set_drvdata(&dev
->dev
, info
);
405 info
->x1
= info
->y1
= INT_MAX
;
406 spin_lock_init(&info
->dirty_lock
);
407 spin_lock_init(&info
->resize_lock
);
409 info
->fb
= vzalloc(fb_size
);
410 if (info
->fb
== NULL
)
413 info
->nr_pages
= (fb_size
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
;
415 info
->gfns
= vmalloc(array_size(sizeof(unsigned long), info
->nr_pages
));
419 /* set up shared page */
420 info
->page
= (void *)__get_free_page(GFP_KERNEL
| __GFP_ZERO
);
424 /* abusing framebuffer_alloc() to allocate pseudo_palette */
425 fb_info
= framebuffer_alloc(sizeof(u32
) * 256, NULL
);
429 /* complete the abuse: */
430 fb_info
->pseudo_palette
= fb_info
->par
;
433 fb_info
->screen_base
= info
->fb
;
435 fb_info
->fbops
= &xenfb_fb_ops
;
436 fb_info
->var
.xres_virtual
= fb_info
->var
.xres
= video
[KPARAM_WIDTH
];
437 fb_info
->var
.yres_virtual
= fb_info
->var
.yres
= video
[KPARAM_HEIGHT
];
438 fb_info
->var
.bits_per_pixel
= XENFB_DEPTH
;
440 fb_info
->var
.red
= (struct fb_bitfield
){16, 8, 0};
441 fb_info
->var
.green
= (struct fb_bitfield
){8, 8, 0};
442 fb_info
->var
.blue
= (struct fb_bitfield
){0, 8, 0};
444 fb_info
->var
.activate
= FB_ACTIVATE_NOW
;
445 fb_info
->var
.height
= -1;
446 fb_info
->var
.width
= -1;
447 fb_info
->var
.vmode
= FB_VMODE_NONINTERLACED
;
449 fb_info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
450 fb_info
->fix
.line_length
= fb_info
->var
.xres
* XENFB_DEPTH
/ 8;
451 fb_info
->fix
.smem_start
= 0;
452 fb_info
->fix
.smem_len
= fb_size
;
453 strcpy(fb_info
->fix
.id
, "xen");
454 fb_info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
455 fb_info
->fix
.accel
= FB_ACCEL_NONE
;
457 fb_info
->flags
= FBINFO_FLAG_DEFAULT
| FBINFO_VIRTFB
;
459 ret
= fb_alloc_cmap(&fb_info
->cmap
, 256, 0);
461 framebuffer_release(fb_info
);
462 xenbus_dev_fatal(dev
, ret
, "fb_alloc_cmap");
466 fb_info
->fbdefio
= &xenfb_defio
;
467 fb_deferred_io_init(fb_info
);
469 xenfb_init_shared_page(info
, fb_info
);
471 ret
= xenfb_connect_backend(dev
, info
);
473 xenbus_dev_fatal(dev
, ret
, "xenfb_connect_backend");
477 ret
= register_framebuffer(fb_info
);
479 xenbus_dev_fatal(dev
, ret
, "register_framebuffer");
482 info
->fb_info
= fb_info
;
484 xenfb_make_preferred_console();
488 fb_deferred_io_cleanup(fb_info
);
489 fb_dealloc_cmap(&fb_info
->cmap
);
490 framebuffer_release(fb_info
);
494 xenbus_dev_fatal(dev
, ret
, "allocating device memory");
501 static void xenfb_make_preferred_console(void)
505 if (console_set_on_cmdline
)
509 for_each_console(c
) {
510 if (!strcmp(c
->name
, "tty") && c
->index
== 0)
515 unregister_console(c
);
516 c
->flags
|= CON_CONSDEV
;
517 c
->flags
&= ~CON_PRINTBUFFER
; /* don't print again */
522 static int xenfb_resume(struct xenbus_device
*dev
)
524 struct xenfb_info
*info
= dev_get_drvdata(&dev
->dev
);
526 xenfb_disconnect_backend(info
);
527 xenfb_init_shared_page(info
, info
->fb_info
);
528 return xenfb_connect_backend(dev
, info
);
531 static int xenfb_remove(struct xenbus_device
*dev
)
533 struct xenfb_info
*info
= dev_get_drvdata(&dev
->dev
);
535 xenfb_disconnect_backend(info
);
537 fb_deferred_io_cleanup(info
->fb_info
);
538 unregister_framebuffer(info
->fb_info
);
539 fb_dealloc_cmap(&info
->fb_info
->cmap
);
540 framebuffer_release(info
->fb_info
);
542 free_page((unsigned long)info
->page
);
550 static unsigned long vmalloc_to_gfn(void *address
)
552 return xen_page_to_gfn(vmalloc_to_page(address
));
555 static void xenfb_init_shared_page(struct xenfb_info
*info
,
556 struct fb_info
*fb_info
)
559 int epd
= PAGE_SIZE
/ sizeof(info
->gfns
[0]);
561 for (i
= 0; i
< info
->nr_pages
; i
++)
562 info
->gfns
[i
] = vmalloc_to_gfn(info
->fb
+ i
* PAGE_SIZE
);
564 for (i
= 0; i
* epd
< info
->nr_pages
; i
++)
565 info
->page
->pd
[i
] = vmalloc_to_gfn(&info
->gfns
[i
* epd
]);
567 info
->page
->width
= fb_info
->var
.xres
;
568 info
->page
->height
= fb_info
->var
.yres
;
569 info
->page
->depth
= fb_info
->var
.bits_per_pixel
;
570 info
->page
->line_length
= fb_info
->fix
.line_length
;
571 info
->page
->mem_length
= fb_info
->fix
.smem_len
;
572 info
->page
->in_cons
= info
->page
->in_prod
= 0;
573 info
->page
->out_cons
= info
->page
->out_prod
= 0;
576 static int xenfb_connect_backend(struct xenbus_device
*dev
,
577 struct xenfb_info
*info
)
579 int ret
, evtchn
, irq
;
580 struct xenbus_transaction xbt
;
582 ret
= xenbus_alloc_evtchn(dev
, &evtchn
);
585 irq
= bind_evtchn_to_irqhandler(evtchn
, xenfb_event_handler
,
586 0, dev
->devicetype
, info
);
588 xenbus_free_evtchn(dev
, evtchn
);
589 xenbus_dev_fatal(dev
, ret
, "bind_evtchn_to_irqhandler");
593 ret
= xenbus_transaction_start(&xbt
);
595 xenbus_dev_fatal(dev
, ret
, "starting transaction");
598 ret
= xenbus_printf(xbt
, dev
->nodename
, "page-ref", "%lu",
599 virt_to_gfn(info
->page
));
602 ret
= xenbus_printf(xbt
, dev
->nodename
, "event-channel", "%u",
606 ret
= xenbus_printf(xbt
, dev
->nodename
, "protocol", "%s",
607 XEN_IO_PROTO_ABI_NATIVE
);
610 ret
= xenbus_printf(xbt
, dev
->nodename
, "feature-update", "1");
613 ret
= xenbus_transaction_end(xbt
, 0);
617 xenbus_dev_fatal(dev
, ret
, "completing transaction");
621 xenbus_switch_state(dev
, XenbusStateInitialised
);
626 xenbus_transaction_end(xbt
, 1);
627 xenbus_dev_fatal(dev
, ret
, "writing xenstore");
629 unbind_from_irqhandler(irq
, info
);
633 static void xenfb_disconnect_backend(struct xenfb_info
*info
)
635 /* Prevent xenfb refresh */
636 info
->update_wanted
= 0;
638 unbind_from_irqhandler(info
->irq
, info
);
642 static void xenfb_backend_changed(struct xenbus_device
*dev
,
643 enum xenbus_state backend_state
)
645 struct xenfb_info
*info
= dev_get_drvdata(&dev
->dev
);
647 switch (backend_state
) {
648 case XenbusStateInitialising
:
649 case XenbusStateInitialised
:
650 case XenbusStateReconfiguring
:
651 case XenbusStateReconfigured
:
652 case XenbusStateUnknown
:
655 case XenbusStateInitWait
:
656 xenbus_switch_state(dev
, XenbusStateConnected
);
659 case XenbusStateConnected
:
661 * Work around xenbus race condition: If backend goes
662 * through InitWait to Connected fast enough, we can
663 * get Connected twice here.
665 if (dev
->state
!= XenbusStateConnected
)
666 /* no InitWait seen yet, fudge it */
667 xenbus_switch_state(dev
, XenbusStateConnected
);
669 if (xenbus_read_unsigned(info
->xbdev
->otherend
,
670 "request-update", 0))
671 info
->update_wanted
= 1;
673 info
->feature_resize
= xenbus_read_unsigned(dev
->otherend
,
674 "feature-resize", 0);
677 case XenbusStateClosed
:
678 if (dev
->state
== XenbusStateClosed
)
680 fallthrough
; /* Missed the backend's CLOSING state */
681 case XenbusStateClosing
:
682 xenbus_frontend_closed(dev
);
687 static const struct xenbus_device_id xenfb_ids
[] = {
692 static struct xenbus_driver xenfb_driver
= {
694 .probe
= xenfb_probe
,
695 .remove
= xenfb_remove
,
696 .resume
= xenfb_resume
,
697 .otherend_changed
= xenfb_backend_changed
,
700 static int __init
xenfb_init(void)
705 /* Nothing to do if running in dom0. */
706 if (xen_initial_domain())
709 if (!xen_has_pv_devices())
712 return xenbus_register_frontend(&xenfb_driver
);
715 static void __exit
xenfb_cleanup(void)
717 xenbus_unregister_driver(&xenfb_driver
);
720 module_init(xenfb_init
);
721 module_exit(xenfb_cleanup
);
723 MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
724 MODULE_LICENSE("GPL");
725 MODULE_ALIAS("xen:vfb");