1 #include <linux/init.h>
2 #include <linux/config.h>
3 #include <linux/module.h>
4 #include <linux/interrupt.h>
6 #include <linux/input.h>
7 #include <linux/kthread.h>
8 #include <linux/sched.h>
9 #include <linux/console.h>
10 #include <linux/pagemap.h>
18 #define DRIVER_NAME "uml-x11-fb"
20 /* ---------------------------------------------------------------------------- */
22 static int x11_enable = 0;
23 static int x11_fps = 5;
25 static int x11_height;
29 struct x11_window *win;
30 struct task_struct *kthread;
34 /* framebuffer driver */
35 struct fb_fix_screeninfo *fix;
36 struct fb_var_screeninfo *var;
38 struct timer_list refresh;
39 int dirty, x1, x2, y1, y2;
42 struct semaphore mm_lock;
43 struct vm_area_struct *vma;
52 struct input_dev mouse;
55 void x11_mmap_update(struct x11_kerndata *kd)
60 zap_page_range(kd->vma, kd->vma->vm_start,
61 kd->vma->vm_end - kd->vma->vm_start, NULL);
63 for (i = 0; i < kd->nr_pages; i++) {
64 if (NULL == kd->pages[i])
66 if (0 == kd->mapped[i])
69 off = i << PAGE_SHIFT;
71 if (len > kd->fix->smem_len - off)
72 len = kd->fix->smem_len - off;
73 src = kmap(kd->pages[i]);
74 memcpy(kd->info->screen_base + off, src, len);
79 static int x11_thread(void *data)
81 struct x11_kerndata *kd = data;
82 DECLARE_WAITQUEUE(wait,current);
84 add_wait_queue(&kd->wq, &wait);
86 if (kthread_should_stop())
97 kd->dirty = kd->x1 = kd->x2 = kd->y1 = kd->y2 = 0;
98 x11_blit_fb(kd->win, x1, y1, x2, y2);
102 x11_has_data(kd->win,kd);
103 reactivate_fd(x11_get_fd(kd->win), X11_IRQ);
105 set_current_state(TASK_INTERRUPTIBLE);
108 remove_wait_queue(&kd->wq, &wait);
112 /* ---------------------------------------------------------------------------- */
115 void x11_kbd_input(struct x11_kerndata *kd, int key, int down)
117 if (key >= KEY_MAX) {
119 printk("%s: unknown key pressed [%d]\n",
120 __FUNCTION__, key-KEY_MAX);
123 input_report_key(&kd->kbd,key,down);
124 input_sync(&kd->kbd);
127 void x11_mouse_input(struct x11_kerndata *kd, int key, int down,
130 if (key != KEY_RESERVED)
131 input_report_key(&kd->mouse, key, down);
132 input_report_abs(&kd->mouse, ABS_X, x);
133 input_report_abs(&kd->mouse, ABS_Y, y);
134 input_sync(&kd->mouse);
137 void x11_cad(struct x11_kerndata *kd)
139 printk("%s\n",__FUNCTION__);
142 /* ---------------------------------------------------------------------------- */
143 /* framebuffer driver */
145 static int x11_setcolreg(unsigned regno, unsigned red, unsigned green,
146 unsigned blue, unsigned transp,
147 struct fb_info *info)
149 if (regno >= info->cmap.len)
152 switch (info->var.bits_per_pixel) {
154 if (info->var.red.offset == 10) {
156 ((u32*) (info->pseudo_palette))[regno] =
157 ((red & 0xf800) >> 1) |
158 ((green & 0xf800) >> 6) |
159 ((blue & 0xf800) >> 11);
162 ((u32*) (info->pseudo_palette))[regno] =
164 ((green & 0xfc00) >> 5) |
165 ((blue & 0xf800) >> 11);
172 ((u32 *)(info->pseudo_palette))[regno] =
173 (red << info->var.red.offset) |
174 (green << info->var.green.offset) |
175 (blue << info->var.blue.offset);
181 ((u32 *)(info->pseudo_palette))[regno] =
182 (red << info->var.red.offset) |
183 (green << info->var.green.offset) |
184 (blue << info->var.blue.offset);
190 static void x11_fb_timer(unsigned long data)
192 struct x11_kerndata *kd = (struct x11_kerndata*)data;
197 static void x11_fb_refresh(struct x11_kerndata *kd,
198 int x1, int y1, int w, int h)
204 if (0 == kd->x2 || 0 == kd->y2) {
219 if (timer_pending(&kd->refresh))
221 mod_timer(&kd->refresh, jiffies + HZ/x11_fps);
224 void x11_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
226 struct x11_kerndata *kd = p->par;
228 cfb_fillrect(p, rect);
229 x11_fb_refresh(kd, rect->dx, rect->dy, rect->width, rect->height);
232 void x11_imageblit(struct fb_info *p, const struct fb_image *image)
234 struct x11_kerndata *kd = p->par;
236 cfb_imageblit(p, image);
237 x11_fb_refresh(kd, image->dx, image->dy, image->width, image->height);
240 void x11_copyarea(struct fb_info *p, const struct fb_copyarea *area)
242 struct x11_kerndata *kd = p->par;
244 cfb_copyarea(p, area);
245 x11_fb_refresh(kd, area->dx, area->dy, area->width, area->height);
248 /* ---------------------------------------------------------------------------- */
251 x11_fb_vm_open(struct vm_area_struct *vma)
253 struct x11_kerndata *kd = vma->vm_private_data;
255 atomic_inc(&kd->map_refs);
259 x11_fb_vm_close(struct vm_area_struct *vma)
261 struct x11_kerndata *kd = vma->vm_private_data;
264 if (!atomic_dec_and_test(&kd->map_refs))
267 for (i = 0; i < kd->nr_pages; i++) {
268 if (NULL == kd->pages[i])
270 put_page(kd->pages[i]);
283 x11_fb_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
286 struct x11_kerndata *kd = vma->vm_private_data;
287 int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
290 if (pgnr >= kd->nr_pages)
291 return NOPAGE_SIGBUS;
294 if (NULL == kd->pages[pgnr]) {
296 page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
299 clear_user_highpage(page, vaddr);
300 kd->pages[pgnr] = page;
302 get_page(kd->pages[pgnr]);
303 kd->mapped[pgnr] = 1;
307 y1 = pgnr * PAGE_SIZE / kd->fix->line_length;
308 y2 = (pgnr * PAGE_SIZE + PAGE_SIZE-1) / kd->fix->line_length;
309 if (y2 > kd->var->yres)
311 x11_fb_refresh(kd, 0, y1, kd->var->xres, y2 - y1);
314 *type = VM_FAULT_MINOR;
315 return kd->pages[pgnr];
318 static struct vm_operations_struct x11_fb_vm_ops =
320 .open = x11_fb_vm_open,
321 .close = x11_fb_vm_close,
322 .nopage = x11_fb_vm_nopage,
325 int x11_mmap(struct fb_info *p, struct file *file,
326 struct vm_area_struct * vma)
328 struct x11_kerndata *kd = p->par;
337 printk("%s: busy, mapping exists\n",__FUNCTION__);
342 if (!(vma->vm_flags & VM_WRITE)) {
343 printk("%s: need writable mapping\n",__FUNCTION__);
346 if (!(vma->vm_flags & VM_SHARED)) {
347 printk("%s: need shared mapping\n",__FUNCTION__);
350 if (vma->vm_pgoff != 0) {
351 printk("%s: need offset 0 (vm_pgoff=%ld)\n",__FUNCTION__,
356 fb_pages = (p->fix.smem_len + PAGE_SIZE-1) >> PAGE_SHIFT;
357 map_pages = (vma->vm_end - vma->vm_start + PAGE_SIZE-1) >> PAGE_SHIFT;
358 if (map_pages > fb_pages) {
359 printk("%s: mapping to big (%ld > %d)\n",__FUNCTION__,
360 vma->vm_end - vma->vm_start, p->fix.smem_len);
365 kd->pages = kmalloc(sizeof(struct page*)*map_pages, GFP_KERNEL);
366 if (NULL == kd->pages)
368 kd->mapped = kmalloc(sizeof(int)*map_pages, GFP_KERNEL);
369 if (NULL == kd->mapped) {
373 memset(kd->pages, 0, sizeof(struct page*) * map_pages);
374 memset(kd->mapped, 0, sizeof(int) * map_pages);
376 kd->nr_pages = map_pages;
377 atomic_set(&kd->map_refs,1);
380 vma->vm_ops = &x11_fb_vm_ops;
381 vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
382 vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
383 vma->vm_private_data = kd;
391 /* ---------------------------------------------------------------------------- */
393 static struct fb_ops x11_fb_ops = {
394 .owner = THIS_MODULE,
395 .fb_setcolreg = x11_setcolreg,
396 .fb_fillrect = x11_fillrect,
397 .fb_copyarea = x11_copyarea,
398 .fb_imageblit = x11_imageblit,
399 .fb_cursor = soft_cursor,
403 /* ---------------------------------------------------------------------------- */
405 static irqreturn_t x11_irq(int irq, void *data, struct pt_regs *unused)
407 struct x11_kerndata *kd = data;
414 static int __init x11_probe(struct device *device)
416 struct x11_kerndata *kd;
419 kd = kmalloc(sizeof(*kd),GFP_KERNEL);
422 memset(kd,0,sizeof(*kd));
424 kd->win = x11_open(x11_width, x11_height);
425 if (NULL == kd->win) {
426 printk(DRIVER_NAME ": can't open X11 window\n");
429 kd->fix = x11_get_fix(kd->win);
430 kd->var = x11_get_var(kd->win);
432 /* framebuffer setup */
433 kd->info = framebuffer_alloc(sizeof(u32) * 256, device);
434 kd->info->pseudo_palette = kd->info->par;
436 kd->info->screen_base = x11_get_fbmem(kd->win);
438 kd->info->fbops = &x11_fb_ops;
439 kd->info->var = *kd->var;
440 kd->info->fix = *kd->fix;
441 kd->info->flags = FBINFO_FLAG_DEFAULT;
443 fb_alloc_cmap(&kd->info->cmap, 256, 0);
444 register_framebuffer(kd->info);
445 printk(KERN_INFO "fb%d: %s frame buffer device, %dx%d, %d fps, %d bpp (%d:%d:%d)\n",
446 kd->info->node, kd->info->fix.id,
447 kd->var->xres, kd->var->yres, x11_fps, kd->var->bits_per_pixel,
448 kd->var->red.length, kd->var->green.length, kd->var->blue.length);
451 init_input_dev(&kd->kbd);
452 set_bit(EV_KEY, kd->kbd.evbit);
453 for (i = 0; i < KEY_MAX; i++)
454 set_bit(i, kd->kbd.keybit);
455 kd->kbd.id.bustype = BUS_HOST;
456 kd->kbd.name = DRIVER_NAME " virtual keyboard";
457 kd->kbd.phys = DRIVER_NAME "/input0";
458 kd->kbd.dev = device;
459 input_register_device(&kd->kbd);
462 init_input_dev(&kd->mouse);
463 set_bit(EV_ABS, kd->mouse.evbit);
464 set_bit(EV_KEY, kd->mouse.evbit);
465 set_bit(BTN_TOUCH, kd->mouse.keybit);
466 set_bit(BTN_LEFT, kd->mouse.keybit);
467 set_bit(BTN_MIDDLE, kd->mouse.keybit);
468 set_bit(BTN_RIGHT, kd->mouse.keybit);
469 set_bit(ABS_X, kd->mouse.absbit);
470 set_bit(ABS_Y, kd->mouse.absbit);
471 kd->mouse.absmin[ABS_X] = 0;
472 kd->mouse.absmax[ABS_X] = kd->var->xres;
473 kd->mouse.absmin[ABS_Y] = 0;
474 kd->mouse.absmax[ABS_Y] = kd->var->yres;
475 kd->mouse.id.bustype = BUS_HOST;
476 kd->mouse.name = DRIVER_NAME " virtual mouse";
477 kd->mouse.phys = DRIVER_NAME "/input1";
478 kd->mouse.dev = device;
479 input_register_device(&kd->mouse);
481 /* misc common kernel stuff */
482 init_MUTEX(&kd->mm_lock);
483 init_waitqueue_head(&kd->wq);
484 init_timer(&kd->refresh);
485 kd->refresh.function = x11_fb_timer;
486 kd->refresh.data = (unsigned long)kd;
488 kd->kthread = kthread_run(x11_thread, kd,
489 DRIVER_NAME " thread");
490 um_request_irq(X11_IRQ, x11_get_fd(kd->win), IRQ_READ, x11_irq,
491 SA_INTERRUPT | SA_SHIRQ, DRIVER_NAME, kd);
500 static struct device_driver x11_driver = {
502 .bus = &platform_bus_type,
505 static struct platform_device x11_device = {
509 static int __init x11_init(void)
513 ret = driver_register(&x11_driver);
518 ret = platform_device_register(&x11_device);
520 driver_unregister(&x11_driver);
524 static void __exit x11_fini(void)
527 platform_device_unregister(&x11_device);
528 driver_unregister(&x11_driver);
531 module_init(x11_init);
532 module_exit(x11_fini);
534 extern int console_use_vt; /* FIXME */
536 static int x11_setup(char *str)
538 if (3 == sscanf(str,"%dx%d@%d",&x11_width,&x11_height,&x11_fps) ||
539 2 == sscanf(str,"%dx%d",&x11_width,&x11_height)) {
545 __setup("x11=", x11_setup);