make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / sgi / char / streamable.c
1 /* $Id: streamable.c,v 1.1.1.1 2005/04/11 02:50:38 jack Exp $
2  *
3  * streamable.c: streamable devices. /dev/gfx
4  * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
5  *
6  * Major 10 is the streams clone device.  The IRIX Xsgi server just
7  * opens /dev/gfx and closes it inmediately.
8  *
9  */
10
11 #include <linux/fs.h>
12 #include <linux/miscdevice.h>
13 #include <linux/sched.h>
14 #include <linux/kbd_kern.h>
15 #include <linux/vt_kern.h>
16 #include <linux/smp_lock.h>
17 #include <asm/uaccess.h>
18 #include <asm/shmiq.h>
19 #include <asm/keyboard.h>
20 #include "graphics.h"
21
22
23 extern struct kbd_struct kbd_table [MAX_NR_CONSOLES];
24
25 /* console number where forwarding is enabled */
26 int forward_chars;
27
28 /* To which shmiq this keyboard is assigned */
29 int kbd_assigned_device;
30
31 /* previous kbd_mode for the forward_chars terminal */
32 int kbd_prev_mode;
33
34 /* Fetchs the strioctl information from user space for I_STR ioctls */
35 int
36 get_sioc (struct strioctl *sioc, unsigned long arg)
37 {
38         int v;
39
40         v = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct strioctl));
41         if (v)
42                 return v;
43         if (copy_from_user (sioc, (void *) arg, sizeof (struct strioctl)))
44                 return -EFAULT;
45
46         v = verify_area (VERIFY_WRITE, (void *) sioc->ic_dp, sioc->ic_len);
47         if (v)
48                 return v;
49         return 0;
50 }
51
52 /* /dev/gfx device */
53 static int
54 sgi_gfx_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
55 {
56         printk ("GFX: ioctl 0x%x %ld called\n", cmd, arg);
57         return 0;
58         return -EINVAL;
59 }
60
61 struct file_operations sgi_gfx_fops = {
62         ioctl:          sgi_gfx_ioctl,
63 };
64
65 static struct miscdevice dev_gfx = {
66         SGI_GFX_MINOR, "sgi-gfx", &sgi_gfx_fops
67 };
68
69 /* /dev/input/keyboard streams device */
70 static idevDesc sgi_kbd_desc = {
71         "keyboard",             /* devName */
72         "KEYBOARD",             /* devType */
73         240,                    /* nButtons */
74         0,                      /* nValuators */
75         0,                      /* nLEDs */
76         0,                      /* nStrDpys */
77         0,                      /* nIntDpys */
78         0,                      /* nBells */
79         IDEV_HAS_KEYMAP | IDEV_HAS_PCKBD
80 };
81
82 static int
83 sgi_kbd_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found)
84 {
85         *found = 1;
86
87         switch (cmd){
88
89         case IDEVINITDEVICE:
90                 return 0;
91
92         case IDEVGETDEVICEDESC:
93                 if (size >= sizeof (idevDesc)){
94                         if (copy_to_user (data, &sgi_kbd_desc, sizeof (sgi_kbd_desc)))
95                                 return -EFAULT;
96                         return 0;
97                 }
98                 return -EINVAL;
99
100         case IDEVGETKEYMAPDESC:
101                 if (size >= sizeof (idevKeymapDesc)){
102                         if (copy_to_user (data, "US", 3))
103                                 return -EFAULT;
104                         return 0;
105                 }
106                 return -EINVAL;
107         }
108         *found = 0;
109         return -EINVAL;
110 }
111
112 static int
113 sgi_keyb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
114 {
115         struct strioctl sioc;
116         int    f, v;
117
118         /* IRIX calls I_PUSH on the opened device, go figure */
119         if (cmd == I_PUSH)
120                 return 0;
121
122         if (cmd == I_STR){
123                 v = get_sioc (&sioc, arg);
124                 if (v)
125                         return v;
126
127                 /* Why like this?  Because this is a sample piece of code
128                  * that can be copied into other drivers and shows how to
129                  * call a stock IRIX xxx_wioctl routine
130                  *
131                  * The NULL is supposed to be a idevInfo, right now we
132                  * do not support this in our kernel.
133                  */
134                 return sgi_kbd_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f);
135         }
136
137         if (cmd == SHMIQ_ON){
138                 kbd_assigned_device = arg;
139                 forward_chars = fg_console + 1;
140                 kbd_prev_mode = kbd_table [fg_console].kbdmode;
141
142                 kbd_table [fg_console].kbdmode = VC_RAW;
143         } else if (cmd == SHMIQ_OFF && forward_chars){
144                 kbd_table [forward_chars-1].kbdmode = kbd_prev_mode;
145                 forward_chars = 0;
146         } else
147                 return -EINVAL;
148         return 0;
149 }
150
151 void
152 kbd_forward_char (int ch)
153 {
154         static struct shmqevent ev;
155
156         ev.data.flags  = (ch & 0200) ? 0 : 1;
157         ev.data.which  = ch;
158         ev.data.device = kbd_assigned_device + 0x11;
159         shmiq_push_event (&ev);
160 }
161
162 static int
163 sgi_keyb_open (struct inode *inode, struct file *file)
164 {
165         /* Nothing, but required by the misc driver */
166         return 0;
167 }
168
169 struct file_operations sgi_keyb_fops = {
170         ioctl:          sgi_keyb_ioctl,
171         open:           sgi_keyb_open,
172 };
173
174 static struct miscdevice dev_input_keyboard = {
175         SGI_STREAMS_KEYBOARD, "streams-keyboard", &sgi_keyb_fops
176 };
177
178 /* /dev/input/mouse streams device */
179 #define MOUSE_VALUATORS 2
180 static idevDesc sgi_mouse_desc = {
181         "mouse",                /* devName */
182         "MOUSE",                /* devType */
183         3,                      /* nButtons */
184         MOUSE_VALUATORS,        /* nValuators */
185         0,                      /* nLEDs */
186         0,                      /* nStrDpys */
187         0,                      /* nIntDpys */
188         0,                      /* nBells */
189         0                       /* flags */
190 };
191
192 static idevValuatorDesc mouse_default_valuator = {
193         200,                    /* hwMinRes */
194         200,                    /* hwMaxRes */
195         0,                      /* hwMinVal */
196         65000,                  /* hwMaxVal */
197         IDEV_EITHER,            /* possibleModes */
198         IDEV_ABSOLUTE,          /* default mode */
199         200,                    /* resolution */
200         0,                      /* minVal */
201         65000                   /* maxVal */
202 };
203
204 static int mouse_opened;
205 static idevValuatorDesc mouse_valuators [MOUSE_VALUATORS];
206
207 int
208 sgi_mouse_open (struct inode *inode, struct file *file)
209 {
210         int i;
211
212         if (mouse_opened)
213                 return -EBUSY;
214
215         mouse_opened = 1;
216         for (i = 0; i < MOUSE_VALUATORS; i++)
217                 mouse_valuators [i] = mouse_default_valuator;
218         return 0;
219 }
220
221 static int
222 sgi_mouse_close (struct inode *inode, struct file *filp)
223 {
224         lock_kernel();
225         mouse_opened = 0;
226         unlock_kernel();
227         return 0;
228 }
229
230 static int
231 sgi_mouse_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found)
232 {
233         *found = 1;
234
235         switch (cmd){
236         case IDEVINITDEVICE:
237                 return 0;
238
239         case IDEVGETDEVICEDESC:
240                 if (size >= sizeof (idevDesc)){
241                         if (copy_to_user (data, &sgi_mouse_desc, sizeof (sgi_mouse_desc)))
242                                 return -EFAULT;
243                         return 0;
244                 }
245                 return -EINVAL;
246
247         case IDEVGETVALUATORDESC: {
248                 idevGetSetValDesc request, *ureq = (idevGetSetValDesc *) data;
249
250                 if (size < sizeof (idevGetSetValDesc))
251                         return -EINVAL;
252
253                 if (copy_from_user (&request, data, sizeof (request)))
254                         return -EFAULT;
255                 if (request.valNum >= MOUSE_VALUATORS)
256                         return -EINVAL;
257                 if (copy_to_user ((void *)&ureq->desc,
258                                   (void *)&mouse_valuators [request.valNum],
259                                   sizeof (idevValuatorDesc)))
260                         return -EFAULT;
261                 return 0;
262         }
263         }
264         *found = 0;
265         return -EINVAL;
266 }
267
268 static int
269 sgi_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
270 {
271         struct strioctl sioc;
272         int    f, v;
273
274         /* IRIX calls I_PUSH on the opened device, go figure */
275         switch (cmd){
276         case I_PUSH:
277                 return 0;
278
279         case I_STR:
280                 v = get_sioc (&sioc, arg);
281                 if (v)
282                         return v;
283
284                 /* Why like this?  Because this is a sample piece of code
285                  * that can be copied into other drivers and shows how to
286                  * call a stock IRIX xxx_wioctl routine
287                  *
288                  * The NULL is supposed to be a idevInfo, right now we
289                  * do not support this in our kernel.
290                  */
291                 return sgi_mouse_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f);
292
293         case SHMIQ_ON:
294         case SHMIQ_OFF:
295                 return 0;
296         }
297         return 0;
298 }
299
300 struct file_operations sgi_mouse_fops = {
301         ioctl:          sgi_mouse_ioctl,
302         open:           sgi_mouse_open,
303         release:        sgi_mouse_close,
304 };
305
306 /* /dev/input/mouse */
307 static struct miscdevice dev_input_mouse = {
308         SGI_STREAMS_KEYBOARD, "streams-mouse", &sgi_mouse_fops
309 };
310
311 void
312 streamable_init (void)
313 {
314         printk ("streamable misc devices registered (keyb:%d, gfx:%d)\n",
315                 SGI_STREAMS_KEYBOARD, SGI_GFX_MINOR);
316
317         misc_register (&dev_gfx);
318         misc_register (&dev_input_keyboard);
319         misc_register (&dev_input_mouse);
320 }