22 #include <linux/kernel.h>
23 #include <linux/errno.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
30 #include <asm/xen/hypervisor.h>
33 #include <xen/events.h>
58 #define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
61 static int video[
KPARAM_CNT] = { 2, XENFB_WIDTH, XENFB_HEIGHT };
64 "Video memory size in MB, width, height in pixels (default 2,800,600)");
66 static void xenfb_make_preferred_console(
void);
70 static void xenfb_disconnect_backend(
struct xenfb_info *);
77 prod = info->
page->out_prod;
82 info->
page->out_prod = prod + 1;
88 int x,
int y,
int w,
int h)
96 event.update.width =
w;
97 event.update.height =
h;
100 xenfb_send_event(info, &
event);
103 static void xenfb_do_resize(
struct xenfb_info *info)
108 event.resize = info->
resize;
111 xenfb_send_event(info, &
event);
114 static int xenfb_queue_full(
struct xenfb_info *info)
118 prod = info->
page->out_prod;
119 cons = info->
page->out_cons;
123 static void xenfb_handle_resize_dpy(
struct xenfb_info *info)
129 if (!xenfb_queue_full(info)) {
131 xenfb_do_resize(info);
137 static void xenfb_refresh(
struct xenfb_info *info,
138 int x1,
int y1,
int w,
int h)
144 xenfb_handle_resize_dpy(info);
161 if (xenfb_queue_full(info)) {
167 spin_unlock_irqrestore(&info->
dirty_lock, flags);
173 info->
x2 = info->
y2 = 0;
175 spin_unlock_irqrestore(&info->
dirty_lock, flags);
177 if (x1 <= x2 && y1 <= y2)
178 xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
186 unsigned long beg,
end;
187 int y1, y2, miny, maxy;
194 y1 = beg / fb_info->
fix.line_length;
195 y2 = end / fb_info->
fix.line_length;
196 if (y2 >= fb_info->
var.yres)
197 y2 = fb_info->
var.yres - 1;
203 xenfb_refresh(info, 0, miny, fb_info->
var.xres, maxy - miny + 1);
206 static struct fb_deferred_io xenfb_defio = {
208 .deferred_io = xenfb_deferred_io,
211 static int xenfb_setcolreg(
unsigned regno,
unsigned red,
unsigned green,
213 struct fb_info *info)
217 if (regno > info->
cmap.len)
220 #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
227 v = (red << info->
var.red.offset) |
228 (green << info->
var.green.offset) |
229 (blue << info->
var.blue.offset);
231 switch (info->
var.bits_per_pixel) {
242 static void xenfb_fillrect(
struct fb_info *
p,
const struct fb_fillrect *rect)
250 static void xenfb_imageblit(
struct fb_info *
p,
const struct fb_image *
image)
255 xenfb_refresh(info, image->
dx, image->
dy, image->
width, image->
height);
258 static void xenfb_copyarea(
struct fb_info *
p,
const struct fb_copyarea *area)
266 static ssize_t xenfb_write(
struct fb_info *
p,
const char __user *
buf,
267 size_t count, loff_t *ppos)
273 xenfb_refresh(info, 0, 0, info->
page->width, info->
page->height);
281 int required_mem_len;
283 xenfb_info = info->
par;
298 required_mem_len = var->
xres * var->
yres * xenfb_info->
page->depth / 8;
300 var->
xres <= info->
fix.line_length / (XENFB_DEPTH / 8) &&
301 required_mem_len <= info->fix.smem_len) {
309 static int xenfb_set_par(
struct fb_info *info)
311 struct xenfb_info *xenfb_info;
314 xenfb_info = info->
par;
318 xenfb_info->
resize.width = info->
var.xres;
319 xenfb_info->
resize.height = info->
var.yres;
320 xenfb_info->
resize.stride = info->
fix.line_length;
321 xenfb_info->
resize.depth = info->
var.bits_per_pixel;
322 xenfb_info->
resize.offset = 0;
324 spin_unlock_irqrestore(&xenfb_info->
resize_lock, flags);
328 static struct fb_ops xenfb_fb_ops = {
331 .fb_write = xenfb_write,
332 .fb_setcolreg = xenfb_setcolreg,
333 .fb_fillrect = xenfb_fillrect,
334 .fb_copyarea = xenfb_copyarea,
335 .fb_imageblit = xenfb_imageblit,
336 .fb_check_var = xenfb_check_var,
337 .fb_set_par = xenfb_set_par,
347 struct xenfb_info *info =
dev_id;
351 info->
page->in_cons = info->
page->in_prod;
364 struct xenfb_info *
info;
384 if (video[
KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8
424 fb_info->
fbops = &xenfb_fb_ops;
427 fb_info->
var.bits_per_pixel = XENFB_DEPTH;
434 fb_info->
var.height = -1;
435 fb_info->
var.width = -1;
439 fb_info->
fix.line_length = fb_info->
var.xres * XENFB_DEPTH / 8;
440 fb_info->
fix.smem_start = 0;
441 fb_info->
fix.smem_len = fb_size;
455 fb_info->fbdefio = &xenfb_defio;
458 xenfb_init_shared_page(info, fb_info);
460 ret = xenfb_connect_backend(dev, info);
473 xenfb_make_preferred_console();
491 xenfb_make_preferred_console(
void)
516 xenfb_disconnect_backend(info);
517 xenfb_init_shared_page(info, info->
fb_info);
518 return xenfb_connect_backend(dev, info);
525 xenfb_disconnect_backend(info);
540 static unsigned long vmalloc_to_mfn(
void *
address)
545 static void xenfb_init_shared_page(
struct xenfb_info *info,
546 struct fb_info *fb_info)
549 int epd = PAGE_SIZE /
sizeof(info->
mfns[0]);
551 for (i = 0; i < info->
nr_pages; i++)
552 info->
mfns[i] = vmalloc_to_mfn(info->
fb + i * PAGE_SIZE);
554 for (i = 0; i * epd < info->
nr_pages; i++)
555 info->
page->pd[i] = vmalloc_to_mfn(&info->
mfns[i * epd]);
557 info->
page->width = fb_info->
var.xres;
558 info->
page->height = fb_info->
var.yres;
559 info->
page->depth = fb_info->
var.bits_per_pixel;
560 info->
page->line_length = fb_info->
fix.line_length;
561 info->
page->mem_length = fb_info->
fix.smem_len;
562 info->
page->in_cons = info->
page->in_prod = 0;
563 info->
page->out_cons = info->
page->out_prod = 0;
567 struct xenfb_info *info)
597 XEN_IO_PROTO_ABI_NATIVE);
623 static void xenfb_disconnect_backend(
struct xenfb_info *info)
638 switch (backend_state) {
661 "request-update",
"%d", &val) < 0)
667 "feature-resize",
"%d", &val) < 0)
688 .probe = xenfb_probe,
689 .
remove = xenfb_remove,
691 .otherend_changed = xenfb_backend_changed,
694 static int __init xenfb_init(
void)
706 static void __exit xenfb_cleanup(
void)