• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
461