Staging: meilhaus: Use DEFINE_SPINLOCK
[safe/jmp/linux-2.6] / drivers / staging / meilhaus / memain.h
1 /*
2  * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
3  *
4  * Source File : memain.h
5  * Author      : GG (Guenter Gebhardt)  <g.gebhardt@meilhaus.de>
6  */
7
8 #ifndef _MEMAIN_H_
9 #define _MEMAIN_H_
10
11 #include "meinternal.h"
12
13 #include "meids.h"
14 #include "medebug.h"
15
16 #include "medevice.h"
17 /*#include "me1000_device.h"
18 #include "me1400_device.h"
19 #include "me1600_device.h"*/
20 #include "me4600_device.h"
21 /*#include "me6000_device.h"
22 #include "me0600_device.h"
23 #include "me8100_device.h"
24 #include "me8200_device.h"
25 #include "me0900_device.h"*/
26 #include "medummy.h"
27
28 #ifdef __KERNEL__
29
30 /*=============================================================================
31   PCI device table.
32   This is used by modprobe to translate PCI IDs to drivers.
33   ===========================================================================*/
34
35 static struct pci_device_id me_pci_table[] __devinitdata = {
36         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000, PCI_ANY_ID,
37          PCI_ANY_ID, 0, 0, 0},
38         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_A, PCI_ANY_ID,
39          PCI_ANY_ID, 0, 0, 0},
40         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_B, PCI_ANY_ID,
41          PCI_ANY_ID, 0, 0, 0},
42
43         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1400, PCI_ANY_ID,
44          PCI_ANY_ID, 0, 0, 0},
45         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140A, PCI_ANY_ID,
46          PCI_ANY_ID, 0, 0, 0},
47         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140B, PCI_ANY_ID,
48          PCI_ANY_ID, 0, 0, 0},
49         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14E0, PCI_ANY_ID,
50          PCI_ANY_ID, 0, 0, 0},
51         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EA, PCI_ANY_ID,
52          PCI_ANY_ID, 0, 0, 0},
53         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EB, PCI_ANY_ID,
54          PCI_ANY_ID, 0, 0, 0},
55         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140C, PCI_ANY_ID,
56          PCI_ANY_ID, 0, 0, 0},
57         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140D, PCI_ANY_ID,
58          PCI_ANY_ID, 0, 0, 0},
59
60         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_4U, PCI_ANY_ID,
61          PCI_ANY_ID, 0, 0, 0},
62         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_8U, PCI_ANY_ID,
63          PCI_ANY_ID, 0, 0, 0},
64         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_12U, PCI_ANY_ID,
65          PCI_ANY_ID, 0, 0, 0},
66         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U, PCI_ANY_ID,
67          PCI_ANY_ID, 0, 0, 0},
68         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I,
69          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
70
71         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4610, PCI_ANY_ID,
72          PCI_ANY_ID, 0, 0, 0},
73         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650, PCI_ANY_ID,
74          PCI_ANY_ID, 0, 0, 0},
75         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660, PCI_ANY_ID,
76          PCI_ANY_ID, 0, 0, 0},
77         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I, PCI_ANY_ID,
78          PCI_ANY_ID, 0, 0, 0},
79         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670, PCI_ANY_ID,
80          PCI_ANY_ID, 0, 0, 0},
81         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I, PCI_ANY_ID,
82          PCI_ANY_ID, 0, 0, 0},
83         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S, PCI_ANY_ID,
84          PCI_ANY_ID, 0, 0, 0},
85         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS, PCI_ANY_ID,
86          PCI_ANY_ID, 0, 0, 0},
87         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680, PCI_ANY_ID,
88          PCI_ANY_ID, 0, 0, 0},
89         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I, PCI_ANY_ID,
90          PCI_ANY_ID, 0, 0, 0},
91         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S, PCI_ANY_ID,
92          PCI_ANY_ID, 0, 0, 0},
93         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS, PCI_ANY_ID,
94          PCI_ANY_ID, 0, 0, 0},
95
96         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6004, PCI_ANY_ID,
97          PCI_ANY_ID, 0, 0, 0},
98         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6008, PCI_ANY_ID,
99          PCI_ANY_ID, 0, 0, 0},
100         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME600F, PCI_ANY_ID,
101          PCI_ANY_ID, 0, 0, 0},
102
103         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6014, PCI_ANY_ID,
104          PCI_ANY_ID, 0, 0, 0},
105         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6018, PCI_ANY_ID,
106          PCI_ANY_ID, 0, 0, 0},
107         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME601F, PCI_ANY_ID,
108          PCI_ANY_ID, 0, 0, 0},
109
110         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6034, PCI_ANY_ID,
111          PCI_ANY_ID, 0, 0, 0},
112         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6038, PCI_ANY_ID,
113          PCI_ANY_ID, 0, 0, 0},
114         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME603F, PCI_ANY_ID,
115          PCI_ANY_ID, 0, 0, 0},
116
117         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6104, PCI_ANY_ID,
118          PCI_ANY_ID, 0, 0, 0},
119         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6108, PCI_ANY_ID,
120          PCI_ANY_ID, 0, 0, 0},
121         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME610F, PCI_ANY_ID,
122          PCI_ANY_ID, 0, 0, 0},
123
124         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6114, PCI_ANY_ID,
125          PCI_ANY_ID, 0, 0, 0},
126         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6118, PCI_ANY_ID,
127          PCI_ANY_ID, 0, 0, 0},
128         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME611F, PCI_ANY_ID,
129          PCI_ANY_ID, 0, 0, 0},
130
131         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6134, PCI_ANY_ID,
132          PCI_ANY_ID, 0, 0, 0},
133         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6138, PCI_ANY_ID,
134          PCI_ANY_ID, 0, 0, 0},
135         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME613F, PCI_ANY_ID,
136          PCI_ANY_ID, 0, 0, 0},
137
138         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6044, PCI_ANY_ID,
139          PCI_ANY_ID, 0, 0, 0},
140         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6048, PCI_ANY_ID,
141          PCI_ANY_ID, 0, 0, 0},
142         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME604F, PCI_ANY_ID,
143          PCI_ANY_ID, 0, 0, 0},
144
145         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6054, PCI_ANY_ID,
146          PCI_ANY_ID, 0, 0, 0},
147         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6058, PCI_ANY_ID,
148          PCI_ANY_ID, 0, 0, 0},
149         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME605F, PCI_ANY_ID,
150          PCI_ANY_ID, 0, 0, 0},
151
152         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6074, PCI_ANY_ID,
153          PCI_ANY_ID, 0, 0, 0},
154         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6078, PCI_ANY_ID,
155          PCI_ANY_ID, 0, 0, 0},
156         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME607F, PCI_ANY_ID,
157          PCI_ANY_ID, 0, 0, 0},
158
159         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6144, PCI_ANY_ID,
160          PCI_ANY_ID, 0, 0, 0},
161         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6148, PCI_ANY_ID,
162          PCI_ANY_ID, 0, 0, 0},
163         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME614F, PCI_ANY_ID,
164          PCI_ANY_ID, 0, 0, 0},
165
166         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6154, PCI_ANY_ID,
167          PCI_ANY_ID, 0, 0, 0},
168         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6158, PCI_ANY_ID,
169          PCI_ANY_ID, 0, 0, 0},
170         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME615F, PCI_ANY_ID,
171          PCI_ANY_ID, 0, 0, 0},
172
173         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6174, PCI_ANY_ID,
174          PCI_ANY_ID, 0, 0, 0},
175         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6178, PCI_ANY_ID,
176          PCI_ANY_ID, 0, 0, 0},
177         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME617F, PCI_ANY_ID,
178          PCI_ANY_ID, 0, 0, 0},
179
180         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6259, PCI_ANY_ID,
181          PCI_ANY_ID, 0, 0, 0},
182
183         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6359, PCI_ANY_ID,
184          PCI_ANY_ID, 0, 0, 0},
185
186         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0630, PCI_ANY_ID,
187          PCI_ANY_ID, 0, 0, 0},
188
189         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_A, PCI_ANY_ID,
190          PCI_ANY_ID, 0, 0, 0},
191         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_B, PCI_ANY_ID,
192          PCI_ANY_ID, 0, 0, 0},
193
194         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_A, PCI_ANY_ID,
195          PCI_ANY_ID, 0, 0, 0},
196         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_B, PCI_ANY_ID,
197          PCI_ANY_ID, 0, 0, 0},
198
199         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0940, PCI_ANY_ID,
200          PCI_ANY_ID, 0, 0, 0},
201         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0950, PCI_ANY_ID,
202          PCI_ANY_ID, 0, 0, 0},
203         {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0960, PCI_ANY_ID,
204          PCI_ANY_ID, 0, 0, 0},
205
206         {0}
207 };
208
209 MODULE_DEVICE_TABLE(pci, me_pci_table);
210
211 /*=============================================================================
212   USB device table.
213   This is used by modprobe to translate USB IDs to drivers.
214   ===========================================================================*/
215 /*
216 static struct usb_device_id me_usb_table[] __devinitdata = {
217         { USB_DEVICE(USB_VENDOR_ID_MEPHISTO_S1, USB_DEVICE_ID_MEPHISTO_S1) },
218         { 0 }
219 };
220
221 MODULE_DEVICE_TABLE (usb, me_usb_table);
222 */
223
224 /*=============================================================================
225   Templates
226   ===========================================================================*/
227
228 #define ME_LOCK_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS)    \
229 static int CALL(struct file *filep, TYPE *arg){ \
230         int err = 0; \
231         int k = 0; \
232         struct list_head *pos; \
233         me_device_t *device; \
234         TYPE karg; \
235         \
236         PDEBUG("executed.\n"); \
237         \
238         err = copy_from_user(&karg, arg, sizeof(TYPE)); \
239         if(err){ \
240                 PERROR("Can't copy arguments to kernel space\n"); \
241                 return -EFAULT; \
242         } \
243         \
244         down_read(&me_rwsem);   \
245         \
246         list_for_each(pos, &me_device_list){    \
247                 if(k == karg.device){   \
248                         device = list_entry(pos, me_device_t, list);    \
249                                 break;  \
250                 }       \
251                 k++;    \
252         }       \
253         \
254         if(pos == &me_device_list){ \
255                 PERROR("Invalid device number specified\n"); \
256                 karg.errno = ME_ERRNO_INVALID_DEVICE; \
257         } \
258         else{ \
259                 spin_lock(&me_lock);    \
260                 if((me_filep != NULL) && (me_filep != filep)){  \
261                         spin_unlock(&me_lock);  \
262                         PERROR("Resource is locked by another process\n");      \
263                         if(karg.lock == ME_LOCK_SET)    \
264                                 karg.errno = ME_ERRNO_LOCKED;   \
265                         else if(karg.lock == ME_LOCK_RELEASE)   \
266                                 karg.errno = ME_ERRNO_SUCCESS;  \
267                         else{   \
268                                 PERROR("Invalid lock specified\n");     \
269                                 karg.errno = ME_ERRNO_INVALID_LOCK;     \
270                         }\
271                 }       \
272                 else {  \
273                         me_count++;     \
274                         spin_unlock(&me_lock);  \
275                         \
276                         karg.errno = device->DEV_CALL ARGS;     \
277                         \
278                         spin_lock(&me_lock);    \
279                         me_count--;     \
280                         spin_unlock(&me_lock);  \
281                 }       \
282         } \
283         \
284         up_read(&me_rwsem);     \
285         \
286         err = copy_to_user(arg, &karg, sizeof(TYPE)); \
287         if(err){ \
288                 PERROR("Can't copy arguments back to user space\n"); \
289                 return -EFAULT; \
290         } \
291         \
292         return ME_ERRNO_SUCCESS; \
293 }
294
295 #define ME_IO_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS)      \
296 static int CALL(struct file *filep, TYPE *arg){ \
297         int err = 0; \
298         int k = 0; \
299         struct list_head *pos; \
300         me_device_t *device; \
301         TYPE karg; \
302         \
303         PDEBUG("executed.\n"); \
304         \
305         err = copy_from_user(&karg, arg, sizeof(TYPE)); \
306         if(err){ \
307                 PERROR("Can't copy arguments to kernel space\n"); \
308                 return -EFAULT; \
309         } \
310         \
311         down_read(&me_rwsem);   \
312         \
313         list_for_each(pos, &me_device_list){    \
314                 if(k == karg.device){   \
315                         device = list_entry(pos, me_device_t, list);    \
316                                 break;  \
317                 }       \
318                 k++;    \
319         }       \
320         \
321         if(pos == &me_device_list){ \
322                 PERROR("Invalid device number specified\n"); \
323                 karg.errno = ME_ERRNO_INVALID_DEVICE; \
324         } \
325         else{ \
326                 spin_lock(&me_lock);    \
327                 if((me_filep != NULL) && (me_filep != filep)){  \
328                         spin_unlock(&me_lock);  \
329                         PERROR("Resource is locked by another process\n");      \
330                         karg.errno = ME_ERRNO_LOCKED;   \
331                 }       \
332                 else {  \
333                         me_count++;     \
334                         spin_unlock(&me_lock);  \
335                         \
336                         karg.errno = device->DEV_CALL ARGS;     \
337                         \
338                         spin_lock(&me_lock);    \
339                         me_count--;     \
340                         spin_unlock(&me_lock);  \
341                 }       \
342         } \
343         \
344         up_read(&me_rwsem);     \
345         \
346         err = copy_to_user(arg, &karg, sizeof(TYPE)); \
347         if(err){ \
348                 PERROR("Can't copy arguments back to user space\n"); \
349                 return -EFAULT; \
350         } \
351  \
352         return ME_ERRNO_SUCCESS; \
353 }
354
355 #define ME_QUERY_MULTIPLEX_STR_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS)       \
356 static int CALL(struct file *filep, TYPE *arg){ \
357         int err = 0;    \
358         int k = 0;      \
359         struct list_head *pos;  \
360         me_device_t *device;    \
361         char *msg = NULL;       \
362         TYPE karg;      \
363         \
364         PDEBUG("executed.\n"); \
365         \
366         err = copy_from_user(&karg, arg, sizeof(TYPE)); \
367         if(err){        \
368                 PERROR("Can't copy arguments to kernel space\n");       \
369                 return -EFAULT; \
370         }       \
371         \
372         down_read(&me_rwsem);   \
373         \
374         list_for_each(pos, &me_device_list){    \
375                 if(k == karg.device){   \
376                         device = list_entry(pos, me_device_t, list);    \
377                                 break;  \
378                 }       \
379                 k++;    \
380         }       \
381         \
382         if(pos == &me_device_list){     \
383                 PERROR("Invalid device number specified\n");    \
384                 karg.errno = ME_ERRNO_INVALID_DEVICE;   \
385         }       \
386         else{   \
387                 karg.errno = device->DEV_CALL ARGS;     \
388                 if(!karg.errno){        \
389                         if((strlen(msg) + 1) > karg.count){     \
390                                 PERROR("User buffer for device name is to little\n");   \
391                                 karg.errno = ME_ERRNO_USER_BUFFER_SIZE; \
392                         }       \
393                         else{   \
394                                 err = copy_to_user(karg.name, msg, strlen(msg) + 1);    \
395                                 if(err){        \
396                                         PERROR("Can't copy device name to user space\n");       \
397                                         return -EFAULT; \
398                                 }       \
399                         }       \
400                 }       \
401         }       \
402         \
403         up_read(&me_rwsem);     \
404         \
405         err = copy_to_user(arg, &karg, sizeof(TYPE));   \
406         if(err){        \
407                 PERROR("Can't copy query back to user space\n");        \
408                 return -EFAULT; \
409         }       \
410         \
411         return ME_ERRNO_SUCCESS;        \
412 }
413
414 #define ME_QUERY_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS)   \
415 static int CALL(struct file *filep, TYPE *arg){ \
416         int err = 0;    \
417         int k = 0;      \
418         struct list_head *pos;  \
419         me_device_t *device;    \
420         TYPE karg;      \
421                 \
422         PDEBUG("executed.\n"); \
423          \
424         err = copy_from_user(&karg, arg, sizeof(TYPE)); \
425         if(err){        \
426                 PERROR("Can't copy arguments from user space\n");       \
427                 return -EFAULT; \
428         }       \
429         \
430         down_read(&me_rwsem);   \
431         \
432         list_for_each(pos, &me_device_list){    \
433                 if(k == karg.device){   \
434                         device = list_entry(pos, me_device_t, list);    \
435                         break;  \
436                 }       \
437                 k++;    \
438         }       \
439                 \
440         if(pos == &me_device_list){     \
441                 PERROR("Invalid device number specified\n");    \
442                 karg.errno = ME_ERRNO_INVALID_DEVICE;   \
443         }       \
444         else{   \
445                 karg.errno = device->DEV_CALL ARGS;     \
446         }       \
447         \
448         up_read(&me_rwsem);     \
449         \
450         err = copy_to_user(arg, &karg, sizeof(TYPE));   \
451         if(err){        \
452                 PERROR("Can't copy arguments to user space\n"); \
453                 return -EFAULT; \
454         }       \
455                 \
456         return ME_ERRNO_SUCCESS;        \
457 }
458
459 #endif //__KERNEL__
460 #endif