Drop obsoleted patch.
[linux-flexiantxendom0-3.2.10.git] / arch / um / drivers / x11_kern.c
1 #include <linux/init.h>
2 #include <linux/config.h>
3 #include <linux/module.h>
4 #include <linux/interrupt.h>
5 #include <linux/fb.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>
11 #include <linux/mm.h>
12
13 #include "irq_kern.h"
14 #include "irq_user.h"
15 #include "x11_kern.h"
16 #include "x11_user.h"
17
18 #define DRIVER_NAME "uml-x11-fb"
19
20 /* ---------------------------------------------------------------------------- */
21
22 static int x11_enable  = 0;
23 static int x11_fps     = 5;
24 static int x11_width;
25 static int x11_height;
26
27 struct x11_kerndata {
28         /* common stuff */
29         struct x11_window         *win;
30         struct task_struct        *kthread;
31         wait_queue_head_t         wq;
32         int                       has_data;
33
34         /* framebuffer driver */
35         struct fb_fix_screeninfo  *fix;
36         struct fb_var_screeninfo  *var;
37         struct fb_info            *info;
38         struct timer_list         refresh;
39         int                       dirty, x1, x2, y1, y2;
40
41         /* fb mapping */
42         struct semaphore          mm_lock;
43         struct vm_area_struct     *vma;
44         atomic_t                  map_refs;
45         int                       faults;
46         int                       nr_pages;
47         struct page               **pages;
48         int                       *mapped;
49
50         /* input drivers */
51         struct input_dev          kbd;
52         struct input_dev          mouse;
53 };
54
55 void x11_mmap_update(struct x11_kerndata *kd)
56 {
57         int i, off, len;
58         char *src;
59
60         zap_page_range(kd->vma, kd->vma->vm_start,
61                        kd->vma->vm_end - kd->vma->vm_start, NULL);
62         kd->faults = 0;
63         for (i = 0; i < kd->nr_pages; i++) {
64                 if (NULL == kd->pages[i])
65                         continue;
66                 if (0 == kd->mapped[i])
67                         continue;
68                 kd->mapped[i] = 0;
69                 off = i << PAGE_SHIFT;
70                 len = PAGE_SIZE;
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);
75                 kunmap(kd->pages[i]);
76         }
77 }
78
79 static int x11_thread(void *data)
80 {
81         struct x11_kerndata *kd = data;
82         DECLARE_WAITQUEUE(wait,current);
83
84         add_wait_queue(&kd->wq, &wait);
85         for (;;) {
86                 if (kthread_should_stop())
87                         break;
88                 if (kd->dirty) {
89                         int x1 = kd->x1;
90                         int x2 = kd->x2;
91                         int y1 = kd->y1;
92                         int y2 = kd->y2;
93                         down(&kd->mm_lock);
94                         if (kd->faults > 0)
95                                 x11_mmap_update(kd);
96                         up(&kd->mm_lock);
97                         kd->dirty = kd->x1 = kd->x2 = kd->y1 = kd->y2 = 0;
98                         x11_blit_fb(kd->win, x1, y1, x2, y2);
99                 }
100                 if (kd->has_data) {
101                         kd->has_data = 0;
102                         x11_has_data(kd->win,kd);
103                         reactivate_fd(x11_get_fd(kd->win), X11_IRQ);
104                 }
105                 set_current_state(TASK_INTERRUPTIBLE);
106                 schedule();
107         }
108         remove_wait_queue(&kd->wq, &wait);
109         return 0;
110 }
111
112 /* ---------------------------------------------------------------------------- */
113 /* input driver                                                                 */
114
115 void x11_kbd_input(struct x11_kerndata *kd, int key, int down)
116 {
117         if (key >= KEY_MAX) {
118                 if (down)
119                         printk("%s: unknown key pressed [%d]\n",
120                                __FUNCTION__, key-KEY_MAX);
121                 return;
122         }
123         input_report_key(&kd->kbd,key,down);
124         input_sync(&kd->kbd);
125 }
126
127 void x11_mouse_input(struct x11_kerndata *kd, int key, int down,
128                      int x, int y)
129 {
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);
135 }
136
137 void x11_cad(struct x11_kerndata *kd)
138 {
139         printk("%s\n",__FUNCTION__);
140 }
141
142 /* ---------------------------------------------------------------------------- */
143 /* framebuffer driver                                                           */
144
145 static int x11_setcolreg(unsigned regno, unsigned red, unsigned green,
146                          unsigned blue, unsigned transp,
147                          struct fb_info *info)
148 {
149         if (regno >= info->cmap.len)
150                 return 1;
151
152         switch (info->var.bits_per_pixel) {
153         case 16:
154                 if (info->var.red.offset == 10) {
155                         /* 1:5:5:5 */
156                         ((u32*) (info->pseudo_palette))[regno] =        
157                                 ((red   & 0xf800) >>  1) |
158                                 ((green & 0xf800) >>  6) |
159                                 ((blue  & 0xf800) >> 11);
160                 } else {
161                         /* 0:5:6:5 */
162                         ((u32*) (info->pseudo_palette))[regno] =        
163                                 ((red   & 0xf800)      ) |
164                                 ((green & 0xfc00) >>  5) |
165                                 ((blue  & 0xf800) >> 11);
166                 }
167                 break;
168         case 24:
169                 red   >>= 8;
170                 green >>= 8;
171                 blue  >>= 8;
172                 ((u32 *)(info->pseudo_palette))[regno] =
173                         (red   << info->var.red.offset)   |
174                         (green << info->var.green.offset) |
175                         (blue  << info->var.blue.offset);
176                 break;
177         case 32:
178                 red   >>= 8;
179                 green >>= 8;
180                 blue  >>= 8;
181                 ((u32 *)(info->pseudo_palette))[regno] =
182                         (red   << info->var.red.offset)   |
183                         (green << info->var.green.offset) |
184                         (blue  << info->var.blue.offset);
185                 break;
186         }
187         return 0;
188 }
189
190 static void x11_fb_timer(unsigned long data)
191 {
192         struct x11_kerndata *kd = (struct x11_kerndata*)data;
193         kd->dirty++;
194         wake_up(&kd->wq);
195 }
196
197 static void x11_fb_refresh(struct x11_kerndata *kd,
198                            int x1, int y1, int w, int h)
199 {
200         int x2, y2;
201
202         x2 = x1 + w;
203         y2 = y1 + h;
204         if (0 == kd->x2 || 0 == kd->y2) {
205                 kd->x1 = x1;
206                 kd->x2 = x2;
207                 kd->y1 = y1;
208                 kd->y2 = y2;
209         }
210         if (kd->x1 > x1)
211                 kd->x1 = x1;
212         if (kd->x2 < x2)
213                 kd->x2 = x2;
214         if (kd->y1 > y1)
215                 kd->y1 = y1;
216         if (kd->y2 < y2)
217                 kd->y2 = y2;
218
219         if (timer_pending(&kd->refresh))
220                 return;
221         mod_timer(&kd->refresh, jiffies + HZ/x11_fps);
222 }
223
224 void x11_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
225 {
226         struct x11_kerndata *kd = p->par;
227
228         cfb_fillrect(p, rect);
229         x11_fb_refresh(kd, rect->dx, rect->dy, rect->width, rect->height);
230 }
231
232 void x11_imageblit(struct fb_info *p, const struct fb_image *image)
233 {
234         struct x11_kerndata *kd = p->par;
235
236         cfb_imageblit(p, image);
237         x11_fb_refresh(kd, image->dx, image->dy, image->width, image->height);
238 }
239
240 void x11_copyarea(struct fb_info *p, const struct fb_copyarea *area)
241 {
242         struct x11_kerndata *kd = p->par;
243
244         cfb_copyarea(p, area);
245         x11_fb_refresh(kd, area->dx, area->dy, area->width, area->height);
246 }
247
248 /* ---------------------------------------------------------------------------- */
249
250 static void
251 x11_fb_vm_open(struct vm_area_struct *vma)
252 {
253         struct x11_kerndata *kd = vma->vm_private_data;
254
255         atomic_inc(&kd->map_refs);
256 }
257
258 static void
259 x11_fb_vm_close(struct vm_area_struct *vma)
260 {
261         struct x11_kerndata *kd = vma->vm_private_data;
262         int i;
263
264         if (!atomic_dec_and_test(&kd->map_refs))
265                 return;
266         down(&kd->mm_lock);
267         for (i = 0; i < kd->nr_pages; i++) {
268                 if (NULL == kd->pages[i])
269                         continue;
270                 put_page(kd->pages[i]);
271         }
272         kfree(kd->pages);
273         kfree(kd->mapped);
274         kd->pages    = NULL;
275         kd->mapped   = NULL;
276         kd->vma      = NULL;
277         kd->nr_pages = 0;
278         kd->faults   = 0;
279         up(&kd->mm_lock);
280 }
281
282 static struct page*
283 x11_fb_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
284                  int *type)
285 {
286         struct x11_kerndata *kd = vma->vm_private_data;
287         int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
288         int y1,y2;
289
290         if (pgnr >= kd->nr_pages)
291                 return NOPAGE_SIGBUS;
292
293         down(&kd->mm_lock);
294         if (NULL == kd->pages[pgnr]) {
295                 struct page *page;
296                 page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
297                 if (!page)
298                         return NOPAGE_OOM;
299                 clear_user_highpage(page, vaddr);
300                 kd->pages[pgnr] = page;
301         }
302         get_page(kd->pages[pgnr]);
303         kd->mapped[pgnr] = 1;
304         kd->faults++;
305         up(&kd->mm_lock);
306
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)
310                 y2 = kd->var->yres;
311         x11_fb_refresh(kd, 0, y1, kd->var->xres, y2 - y1);
312         
313         if (type)
314                 *type = VM_FAULT_MINOR;
315         return kd->pages[pgnr];
316 }
317
318 static struct vm_operations_struct x11_fb_vm_ops =
319 {
320         .open     = x11_fb_vm_open,
321         .close    = x11_fb_vm_close,
322         .nopage   = x11_fb_vm_nopage,
323 };
324
325 int x11_mmap(struct fb_info *p, struct file *file,
326              struct vm_area_struct * vma)
327 {
328         struct x11_kerndata *kd = p->par;
329         int retval;
330         int fb_pages;
331         int map_pages;
332
333         down(&kd->mm_lock);
334
335         retval = -EBUSY;
336         if (kd->vma) {
337                 printk("%s: busy, mapping exists\n",__FUNCTION__);
338                 goto out;
339         }
340
341         retval = -EINVAL;
342         if (!(vma->vm_flags & VM_WRITE)) {
343                 printk("%s: need writable mapping\n",__FUNCTION__);
344                 goto out;
345         }
346         if (!(vma->vm_flags & VM_SHARED)) {
347                 printk("%s: need shared mapping\n",__FUNCTION__);
348                 goto out;
349         }
350         if (vma->vm_pgoff != 0) {
351                 printk("%s: need offset 0 (vm_pgoff=%ld)\n",__FUNCTION__,
352                        vma->vm_pgoff);
353                 goto out;
354         }
355
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);
361                 goto out;
362         }
363
364         retval = -ENOMEM;
365         kd->pages = kmalloc(sizeof(struct page*)*map_pages, GFP_KERNEL);
366         if (NULL == kd->pages)
367                 goto out;
368         kd->mapped = kmalloc(sizeof(int)*map_pages, GFP_KERNEL);
369         if (NULL == kd->mapped) {
370                 kfree(kd->pages);
371                 goto out;
372         }
373         memset(kd->pages,  0, sizeof(struct page*) * map_pages);
374         memset(kd->mapped, 0, sizeof(int)          * map_pages);
375         kd->vma = vma;
376         kd->nr_pages = map_pages;
377         atomic_set(&kd->map_refs,1);
378         kd->faults = 0;
379
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;
384         retval = 0;
385
386 out:
387         up(&kd->mm_lock);
388         return retval;  
389 }
390
391 /* ---------------------------------------------------------------------------- */
392
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,
400         .fb_mmap        = x11_mmap,
401 };
402
403 /* ---------------------------------------------------------------------------- */
404
405 static irqreturn_t x11_irq(int irq, void *data, struct pt_regs *unused)
406 {
407         struct x11_kerndata *kd = data;
408
409         kd->has_data++;
410         wake_up(&kd->wq);
411         return IRQ_HANDLED;
412 }
413
414 static int __init x11_probe(struct device *device)
415 {
416         struct x11_kerndata *kd;
417         int i;
418         
419         kd = kmalloc(sizeof(*kd),GFP_KERNEL);
420         if (NULL == kd)
421                 return -ENOMEM;
422         memset(kd,0,sizeof(*kd));
423
424         kd->win = x11_open(x11_width, x11_height);
425         if (NULL == kd->win) {
426                 printk(DRIVER_NAME ": can't open X11 window\n");
427                 goto fail_free;
428         }
429         kd->fix = x11_get_fix(kd->win);
430         kd->var = x11_get_var(kd->win);
431         
432         /* framebuffer setup */
433         kd->info = framebuffer_alloc(sizeof(u32) * 256, device);
434         kd->info->pseudo_palette = kd->info->par;
435         kd->info->par = kd;
436         kd->info->screen_base = x11_get_fbmem(kd->win);
437
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;
442
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);
449
450         /* keyboard setup */
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);
460
461         /* mouse setup */
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);
480
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;
487
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);
492
493         return 0;
494
495 fail_free:
496         kfree(kd);
497         return -ENODEV;
498 }
499
500 static struct device_driver x11_driver = {
501         .name  = DRIVER_NAME,
502         .bus   = &platform_bus_type,
503         .probe = x11_probe,
504 };
505 static struct platform_device x11_device = {
506         .name  = DRIVER_NAME,
507 };
508
509 static int __init x11_init(void)
510 {
511         int ret;
512
513         ret = driver_register(&x11_driver);
514         if (ret)
515                 return ret;
516         if (!x11_enable)
517                 return 0;
518         ret = platform_device_register(&x11_device);
519         if (ret)
520                 driver_unregister(&x11_driver);
521         return ret;
522 }
523
524 static void __exit x11_fini(void)
525 {
526         if (x11_enable)
527                 platform_device_unregister(&x11_device);
528         driver_unregister(&x11_driver);
529 }
530
531 module_init(x11_init);
532 module_exit(x11_fini);
533
534 extern int console_use_vt; /* FIXME */
535
536 static int x11_setup(char *str)
537 {
538         if (3 == sscanf(str,"%dx%d@%d",&x11_width,&x11_height,&x11_fps) ||
539             2 == sscanf(str,"%dx%d",&x11_width,&x11_height)) {
540                 x11_enable = 1;
541                 return 0;
542         }
543         return -1;
544 }
545 __setup("x11=", x11_setup);
546
547 /*
548  * Local variables:
549  * c-basic-offset: 8
550  * End:
551  */