ae649517624977d34c7ec6016815aee6a5a6b077
[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
11 #include "irq_kern.h"
12 #include "irq_user.h"
13 #include "x11_kern.h"
14 #include "x11_user.h"
15
16 /* ---------------------------------------------------------------------------- */
17
18 static int x11_enable  = 0;
19 static int x11_fps     = 5;
20 static int x11_width;
21 static int x11_height;
22
23 struct x11_kerndata {
24         /* common stuff */
25         struct x11_window         *win;
26         struct task_struct        *kthread;
27         wait_queue_head_t         wq;
28         int                       has_data;
29
30         /* framebuffer driver */
31         struct fb_fix_screeninfo  *fix;
32         struct fb_var_screeninfo  *var;
33         struct fb_info            *info;
34         struct timer_list         refresh;
35         int                       dirty, x1, x2, y1, y2;
36
37         /* input drivers */
38         struct input_dev          kbd;
39         struct input_dev          mouse;
40 };
41
42 static int x11_thread(void *data)
43 {
44         struct x11_kerndata *kd = data;
45         DECLARE_WAITQUEUE(wait,current);
46
47         add_wait_queue(&kd->wq, &wait);
48         for (;;) {
49                 if (kthread_should_stop())
50                         break;
51                 if (kd->dirty) {
52                         int x1 = kd->x1;
53                         int x2 = kd->x2;
54                         int y1 = kd->y1;
55                         int y2 = kd->y2;
56                         kd->dirty = kd->x1 = kd->x2 = kd->y1 = kd->y2 = 0;
57                         x11_blit_fb(kd->win, x1, y1, x2, y2);
58                 }
59                 if (kd->has_data) {
60                         kd->has_data = 0;
61                         x11_has_data(kd->win,kd);
62                         reactivate_fd(x11_get_fd(kd->win), X11_IRQ);
63                 }
64                 set_current_state(TASK_INTERRUPTIBLE);
65                 schedule();
66         }
67         remove_wait_queue(&kd->wq, &wait);
68         return 0;
69 }
70
71 /* ---------------------------------------------------------------------------- */
72 /* input driver                                                                 */
73
74 void x11_kbd_input(struct x11_kerndata *kd, int key, int down)
75 {
76         if (key >= KEY_MAX) {
77                 if (down)
78                         printk("%s: unknown key pressed [%d]\n",
79                                __FUNCTION__, key-KEY_MAX);
80                 return;
81         }
82         input_report_key(&kd->kbd,key,down);
83         input_sync(&kd->kbd);
84 }
85
86 void x11_mouse_input(struct x11_kerndata *kd, int state, int x, int y)
87 {
88         input_report_key(&kd->mouse, BTN_LEFT,   (state >>  8) & 1); /* Button1Mask */
89         input_report_key(&kd->mouse, BTN_MIDDLE, (state >>  9) & 1); /* Button2Mask */
90         input_report_key(&kd->mouse, BTN_RIGHT,  (state >> 10) & 1); /* Button3Mask */
91         input_report_abs(&kd->mouse, ABS_X, x);
92         input_report_abs(&kd->mouse, ABS_Y, y);
93         input_sync(&kd->mouse);
94 }
95
96 void x11_cad(struct x11_kerndata *kd)
97 {
98         printk("%s\n",__FUNCTION__);
99 }
100
101 /* ---------------------------------------------------------------------------- */
102 /* framebuffer driver                                                           */
103
104 static int x11_setcolreg(unsigned regno, unsigned red, unsigned green,
105                          unsigned blue, unsigned transp,
106                          struct fb_info *info)
107 {
108         if (regno >= info->cmap.len)
109                 return 1;
110
111         switch (info->var.bits_per_pixel) {
112         case 16:
113                 if (info->var.red.offset == 10) {
114                         /* 1:5:5:5 */
115                         ((u32*) (info->pseudo_palette))[regno] =        
116                                 ((red   & 0xf800) >>  1) |
117                                 ((green & 0xf800) >>  6) |
118                                 ((blue  & 0xf800) >> 11);
119                 } else {
120                         /* 0:5:6:5 */
121                         ((u32*) (info->pseudo_palette))[regno] =        
122                                 ((red   & 0xf800)      ) |
123                                 ((green & 0xfc00) >>  5) |
124                                 ((blue  & 0xf800) >> 11);
125                 }
126                 break;
127         case 24:
128                 red   >>= 8;
129                 green >>= 8;
130                 blue  >>= 8;
131                 ((u32 *)(info->pseudo_palette))[regno] =
132                         (red   << info->var.red.offset)   |
133                         (green << info->var.green.offset) |
134                         (blue  << info->var.blue.offset);
135                 break;
136         case 32:
137                 red   >>= 8;
138                 green >>= 8;
139                 blue  >>= 8;
140                 ((u32 *)(info->pseudo_palette))[regno] =
141                         (red   << info->var.red.offset)   |
142                         (green << info->var.green.offset) |
143                         (blue  << info->var.blue.offset);
144                 break;
145         }
146         return 0;
147 }
148
149 static void x11_fb_timer(unsigned long data)
150 {
151         struct x11_kerndata *kd = (struct x11_kerndata*)data;
152         kd->dirty++;
153         wake_up(&kd->wq);
154 }
155
156 static void x11_fb_refresh(struct x11_kerndata *kd,
157                            int x1, int y1, int w, int h)
158 {
159         int x2, y2;
160
161         x2 = x1 + w;
162         y2 = y1 + h;
163         if (0 == kd->x2 || 0 == kd->y2) {
164                 kd->x1 = x1;
165                 kd->x2 = x2;
166                 kd->y1 = y1;
167                 kd->y2 = y2;
168         }
169         if (kd->x1 > x1)
170                 kd->x1 = x1;
171         if (kd->x2 < x2)
172                 kd->x2 = x2;
173         if (kd->y1 > y1)
174                 kd->y1 = y1;
175         if (kd->y2 < y2)
176                 kd->y2 = y2;
177
178         if (timer_pending(&kd->refresh))
179                 return;
180         mod_timer(&kd->refresh, jiffies + HZ/x11_fps);
181 }
182
183 void x11_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
184 {
185         struct x11_kerndata *kd = p->par;
186
187         cfb_fillrect(p, rect);
188         x11_fb_refresh(kd, rect->dx, rect->dy, rect->width, rect->height);
189 }
190
191 void x11_imageblit(struct fb_info *p, const struct fb_image *image)
192 {
193         struct x11_kerndata *kd = p->par;
194
195         cfb_imageblit(p, image);
196         x11_fb_refresh(kd, image->dx, image->dy, image->width, image->height);
197 }
198
199 void x11_copyarea(struct fb_info *p, const struct fb_copyarea *area)
200 {
201         struct x11_kerndata *kd = p->par;
202
203         cfb_copyarea(p, area);
204         x11_fb_refresh(kd, area->dx, area->dy, area->width, area->height);
205 }
206
207 static struct fb_ops x11_fb_ops = {
208         .owner          = THIS_MODULE,
209         .fb_setcolreg   = x11_setcolreg,
210         .fb_fillrect    = x11_fillrect,
211         .fb_copyarea    = x11_copyarea,
212         .fb_imageblit   = x11_imageblit,
213         .fb_cursor      = soft_cursor,
214 };
215
216 /* ---------------------------------------------------------------------------- */
217
218 static irqreturn_t x11_irq(int irq, void *data, struct pt_regs *unused)
219 {
220         struct x11_kerndata *kd = data;
221
222         kd->has_data++;
223         wake_up(&kd->wq);
224         return IRQ_HANDLED;
225 }
226
227 static int x11_probe(void)
228 {
229         struct x11_kerndata *kd;
230         int i;
231         
232         if (!x11_enable)
233                 return -ENODEV;
234
235         kd = kmalloc(sizeof(*kd),GFP_KERNEL);
236         if (NULL == kd)
237                 return -ENOMEM;
238         memset(kd,0,sizeof(*kd));
239
240         kd->win = x11_open(x11_width, x11_height);
241         if (NULL == kd->win)
242                 goto fail_free;
243         kd->fix = x11_get_fix(kd->win);
244         kd->var = x11_get_var(kd->win);
245         
246         /* framebuffer setup */
247         kd->info = framebuffer_alloc(sizeof(u32) * 256, NULL);
248         kd->info->pseudo_palette = kd->info->par;
249         kd->info->par = kd;
250         kd->info->screen_base = x11_get_fbmem(kd->win);
251
252         kd->info->fbops = &x11_fb_ops;
253         kd->info->var = *kd->var;
254         kd->info->fix = *kd->fix;
255         kd->info->flags = FBINFO_FLAG_DEFAULT;
256
257         fb_alloc_cmap(&kd->info->cmap, 256, 0);
258         register_framebuffer(kd->info);
259         printk(KERN_INFO "fb%d: %s frame buffer device, %dx%d, %d fps, %d:%d:%d\n",
260                kd->info->node, kd->info->fix.id,
261                kd->var->xres, kd->var->yres, x11_fps,
262                kd->var->red.length, kd->var->green.length, kd->var->blue.length);
263
264         /* keyboard setup */
265         init_input_dev(&kd->kbd);
266         set_bit(EV_KEY, kd->kbd.evbit);
267         for (i = 0; i < KEY_MAX; i++)
268                 set_bit(i, kd->kbd.keybit);
269         kd->kbd.id.bustype = BUS_HOST;
270         kd->kbd.name = "virtual keyboard";
271         kd->kbd.phys = "x11/input0";
272         input_register_device(&kd->kbd);
273
274         /* mouse setup */
275         init_input_dev(&kd->mouse);
276         set_bit(EV_ABS,     kd->mouse.evbit);
277         set_bit(EV_KEY,     kd->mouse.evbit);
278         set_bit(BTN_LEFT,   kd->mouse.keybit);
279         set_bit(BTN_MIDDLE, kd->mouse.keybit);
280         set_bit(BTN_RIGHT,  kd->mouse.keybit);
281         set_bit(ABS_X,      kd->mouse.absbit);
282         set_bit(ABS_Y,      kd->mouse.absbit);
283         kd->mouse.absmin[ABS_X] = 0;
284         kd->mouse.absmax[ABS_X] = kd->var->xres;
285         kd->mouse.absmin[ABS_Y] = 0;
286         kd->mouse.absmax[ABS_Y] = kd->var->yres;
287         kd->mouse.id.bustype = BUS_HOST;
288         kd->mouse.name = "virtual mouse";
289         kd->mouse.phys = "x11/input1";
290         input_register_device(&kd->mouse);
291
292         /* misc common kernel stuff */
293         init_waitqueue_head(&kd->wq);
294         init_timer(&kd->refresh);
295         kd->refresh.function = x11_fb_timer;
296         kd->refresh.data     = (unsigned long)kd;
297
298         kd->kthread = kthread_run(x11_thread, kd, "x11 thread");
299         um_request_irq(X11_IRQ, x11_get_fd(kd->win), IRQ_READ, x11_irq,
300                        SA_INTERRUPT | SA_SHIRQ, "x11", kd);
301
302         return 0;
303
304 fail_free:
305         kfree(kd);
306         return -ENODEV;
307 }
308
309 static int __init x11_init(void)
310 {
311         return x11_probe();
312 }
313
314 static void __exit x11_fini(void)
315 {
316         /* FIXME */
317 }
318
319 module_init(x11_init);
320 module_exit(x11_fini);
321
322 static int x11_setup(char *str)
323 {
324         if (3 == sscanf(str,"%dx%d@%d",&x11_width,&x11_height,&x11_fps) ||
325             2 == sscanf(str,"%dx%d",&x11_width,&x11_height)) {
326                 x11_enable = 1;
327 #if defined(CONFIG_DUMMY_CONSOLE)
328                 /* this enables the virtual consoles */
329                 conswitchp = &dummy_con;
330 #endif  
331                 return 0;
332         }
333         return -1;
334 }
335 __setup("x11=", x11_setup);
336
337 /*
338  * Local variables:
339  * c-basic-offset: 8
340  * End:
341  */