diff options
Diffstat (limited to 'drivers/staging/me4000/me4000.c')
-rw-r--r-- | drivers/staging/me4000/me4000.c | 6109 |
1 files changed, 0 insertions, 6109 deletions
diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c deleted file mode 100644 index 01017b731d0..00000000000 --- a/drivers/staging/me4000/me4000.c +++ /dev/null | |||
@@ -1,6109 +0,0 @@ | |||
1 | /* Device driver for Meilhaus ME-4000 board family. | ||
2 | * ================================================ | ||
3 | * | ||
4 | * Copyright (C) 2003 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
5 | * | ||
6 | * This file is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * | ||
20 | * Author: Guenter Gebhardt <g.gebhardt@meilhaus.de> | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/fs.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/unistd.h> | ||
32 | #include <linux/list.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/types.h> | ||
35 | #include <linux/poll.h> | ||
36 | #include <linux/vmalloc.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <asm/pgtable.h> | ||
39 | #include <linux/uaccess.h> | ||
40 | #include <linux/io.h> | ||
41 | #include <asm/system.h> | ||
42 | |||
43 | /* Include-File for the Meilhaus ME-4000 I/O board */ | ||
44 | #include "me4000.h" | ||
45 | #include "me4000_firmware.h" | ||
46 | #include "me4610_firmware.h" | ||
47 | |||
48 | /* Administrative stuff for modinfo */ | ||
49 | MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>"); | ||
50 | MODULE_DESCRIPTION | ||
51 | ("Device Driver Module for Meilhaus ME-4000 boards version 1.0.5"); | ||
52 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-4000 Multi I/O boards"); | ||
53 | MODULE_LICENSE("GPL"); | ||
54 | |||
55 | /* Board specific data are kept in a global list */ | ||
56 | static LIST_HEAD(me4000_board_info_list); | ||
57 | |||
58 | /* Major Device Numbers. 0 means to get it automatically from the System */ | ||
59 | static int me4000_ao_major_driver_no; | ||
60 | static int me4000_ai_major_driver_no; | ||
61 | static int me4000_dio_major_driver_no; | ||
62 | static int me4000_cnt_major_driver_no; | ||
63 | static int me4000_ext_int_major_driver_no; | ||
64 | |||
65 | /* Let the user specify a custom major driver number */ | ||
66 | module_param(me4000_ao_major_driver_no, int, 0); | ||
67 | MODULE_PARM_DESC(me4000_ao_major_driver_no, | ||
68 | "Major driver number for analog output (default 0)"); | ||
69 | |||
70 | module_param(me4000_ai_major_driver_no, int, 0); | ||
71 | MODULE_PARM_DESC(me4000_ai_major_driver_no, | ||
72 | "Major driver number for analog input (default 0)"); | ||
73 | |||
74 | module_param(me4000_dio_major_driver_no, int, 0); | ||
75 | MODULE_PARM_DESC(me4000_dio_major_driver_no, | ||
76 | "Major driver number digital I/O (default 0)"); | ||
77 | |||
78 | module_param(me4000_cnt_major_driver_no, int, 0); | ||
79 | MODULE_PARM_DESC(me4000_cnt_major_driver_no, | ||
80 | "Major driver number for counter (default 0)"); | ||
81 | |||
82 | module_param(me4000_ext_int_major_driver_no, int, 0); | ||
83 | MODULE_PARM_DESC(me4000_ext_int_major_driver_no, | ||
84 | "Major driver number for external interrupt (default 0)"); | ||
85 | |||
86 | /*----------------------------------------------------------------------------- | ||
87 | Board detection and initialization | ||
88 | ---------------------------------------------------------------------------*/ | ||
89 | static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id); | ||
90 | static int me4000_xilinx_download(struct me4000_info *); | ||
91 | static int me4000_reset_board(struct me4000_info *); | ||
92 | |||
93 | static void clear_board_info_list(void); | ||
94 | static void release_ao_contexts(struct me4000_info *board_info); | ||
95 | /*----------------------------------------------------------------------------- | ||
96 | Stuff used by all device parts | ||
97 | ---------------------------------------------------------------------------*/ | ||
98 | static int me4000_open(struct inode *, struct file *); | ||
99 | static int me4000_release(struct inode *, struct file *); | ||
100 | |||
101 | static int me4000_get_user_info(struct me4000_user_info *, | ||
102 | struct me4000_info *board_info); | ||
103 | static int me4000_read_procmem(char *, char **, off_t, int, int *, void *); | ||
104 | |||
105 | /*----------------------------------------------------------------------------- | ||
106 | Analog output stuff | ||
107 | ---------------------------------------------------------------------------*/ | ||
108 | static ssize_t me4000_ao_write_sing(struct file *, const char *, size_t, | ||
109 | loff_t *); | ||
110 | static ssize_t me4000_ao_write_wrap(struct file *, const char *, size_t, | ||
111 | loff_t *); | ||
112 | static ssize_t me4000_ao_write_cont(struct file *, const char *, size_t, | ||
113 | loff_t *); | ||
114 | |||
115 | static int me4000_ao_ioctl_sing(struct inode *, struct file *, unsigned int, | ||
116 | unsigned long); | ||
117 | static int me4000_ao_ioctl_wrap(struct inode *, struct file *, unsigned int, | ||
118 | unsigned long); | ||
119 | static int me4000_ao_ioctl_cont(struct inode *, struct file *, unsigned int, | ||
120 | unsigned long); | ||
121 | |||
122 | static unsigned int me4000_ao_poll_cont(struct file *, poll_table *); | ||
123 | static int me4000_ao_fsync_cont(struct file *, struct dentry *, int); | ||
124 | |||
125 | static int me4000_ao_start(unsigned long *, struct me4000_ao_context *); | ||
126 | static int me4000_ao_stop(struct me4000_ao_context *); | ||
127 | static int me4000_ao_immediate_stop(struct me4000_ao_context *); | ||
128 | static int me4000_ao_timer_set_divisor(u32 *, struct me4000_ao_context *); | ||
129 | static int me4000_ao_preload(struct me4000_ao_context *); | ||
130 | static int me4000_ao_preload_update(struct me4000_ao_context *); | ||
131 | static int me4000_ao_ex_trig_set_edge(int *, struct me4000_ao_context *); | ||
132 | static int me4000_ao_ex_trig_enable(struct me4000_ao_context *); | ||
133 | static int me4000_ao_ex_trig_disable(struct me4000_ao_context *); | ||
134 | static int me4000_ao_prepare(struct me4000_ao_context *ao_info); | ||
135 | static int me4000_ao_reset(struct me4000_ao_context *ao_info); | ||
136 | static int me4000_ao_enable_do(struct me4000_ao_context *); | ||
137 | static int me4000_ao_disable_do(struct me4000_ao_context *); | ||
138 | static int me4000_ao_fsm_state(int *, struct me4000_ao_context *); | ||
139 | |||
140 | static int me4000_ao_simultaneous_ex_trig(struct me4000_ao_context *ao_context); | ||
141 | static int me4000_ao_simultaneous_sw(struct me4000_ao_context *ao_context); | ||
142 | static int me4000_ao_simultaneous_disable(struct me4000_ao_context *ao_context); | ||
143 | static int me4000_ao_simultaneous_update( | ||
144 | struct me4000_ao_channel_list *channels, | ||
145 | struct me4000_ao_context *ao_context); | ||
146 | |||
147 | static int me4000_ao_synchronous_ex_trig(struct me4000_ao_context *ao_context); | ||
148 | static int me4000_ao_synchronous_sw(struct me4000_ao_context *ao_context); | ||
149 | static int me4000_ao_synchronous_disable(struct me4000_ao_context *ao_context); | ||
150 | |||
151 | static int me4000_ao_ex_trig_timeout(unsigned long *arg, | ||
152 | struct me4000_ao_context *ao_context); | ||
153 | static int me4000_ao_get_free_buffer(unsigned long *arg, | ||
154 | struct me4000_ao_context *ao_context); | ||
155 | |||
156 | /*----------------------------------------------------------------------------- | ||
157 | Analog input stuff | ||
158 | ---------------------------------------------------------------------------*/ | ||
159 | static int me4000_ai_single(struct me4000_ai_single *, | ||
160 | struct me4000_ai_context *); | ||
161 | static int me4000_ai_ioctl_sing(struct inode *, struct file *, unsigned int, | ||
162 | unsigned long); | ||
163 | |||
164 | static ssize_t me4000_ai_read(struct file *, char *, size_t, loff_t *); | ||
165 | static int me4000_ai_ioctl_sw(struct inode *, struct file *, unsigned int, | ||
166 | unsigned long); | ||
167 | static unsigned int me4000_ai_poll(struct file *, poll_table *); | ||
168 | static int me4000_ai_fasync(int fd, struct file *file_p, int mode); | ||
169 | |||
170 | static int me4000_ai_ioctl_ext(struct inode *, struct file *, unsigned int, | ||
171 | unsigned long); | ||
172 | |||
173 | static int me4000_ai_prepare(struct me4000_ai_context *ai_context); | ||
174 | static int me4000_ai_reset(struct me4000_ai_context *ai_context); | ||
175 | static int me4000_ai_config(struct me4000_ai_config *, | ||
176 | struct me4000_ai_context *); | ||
177 | static int me4000_ai_start(struct me4000_ai_context *); | ||
178 | static int me4000_ai_start_ex(unsigned long *, struct me4000_ai_context *); | ||
179 | static int me4000_ai_stop(struct me4000_ai_context *); | ||
180 | static int me4000_ai_immediate_stop(struct me4000_ai_context *); | ||
181 | static int me4000_ai_ex_trig_enable(struct me4000_ai_context *); | ||
182 | static int me4000_ai_ex_trig_disable(struct me4000_ai_context *); | ||
183 | static int me4000_ai_ex_trig_setup(struct me4000_ai_trigger *, | ||
184 | struct me4000_ai_context *); | ||
185 | static int me4000_ai_sc_setup(struct me4000_ai_sc *arg, | ||
186 | struct me4000_ai_context *ai_context); | ||
187 | static int me4000_ai_offset_enable(struct me4000_ai_context *ai_context); | ||
188 | static int me4000_ai_offset_disable(struct me4000_ai_context *ai_context); | ||
189 | static int me4000_ai_fullscale_enable(struct me4000_ai_context *ai_context); | ||
190 | static int me4000_ai_fullscale_disable(struct me4000_ai_context *ai_context); | ||
191 | static int me4000_ai_fsm_state(int *arg, struct me4000_ai_context *ai_context); | ||
192 | static int me4000_ai_get_count_buffer(unsigned long *arg, | ||
193 | struct me4000_ai_context *ai_context); | ||
194 | |||
195 | /*----------------------------------------------------------------------------- | ||
196 | EEPROM stuff | ||
197 | ---------------------------------------------------------------------------*/ | ||
198 | static int me4000_eeprom_read(struct me4000_eeprom *arg, | ||
199 | struct me4000_ai_context *ai_context); | ||
200 | static int me4000_eeprom_write(struct me4000_eeprom *arg, | ||
201 | struct me4000_ai_context *ai_context); | ||
202 | |||
203 | /*----------------------------------------------------------------------------- | ||
204 | Digital I/O stuff | ||
205 | ---------------------------------------------------------------------------*/ | ||
206 | static int me4000_dio_ioctl(struct inode *, struct file *, unsigned int, | ||
207 | unsigned long); | ||
208 | static int me4000_dio_config(struct me4000_dio_config *, | ||
209 | struct me4000_dio_context *); | ||
210 | static int me4000_dio_get_byte(struct me4000_dio_byte *, | ||
211 | struct me4000_dio_context *); | ||
212 | static int me4000_dio_set_byte(struct me4000_dio_byte *, | ||
213 | struct me4000_dio_context *); | ||
214 | static int me4000_dio_reset(struct me4000_dio_context *); | ||
215 | |||
216 | /*----------------------------------------------------------------------------- | ||
217 | Counter stuff | ||
218 | ---------------------------------------------------------------------------*/ | ||
219 | static int me4000_cnt_ioctl(struct inode *, struct file *, unsigned int, | ||
220 | unsigned long); | ||
221 | static int me4000_cnt_config(struct me4000_cnt_config *, | ||
222 | struct me4000_cnt_context *); | ||
223 | static int me4000_cnt_read(struct me4000_cnt *, struct me4000_cnt_context *); | ||
224 | static int me4000_cnt_write(struct me4000_cnt *, struct me4000_cnt_context *); | ||
225 | static int me4000_cnt_reset(struct me4000_cnt_context *); | ||
226 | |||
227 | /*----------------------------------------------------------------------------- | ||
228 | External interrupt routines | ||
229 | ---------------------------------------------------------------------------*/ | ||
230 | static int me4000_ext_int_ioctl(struct inode *, struct file *, unsigned int, | ||
231 | unsigned long); | ||
232 | static int me4000_ext_int_enable(struct me4000_ext_int_context *); | ||
233 | static int me4000_ext_int_disable(struct me4000_ext_int_context *); | ||
234 | static int me4000_ext_int_count(unsigned long *arg, | ||
235 | struct me4000_ext_int_context *ext_int_context); | ||
236 | static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode); | ||
237 | |||
238 | /*----------------------------------------------------------------------------- | ||
239 | The interrupt service routines | ||
240 | ---------------------------------------------------------------------------*/ | ||
241 | static irqreturn_t me4000_ao_isr(int, void *); | ||
242 | static irqreturn_t me4000_ai_isr(int, void *); | ||
243 | static irqreturn_t me4000_ext_int_isr(int, void *); | ||
244 | |||
245 | /*----------------------------------------------------------------------------- | ||
246 | Inline functions | ||
247 | ---------------------------------------------------------------------------*/ | ||
248 | |||
249 | static inline int me4000_buf_count(struct me4000_circ_buf buf, int size) | ||
250 | { | ||
251 | return (buf.head - buf.tail) & (size - 1); | ||
252 | } | ||
253 | |||
254 | static inline int me4000_buf_space(struct me4000_circ_buf buf, int size) | ||
255 | { | ||
256 | return (buf.tail - (buf.head + 1)) & (size - 1); | ||
257 | } | ||
258 | |||
259 | static inline int me4000_values_to_end(struct me4000_circ_buf buf, int size) | ||
260 | { | ||
261 | int end; | ||
262 | int n; | ||
263 | end = size - buf.tail; | ||
264 | n = (buf.head + end) & (size - 1); | ||
265 | return (n < end) ? n : end; | ||
266 | } | ||
267 | |||
268 | static inline int me4000_space_to_end(struct me4000_circ_buf buf, int size) | ||
269 | { | ||
270 | int end; | ||
271 | int n; | ||
272 | |||
273 | end = size - 1 - buf.head; | ||
274 | n = (end + buf.tail) & (size - 1); | ||
275 | return (n <= end) ? n : (end + 1); | ||
276 | } | ||
277 | |||
278 | static inline void me4000_outb(unsigned char value, unsigned long port) | ||
279 | { | ||
280 | PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port); | ||
281 | outb(value, port); | ||
282 | } | ||
283 | |||
284 | static inline void me4000_outl(unsigned long value, unsigned long port) | ||
285 | { | ||
286 | PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port); | ||
287 | outl(value, port); | ||
288 | } | ||
289 | |||
290 | static inline unsigned long me4000_inl(unsigned long port) | ||
291 | { | ||
292 | unsigned long value; | ||
293 | value = inl(port); | ||
294 | PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port); | ||
295 | return value; | ||
296 | } | ||
297 | |||
298 | static inline unsigned char me4000_inb(unsigned long port) | ||
299 | { | ||
300 | unsigned char value; | ||
301 | value = inb(port); | ||
302 | PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port); | ||
303 | return value; | ||
304 | } | ||
305 | |||
306 | static struct pci_driver me4000_driver = { | ||
307 | .name = ME4000_NAME, | ||
308 | .id_table = me4000_pci_table, | ||
309 | .probe = me4000_probe | ||
310 | }; | ||
311 | |||
312 | static const struct file_operations me4000_ao_fops_sing = { | ||
313 | .owner = THIS_MODULE, | ||
314 | .write = me4000_ao_write_sing, | ||
315 | .ioctl = me4000_ao_ioctl_sing, | ||
316 | .open = me4000_open, | ||
317 | .release = me4000_release, | ||
318 | }; | ||
319 | |||
320 | static const struct file_operations me4000_ao_fops_wrap = { | ||
321 | .owner = THIS_MODULE, | ||
322 | .write = me4000_ao_write_wrap, | ||
323 | .ioctl = me4000_ao_ioctl_wrap, | ||
324 | .open = me4000_open, | ||
325 | .release = me4000_release, | ||
326 | }; | ||
327 | |||
328 | static const struct file_operations me4000_ao_fops_cont = { | ||
329 | .owner = THIS_MODULE, | ||
330 | .write = me4000_ao_write_cont, | ||
331 | .poll = me4000_ao_poll_cont, | ||
332 | .ioctl = me4000_ao_ioctl_cont, | ||
333 | .open = me4000_open, | ||
334 | .release = me4000_release, | ||
335 | .fsync = me4000_ao_fsync_cont, | ||
336 | }; | ||
337 | |||
338 | static const struct file_operations me4000_ai_fops_sing = { | ||
339 | .owner = THIS_MODULE, | ||
340 | .ioctl = me4000_ai_ioctl_sing, | ||
341 | .open = me4000_open, | ||
342 | .release = me4000_release, | ||
343 | }; | ||
344 | |||
345 | static const struct file_operations me4000_ai_fops_cont_sw = { | ||
346 | .owner = THIS_MODULE, | ||
347 | .read = me4000_ai_read, | ||
348 | .poll = me4000_ai_poll, | ||
349 | .ioctl = me4000_ai_ioctl_sw, | ||
350 | .open = me4000_open, | ||
351 | .release = me4000_release, | ||
352 | .fasync = me4000_ai_fasync, | ||
353 | }; | ||
354 | |||
355 | static const struct file_operations me4000_ai_fops_cont_et = { | ||
356 | .owner = THIS_MODULE, | ||
357 | .read = me4000_ai_read, | ||
358 | .poll = me4000_ai_poll, | ||
359 | .ioctl = me4000_ai_ioctl_ext, | ||
360 | .open = me4000_open, | ||
361 | .release = me4000_release, | ||
362 | }; | ||
363 | |||
364 | static const struct file_operations me4000_ai_fops_cont_et_value = { | ||
365 | .owner = THIS_MODULE, | ||
366 | .read = me4000_ai_read, | ||
367 | .poll = me4000_ai_poll, | ||
368 | .ioctl = me4000_ai_ioctl_ext, | ||
369 | .open = me4000_open, | ||
370 | .release = me4000_release, | ||
371 | }; | ||
372 | |||
373 | static const struct file_operations me4000_ai_fops_cont_et_chanlist = { | ||
374 | .owner = THIS_MODULE, | ||
375 | .read = me4000_ai_read, | ||
376 | .poll = me4000_ai_poll, | ||
377 | .ioctl = me4000_ai_ioctl_ext, | ||
378 | .open = me4000_open, | ||
379 | .release = me4000_release, | ||
380 | }; | ||
381 | |||
382 | static const struct file_operations me4000_dio_fops = { | ||
383 | .owner = THIS_MODULE, | ||
384 | .ioctl = me4000_dio_ioctl, | ||
385 | .open = me4000_open, | ||
386 | .release = me4000_release, | ||
387 | }; | ||
388 | |||
389 | static const struct file_operations me4000_cnt_fops = { | ||
390 | .owner = THIS_MODULE, | ||
391 | .ioctl = me4000_cnt_ioctl, | ||
392 | .open = me4000_open, | ||
393 | .release = me4000_release, | ||
394 | }; | ||
395 | |||
396 | static const struct file_operations me4000_ext_int_fops = { | ||
397 | .owner = THIS_MODULE, | ||
398 | .ioctl = me4000_ext_int_ioctl, | ||
399 | .open = me4000_open, | ||
400 | .release = me4000_release, | ||
401 | .fasync = me4000_ext_int_fasync, | ||
402 | }; | ||
403 | |||
404 | static const struct file_operations *me4000_ao_fops_array[] = { | ||
405 | /* single operations */ | ||
406 | &me4000_ao_fops_sing, | ||
407 | /* wraparound operations */ | ||
408 | &me4000_ao_fops_wrap, | ||
409 | /* continuous operations */ | ||
410 | &me4000_ao_fops_cont, | ||
411 | }; | ||
412 | |||
413 | static const struct file_operations *me4000_ai_fops_array[] = { | ||
414 | /* single operations */ | ||
415 | &me4000_ai_fops_sing, | ||
416 | /* continuous operations with software start */ | ||
417 | &me4000_ai_fops_cont_sw, | ||
418 | /* continuous operations with external trigger */ | ||
419 | &me4000_ai_fops_cont_et, | ||
420 | /* sample values by external trigger */ | ||
421 | &me4000_ai_fops_cont_et_value, | ||
422 | /* work through one channel list by external trigger */ | ||
423 | &me4000_ai_fops_cont_et_chanlist, | ||
424 | }; | ||
425 | |||
426 | static int __init me4000_init_module(void) | ||
427 | { | ||
428 | int result; | ||
429 | |||
430 | CALL_PDEBUG("init_module() is executed\n"); | ||
431 | |||
432 | /* Register driver capabilities */ | ||
433 | result = pci_register_driver(&me4000_driver); | ||
434 | PDEBUG("init_module():%d devices detected\n", result); | ||
435 | if (result < 0) { | ||
436 | printk(KERN_ERR "ME4000:init_module():Can't register driver\n"); | ||
437 | goto INIT_ERROR_1; | ||
438 | } | ||
439 | |||
440 | /* Allocate major number for analog output */ | ||
441 | result = | ||
442 | register_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME, | ||
443 | &me4000_ao_fops_sing); | ||
444 | if (result < 0) { | ||
445 | printk(KERN_ERR "ME4000:init_module():Can't get AO major no\n"); | ||
446 | goto INIT_ERROR_2; | ||
447 | } else { | ||
448 | me4000_ao_major_driver_no = result; | ||
449 | } | ||
450 | PDEBUG("init_module():Major driver number for AO = %ld\n", | ||
451 | me4000_ao_major_driver_no); | ||
452 | |||
453 | /* Allocate major number for analog input */ | ||
454 | result = | ||
455 | register_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME, | ||
456 | &me4000_ai_fops_sing); | ||
457 | if (result < 0) { | ||
458 | printk(KERN_ERR "ME4000:init_module():Can't get AI major no\n"); | ||
459 | goto INIT_ERROR_3; | ||
460 | } else { | ||
461 | me4000_ai_major_driver_no = result; | ||
462 | } | ||
463 | PDEBUG("init_module():Major driver number for AI = %ld\n", | ||
464 | me4000_ai_major_driver_no); | ||
465 | |||
466 | /* Allocate major number for digital I/O */ | ||
467 | result = | ||
468 | register_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME, | ||
469 | &me4000_dio_fops); | ||
470 | if (result < 0) { | ||
471 | printk(KERN_ERR | ||
472 | "ME4000:init_module():Can't get DIO major no\n"); | ||
473 | goto INIT_ERROR_4; | ||
474 | } else { | ||
475 | me4000_dio_major_driver_no = result; | ||
476 | } | ||
477 | PDEBUG("init_module():Major driver number for DIO = %ld\n", | ||
478 | me4000_dio_major_driver_no); | ||
479 | |||
480 | /* Allocate major number for counter */ | ||
481 | result = | ||
482 | register_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME, | ||
483 | &me4000_cnt_fops); | ||
484 | if (result < 0) { | ||
485 | printk(KERN_ERR | ||
486 | "ME4000:init_module():Can't get CNT major no\n"); | ||
487 | goto INIT_ERROR_5; | ||
488 | } else { | ||
489 | me4000_cnt_major_driver_no = result; | ||
490 | } | ||
491 | PDEBUG("init_module():Major driver number for CNT = %ld\n", | ||
492 | me4000_cnt_major_driver_no); | ||
493 | |||
494 | /* Allocate major number for external interrupt */ | ||
495 | result = | ||
496 | register_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME, | ||
497 | &me4000_ext_int_fops); | ||
498 | if (result < 0) { | ||
499 | printk(KERN_ERR | ||
500 | "ME4000:init_module():Can't get major no for external interrupt\n"); | ||
501 | goto INIT_ERROR_6; | ||
502 | } else { | ||
503 | me4000_ext_int_major_driver_no = result; | ||
504 | } | ||
505 | PDEBUG | ||
506 | ("init_module():Major driver number for external interrupt = %ld\n", | ||
507 | me4000_ext_int_major_driver_no); | ||
508 | |||
509 | /* Create the /proc/me4000 entry */ | ||
510 | if (!create_proc_read_entry | ||
511 | ("me4000", 0, NULL, me4000_read_procmem, NULL)) { | ||
512 | result = -ENODEV; | ||
513 | printk(KERN_ERR | ||
514 | "ME4000:init_module():Can't create proc entry\n"); | ||
515 | goto INIT_ERROR_7; | ||
516 | } | ||
517 | |||
518 | return 0; | ||
519 | |||
520 | INIT_ERROR_7: | ||
521 | unregister_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME); | ||
522 | |||
523 | INIT_ERROR_6: | ||
524 | unregister_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME); | ||
525 | |||
526 | INIT_ERROR_5: | ||
527 | unregister_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME); | ||
528 | |||
529 | INIT_ERROR_4: | ||
530 | unregister_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME); | ||
531 | |||
532 | INIT_ERROR_3: | ||
533 | unregister_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME); | ||
534 | |||
535 | INIT_ERROR_2: | ||
536 | pci_unregister_driver(&me4000_driver); | ||
537 | clear_board_info_list(); | ||
538 | |||
539 | INIT_ERROR_1: | ||
540 | return result; | ||
541 | } | ||
542 | |||
543 | module_init(me4000_init_module); | ||
544 | |||
545 | static void clear_board_info_list(void) | ||
546 | { | ||
547 | struct me4000_info *board_info, *board_info_safe; | ||
548 | struct me4000_ao_context *ao_context, *ao_context_safe; | ||
549 | |||
550 | /* Clear context lists */ | ||
551 | list_for_each_entry(board_info, &me4000_board_info_list, list) { | ||
552 | /* Clear analog output context list */ | ||
553 | list_for_each_entry_safe(ao_context, ao_context_safe, | ||
554 | &board_info->ao_context_list, list) { | ||
555 | me4000_ao_reset(ao_context); | ||
556 | free_irq(ao_context->irq, ao_context); | ||
557 | kfree(ao_context->circ_buf.buf); | ||
558 | list_del(&ao_context->list); | ||
559 | kfree(ao_context); | ||
560 | } | ||
561 | |||
562 | /* Clear analog input context */ | ||
563 | kfree(board_info->ai_context->circ_buf.buf); | ||
564 | kfree(board_info->ai_context); | ||
565 | |||
566 | /* Clear digital I/O context */ | ||
567 | kfree(board_info->dio_context); | ||
568 | |||
569 | /* Clear counter context */ | ||
570 | kfree(board_info->cnt_context); | ||
571 | |||
572 | /* Clear external interrupt context */ | ||
573 | kfree(board_info->ext_int_context); | ||
574 | } | ||
575 | |||
576 | /* Clear the board info list */ | ||
577 | list_for_each_entry_safe(board_info, board_info_safe, | ||
578 | &me4000_board_info_list, list) { | ||
579 | pci_release_regions(board_info->pci_dev_p); | ||
580 | list_del(&board_info->list); | ||
581 | kfree(board_info); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | static int get_registers(struct pci_dev *dev, struct me4000_info *board_info) | ||
586 | { | ||
587 | |||
588 | /*--------------------------- plx regbase ---------------------------------*/ | ||
589 | |||
590 | board_info->plx_regbase = pci_resource_start(dev, 1); | ||
591 | if (board_info->plx_regbase == 0) { | ||
592 | printk(KERN_ERR | ||
593 | "ME4000:get_registers():PCI base address 1 is not available\n"); | ||
594 | return -ENODEV; | ||
595 | } | ||
596 | board_info->plx_regbase_size = pci_resource_len(dev, 1); | ||
597 | |||
598 | PDEBUG | ||
599 | ("get_registers():PLX configuration registers at address 0x%4lX [0x%4lX]\n", | ||
600 | board_info->plx_regbase, board_info->plx_regbase_size); | ||
601 | |||
602 | /*--------------------------- me4000 regbase ------------------------------*/ | ||
603 | |||
604 | board_info->me4000_regbase = pci_resource_start(dev, 2); | ||
605 | if (board_info->me4000_regbase == 0) { | ||
606 | printk(KERN_ERR | ||
607 | "ME4000:get_registers():PCI base address 2 is not available\n"); | ||
608 | return -ENODEV; | ||
609 | } | ||
610 | board_info->me4000_regbase_size = pci_resource_len(dev, 2); | ||
611 | |||
612 | PDEBUG("get_registers():ME4000 registers at address 0x%4lX [0x%4lX]\n", | ||
613 | board_info->me4000_regbase, board_info->me4000_regbase_size); | ||
614 | |||
615 | /*--------------------------- timer regbase ------------------------------*/ | ||
616 | |||
617 | board_info->timer_regbase = pci_resource_start(dev, 3); | ||
618 | if (board_info->timer_regbase == 0) { | ||
619 | printk(KERN_ERR | ||
620 | "ME4000:get_registers():PCI base address 3 is not available\n"); | ||
621 | return -ENODEV; | ||
622 | } | ||
623 | board_info->timer_regbase_size = pci_resource_len(dev, 3); | ||
624 | |||
625 | PDEBUG("get_registers():Timer registers at address 0x%4lX [0x%4lX]\n", | ||
626 | board_info->timer_regbase, board_info->timer_regbase_size); | ||
627 | |||
628 | /*--------------------------- program regbase ------------------------------*/ | ||
629 | |||
630 | board_info->program_regbase = pci_resource_start(dev, 5); | ||
631 | if (board_info->program_regbase == 0) { | ||
632 | printk(KERN_ERR | ||
633 | "get_registers():ME4000:PCI base address 5 is not available\n"); | ||
634 | return -ENODEV; | ||
635 | } | ||
636 | board_info->program_regbase_size = pci_resource_len(dev, 5); | ||
637 | |||
638 | PDEBUG("get_registers():Program registers at address 0x%4lX [0x%4lX]\n", | ||
639 | board_info->program_regbase, board_info->program_regbase_size); | ||
640 | |||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int init_board_info(struct pci_dev *pci_dev_p, | ||
645 | struct me4000_info *board_info) | ||
646 | { | ||
647 | int i; | ||
648 | int result; | ||
649 | struct list_head *board_p; | ||
650 | board_info->pci_dev_p = pci_dev_p; | ||
651 | |||
652 | for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) { | ||
653 | if (me4000_boards[i].device_id == pci_dev_p->device) { | ||
654 | board_info->board_p = &me4000_boards[i]; | ||
655 | break; | ||
656 | } | ||
657 | } | ||
658 | if (i == ARRAY_SIZE(me4000_boards)) { | ||
659 | printk(KERN_ERR | ||
660 | "ME4000:init_board_info():Device ID not valid\n"); | ||
661 | return -ENODEV; | ||
662 | } | ||
663 | |||
664 | /* Get the index of the board in the global list */ | ||
665 | i = 0; | ||
666 | list_for_each(board_p, &me4000_board_info_list) { | ||
667 | if (board_p == &board_info->list) { | ||
668 | board_info->board_count = i; | ||
669 | break; | ||
670 | } | ||
671 | i++; | ||
672 | } | ||
673 | if (board_p == &me4000_board_info_list) { | ||
674 | printk(KERN_ERR | ||
675 | "ME4000:init_board_info():Cannot get index of board\n"); | ||
676 | return -ENODEV; | ||
677 | } | ||
678 | |||
679 | /* Init list head for analog output contexts */ | ||
680 | INIT_LIST_HEAD(&board_info->ao_context_list); | ||
681 | |||
682 | /* Init spin locks */ | ||
683 | spin_lock_init(&board_info->preload_lock); | ||
684 | spin_lock_init(&board_info->ai_ctrl_lock); | ||
685 | |||
686 | /* Get the serial number */ | ||
687 | result = pci_read_config_dword(pci_dev_p, 0x2C, &board_info->serial_no); | ||
688 | if (result != PCIBIOS_SUCCESSFUL) { | ||
689 | printk(KERN_WARNING | ||
690 | "ME4000:init_board_info: Can't get serial_no\n"); | ||
691 | return result; | ||
692 | } | ||
693 | PDEBUG("init_board_info():serial_no = 0x%x\n", board_info->serial_no); | ||
694 | |||
695 | /* Get the hardware revision */ | ||
696 | result = | ||
697 | pci_read_config_byte(pci_dev_p, 0x08, &board_info->hw_revision); | ||
698 | if (result != PCIBIOS_SUCCESSFUL) { | ||
699 | printk(KERN_WARNING | ||
700 | "ME4000:init_board_info():Can't get hw_revision\n"); | ||
701 | return result; | ||
702 | } | ||
703 | PDEBUG("init_board_info():hw_revision = 0x%x\n", | ||
704 | board_info->hw_revision); | ||
705 | |||
706 | /* Get the vendor id */ | ||
707 | board_info->vendor_id = pci_dev_p->vendor; | ||
708 | PDEBUG("init_board_info():vendor_id = 0x%x\n", board_info->vendor_id); | ||
709 | |||
710 | /* Get the device id */ | ||
711 | board_info->device_id = pci_dev_p->device; | ||
712 | PDEBUG("init_board_info():device_id = 0x%x\n", board_info->device_id); | ||
713 | |||
714 | /* Get the pci device number */ | ||
715 | board_info->pci_dev_no = PCI_FUNC(pci_dev_p->devfn); | ||
716 | PDEBUG("init_board_info():pci_func_no = 0x%x\n", | ||
717 | board_info->pci_func_no); | ||
718 | |||
719 | /* Get the pci slot number */ | ||
720 | board_info->pci_dev_no = PCI_SLOT(pci_dev_p->devfn); | ||
721 | PDEBUG("init_board_info():pci_dev_no = 0x%x\n", board_info->pci_dev_no); | ||
722 | |||
723 | /* Get the pci bus number */ | ||
724 | board_info->pci_bus_no = pci_dev_p->bus->number; | ||
725 | PDEBUG("init_board_info():pci_bus_no = 0x%x\n", board_info->pci_bus_no); | ||
726 | |||
727 | /* Get the irq assigned to the board */ | ||
728 | board_info->irq = pci_dev_p->irq; | ||
729 | PDEBUG("init_board_info():irq = %d\n", board_info->irq); | ||
730 | |||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static int alloc_ao_contexts(struct me4000_info *info) | ||
735 | { | ||
736 | int i; | ||
737 | int err; | ||
738 | struct me4000_ao_context *ao_context; | ||
739 | |||
740 | for (i = 0; i < info->board_p->ao.count; i++) { | ||
741 | ao_context = kzalloc(sizeof(struct me4000_ao_context), | ||
742 | GFP_KERNEL); | ||
743 | if (!ao_context) { | ||
744 | printk(KERN_ERR | ||
745 | "alloc_ao_contexts():Can't get memory for ao context\n"); | ||
746 | release_ao_contexts(info); | ||
747 | return -ENOMEM; | ||
748 | } | ||
749 | |||
750 | spin_lock_init(&ao_context->use_lock); | ||
751 | spin_lock_init(&ao_context->int_lock); | ||
752 | ao_context->irq = info->irq; | ||
753 | init_waitqueue_head(&ao_context->wait_queue); | ||
754 | ao_context->board_info = info; | ||
755 | |||
756 | if (info->board_p->ao.fifo_count) { | ||
757 | /* Allocate circular buffer */ | ||
758 | ao_context->circ_buf.buf = | ||
759 | kzalloc(ME4000_AO_BUFFER_SIZE, GFP_KERNEL); | ||
760 | if (!ao_context->circ_buf.buf) { | ||
761 | printk(KERN_ERR | ||
762 | "alloc_ao_contexts():Can't get circular buffer\n"); | ||
763 | release_ao_contexts(info); | ||
764 | return -ENOMEM; | ||
765 | } | ||
766 | |||
767 | /* Clear the circular buffer */ | ||
768 | ao_context->circ_buf.head = 0; | ||
769 | ao_context->circ_buf.tail = 0; | ||
770 | } | ||
771 | |||
772 | switch (i) { | ||
773 | case 0: | ||
774 | ao_context->ctrl_reg = | ||
775 | info->me4000_regbase + ME4000_AO_00_CTRL_REG; | ||
776 | ao_context->status_reg = | ||
777 | info->me4000_regbase + ME4000_AO_00_STATUS_REG; | ||
778 | ao_context->fifo_reg = | ||
779 | info->me4000_regbase + ME4000_AO_00_FIFO_REG; | ||
780 | ao_context->single_reg = | ||
781 | info->me4000_regbase + ME4000_AO_00_SINGLE_REG; | ||
782 | ao_context->timer_reg = | ||
783 | info->me4000_regbase + ME4000_AO_00_TIMER_REG; | ||
784 | ao_context->irq_status_reg = | ||
785 | info->me4000_regbase + ME4000_IRQ_STATUS_REG; | ||
786 | ao_context->preload_reg = | ||
787 | info->me4000_regbase + ME4000_AO_LOADSETREG_XX; | ||
788 | break; | ||
789 | case 1: | ||
790 | ao_context->ctrl_reg = | ||
791 | info->me4000_regbase + ME4000_AO_01_CTRL_REG; | ||
792 | ao_context->status_reg = | ||
793 | info->me4000_regbase + ME4000_AO_01_STATUS_REG; | ||
794 | ao_context->fifo_reg = | ||
795 | info->me4000_regbase + ME4000_AO_01_FIFO_REG; | ||
796 | ao_context->single_reg = | ||
797 | info->me4000_regbase + ME4000_AO_01_SINGLE_REG; | ||
798 | ao_context->timer_reg = | ||
799 | info->me4000_regbase + ME4000_AO_01_TIMER_REG; | ||
800 | ao_context->irq_status_reg = | ||
801 | info->me4000_regbase + ME4000_IRQ_STATUS_REG; | ||
802 | ao_context->preload_reg = | ||
803 | info->me4000_regbase + ME4000_AO_LOADSETREG_XX; | ||
804 | break; | ||
805 | case 2: | ||
806 | ao_context->ctrl_reg = | ||
807 | info->me4000_regbase + ME4000_AO_02_CTRL_REG; | ||
808 | ao_context->status_reg = | ||
809 | info->me4000_regbase + ME4000_AO_02_STATUS_REG; | ||
810 | ao_context->fifo_reg = | ||
811 | info->me4000_regbase + ME4000_AO_02_FIFO_REG; | ||
812 | ao_context->single_reg = | ||
813 | info->me4000_regbase + ME4000_AO_02_SINGLE_REG; | ||
814 | ao_context->timer_reg = | ||
815 | info->me4000_regbase + ME4000_AO_02_TIMER_REG; | ||
816 | ao_context->irq_status_reg = | ||
817 | info->me4000_regbase + ME4000_IRQ_STATUS_REG; | ||
818 | ao_context->preload_reg = | ||
819 | info->me4000_regbase + ME4000_AO_LOADSETREG_XX; | ||
820 | break; | ||
821 | case 3: | ||
822 | ao_context->ctrl_reg = | ||
823 | info->me4000_regbase + ME4000_AO_03_CTRL_REG; | ||
824 | ao_context->status_reg = | ||
825 | info->me4000_regbase + ME4000_AO_03_STATUS_REG; | ||
826 | ao_context->fifo_reg = | ||
827 | info->me4000_regbase + ME4000_AO_03_FIFO_REG; | ||
828 | ao_context->single_reg = | ||
829 | info->me4000_regbase + ME4000_AO_03_SINGLE_REG; | ||
830 | ao_context->timer_reg = | ||
831 | info->me4000_regbase + ME4000_AO_03_TIMER_REG; | ||
832 | ao_context->irq_status_reg = | ||
833 | info->me4000_regbase + ME4000_IRQ_STATUS_REG; | ||
834 | ao_context->preload_reg = | ||
835 | info->me4000_regbase + ME4000_AO_LOADSETREG_XX; | ||
836 | break; | ||
837 | default: | ||
838 | break; | ||
839 | } | ||
840 | |||
841 | if (info->board_p->ao.fifo_count) { | ||
842 | /* Request the interrupt line */ | ||
843 | err = | ||
844 | request_irq(ao_context->irq, me4000_ao_isr, | ||
845 | IRQF_DISABLED | IRQF_SHARED, | ||
846 | ME4000_NAME, ao_context); | ||
847 | if (err) { | ||
848 | printk(KERN_ERR | ||
849 | "%s:Can't get interrupt line", __func__); | ||
850 | kfree(ao_context->circ_buf.buf); | ||
851 | kfree(ao_context); | ||
852 | release_ao_contexts(info); | ||
853 | return -ENODEV; | ||
854 | } | ||
855 | } | ||
856 | |||
857 | list_add_tail(&ao_context->list, &info->ao_context_list); | ||
858 | ao_context->index = i; | ||
859 | } | ||
860 | |||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | static void release_ao_contexts(struct me4000_info *board_info) | ||
865 | { | ||
866 | struct me4000_ao_context *ao_context, *ao_context_safe; | ||
867 | |||
868 | /* Clear analog output context list */ | ||
869 | list_for_each_entry_safe(ao_context, ao_context_safe, | ||
870 | &board_info->ao_context_list, list) { | ||
871 | free_irq(ao_context->irq, ao_context); | ||
872 | kfree(ao_context->circ_buf.buf); | ||
873 | list_del(&ao_context->list); | ||
874 | kfree(ao_context); | ||
875 | } | ||
876 | } | ||
877 | |||
878 | static int alloc_ai_context(struct me4000_info *info) | ||
879 | { | ||
880 | struct me4000_ai_context *ai_context; | ||
881 | |||
882 | if (info->board_p->ai.count) { | ||
883 | ai_context = kzalloc(sizeof(struct me4000_ai_context), | ||
884 | GFP_KERNEL); | ||
885 | if (!ai_context) { | ||
886 | printk(KERN_ERR | ||
887 | "ME4000:alloc_ai_context():Can't get memory for ai context\n"); | ||
888 | return -ENOMEM; | ||
889 | } | ||
890 | |||
891 | info->ai_context = ai_context; | ||
892 | |||
893 | spin_lock_init(&ai_context->use_lock); | ||
894 | spin_lock_init(&ai_context->int_lock); | ||
895 | ai_context->number = 0; | ||
896 | ai_context->irq = info->irq; | ||
897 | init_waitqueue_head(&ai_context->wait_queue); | ||
898 | ai_context->board_info = info; | ||
899 | |||
900 | ai_context->ctrl_reg = | ||
901 | info->me4000_regbase + ME4000_AI_CTRL_REG; | ||
902 | ai_context->status_reg = | ||
903 | info->me4000_regbase + ME4000_AI_STATUS_REG; | ||
904 | ai_context->channel_list_reg = | ||
905 | info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG; | ||
906 | ai_context->data_reg = | ||
907 | info->me4000_regbase + ME4000_AI_DATA_REG; | ||
908 | ai_context->chan_timer_reg = | ||
909 | info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG; | ||
910 | ai_context->chan_pre_timer_reg = | ||
911 | info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG; | ||
912 | ai_context->scan_timer_low_reg = | ||
913 | info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG; | ||
914 | ai_context->scan_timer_high_reg = | ||
915 | info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG; | ||
916 | ai_context->scan_pre_timer_low_reg = | ||
917 | info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG; | ||
918 | ai_context->scan_pre_timer_high_reg = | ||
919 | info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG; | ||
920 | ai_context->start_reg = | ||
921 | info->me4000_regbase + ME4000_AI_START_REG; | ||
922 | ai_context->irq_status_reg = | ||
923 | info->me4000_regbase + ME4000_IRQ_STATUS_REG; | ||
924 | ai_context->sample_counter_reg = | ||
925 | info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG; | ||
926 | } | ||
927 | |||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static int alloc_dio_context(struct me4000_info *info) | ||
932 | { | ||
933 | struct me4000_dio_context *dio_context; | ||
934 | |||
935 | if (info->board_p->dio.count) { | ||
936 | dio_context = kzalloc(sizeof(struct me4000_dio_context), | ||
937 | GFP_KERNEL); | ||
938 | if (!dio_context) { | ||
939 | printk(KERN_ERR | ||
940 | "ME4000:alloc_dio_context():Can't get memory for dio context\n"); | ||
941 | return -ENOMEM; | ||
942 | } | ||
943 | |||
944 | info->dio_context = dio_context; | ||
945 | |||
946 | spin_lock_init(&dio_context->use_lock); | ||
947 | dio_context->board_info = info; | ||
948 | |||
949 | dio_context->dio_count = info->board_p->dio.count; | ||
950 | |||
951 | dio_context->dir_reg = | ||
952 | info->me4000_regbase + ME4000_DIO_DIR_REG; | ||
953 | dio_context->ctrl_reg = | ||
954 | info->me4000_regbase + ME4000_DIO_CTRL_REG; | ||
955 | dio_context->port_0_reg = | ||
956 | info->me4000_regbase + ME4000_DIO_PORT_0_REG; | ||
957 | dio_context->port_1_reg = | ||
958 | info->me4000_regbase + ME4000_DIO_PORT_1_REG; | ||
959 | dio_context->port_2_reg = | ||
960 | info->me4000_regbase + ME4000_DIO_PORT_2_REG; | ||
961 | dio_context->port_3_reg = | ||
962 | info->me4000_regbase + ME4000_DIO_PORT_3_REG; | ||
963 | } | ||
964 | |||
965 | return 0; | ||
966 | } | ||
967 | |||
968 | static int alloc_cnt_context(struct me4000_info *info) | ||
969 | { | ||
970 | struct me4000_cnt_context *cnt_context; | ||
971 | |||
972 | if (info->board_p->cnt.count) { | ||
973 | cnt_context = kzalloc(sizeof(struct me4000_cnt_context), | ||
974 | GFP_KERNEL); | ||
975 | if (!cnt_context) { | ||
976 | printk(KERN_ERR | ||
977 | "ME4000:alloc_cnt_context():Can't get memory for cnt context\n"); | ||
978 | return -ENOMEM; | ||
979 | } | ||
980 | |||
981 | info->cnt_context = cnt_context; | ||
982 | |||
983 | spin_lock_init(&cnt_context->use_lock); | ||
984 | cnt_context->board_info = info; | ||
985 | |||
986 | cnt_context->ctrl_reg = | ||
987 | info->timer_regbase + ME4000_CNT_CTRL_REG; | ||
988 | cnt_context->counter_0_reg = | ||
989 | info->timer_regbase + ME4000_CNT_COUNTER_0_REG; | ||
990 | cnt_context->counter_1_reg = | ||
991 | info->timer_regbase + ME4000_CNT_COUNTER_1_REG; | ||
992 | cnt_context->counter_2_reg = | ||
993 | info->timer_regbase + ME4000_CNT_COUNTER_2_REG; | ||
994 | } | ||
995 | |||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | static int alloc_ext_int_context(struct me4000_info *info) | ||
1000 | { | ||
1001 | struct me4000_ext_int_context *ext_int_context; | ||
1002 | |||
1003 | if (info->board_p->cnt.count) { | ||
1004 | ext_int_context = | ||
1005 | kzalloc(sizeof(struct me4000_ext_int_context), GFP_KERNEL); | ||
1006 | if (!ext_int_context) { | ||
1007 | printk(KERN_ERR | ||
1008 | "ME4000:alloc_ext_int_context():Can't get memory for cnt context\n"); | ||
1009 | return -ENOMEM; | ||
1010 | } | ||
1011 | |||
1012 | info->ext_int_context = ext_int_context; | ||
1013 | |||
1014 | spin_lock_init(&ext_int_context->use_lock); | ||
1015 | ext_int_context->board_info = info; | ||
1016 | |||
1017 | ext_int_context->fasync_ptr = NULL; | ||
1018 | ext_int_context->irq = info->irq; | ||
1019 | |||
1020 | ext_int_context->ctrl_reg = | ||
1021 | info->me4000_regbase + ME4000_AI_CTRL_REG; | ||
1022 | ext_int_context->irq_status_reg = | ||
1023 | info->me4000_regbase + ME4000_IRQ_STATUS_REG; | ||
1024 | } | ||
1025 | |||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
1030 | { | ||
1031 | int result = 0; | ||
1032 | struct me4000_info *board_info; | ||
1033 | |||
1034 | CALL_PDEBUG("me4000_probe() is executed\n"); | ||
1035 | |||
1036 | /* Allocate structure for board context */ | ||
1037 | board_info = kzalloc(sizeof(struct me4000_info), GFP_KERNEL); | ||
1038 | if (!board_info) { | ||
1039 | printk(KERN_ERR | ||
1040 | "ME4000:Can't get memory for board info structure\n"); | ||
1041 | result = -ENOMEM; | ||
1042 | goto PROBE_ERROR_1; | ||
1043 | } | ||
1044 | |||
1045 | /* Add to global linked list */ | ||
1046 | list_add_tail(&board_info->list, &me4000_board_info_list); | ||
1047 | |||
1048 | /* Get the PCI base registers */ | ||
1049 | result = get_registers(dev, board_info); | ||
1050 | if (result) { | ||
1051 | printk(KERN_ERR "%s:Cannot get registers\n", __func__); | ||
1052 | goto PROBE_ERROR_2; | ||
1053 | } | ||
1054 | |||
1055 | /* Enable the device */ | ||
1056 | result = pci_enable_device(dev); | ||
1057 | if (result < 0) { | ||
1058 | printk(KERN_ERR "%s:Cannot enable PCI device\n", __func__); | ||
1059 | goto PROBE_ERROR_2; | ||
1060 | } | ||
1061 | |||
1062 | /* Request the PCI register regions */ | ||
1063 | result = pci_request_regions(dev, ME4000_NAME); | ||
1064 | if (result < 0) { | ||
1065 | printk(KERN_ERR "%s:Cannot request I/O regions\n", __func__); | ||
1066 | goto PROBE_ERROR_2; | ||
1067 | } | ||
1068 | |||
1069 | /* Initialize board info */ | ||
1070 | result = init_board_info(dev, board_info); | ||
1071 | if (result) { | ||
1072 | printk(KERN_ERR "%s:Cannot init baord info\n", __func__); | ||
1073 | goto PROBE_ERROR_3; | ||
1074 | } | ||
1075 | |||
1076 | /* Download the xilinx firmware */ | ||
1077 | result = me4000_xilinx_download(board_info); | ||
1078 | if (result) { | ||
1079 | printk(KERN_ERR "%s:Can't download firmware\n", __func__); | ||
1080 | goto PROBE_ERROR_3; | ||
1081 | } | ||
1082 | |||
1083 | /* Make a hardware reset */ | ||
1084 | result = me4000_reset_board(board_info); | ||
1085 | if (result) { | ||
1086 | printk(KERN_ERR "%s :Can't reset board\n", __func__); | ||
1087 | goto PROBE_ERROR_3; | ||
1088 | } | ||
1089 | |||
1090 | /* Allocate analog output context structures */ | ||
1091 | result = alloc_ao_contexts(board_info); | ||
1092 | if (result) { | ||
1093 | printk(KERN_ERR "%s:Cannot allocate ao contexts\n", __func__); | ||
1094 | goto PROBE_ERROR_3; | ||
1095 | } | ||
1096 | |||
1097 | /* Allocate analog input context */ | ||
1098 | result = alloc_ai_context(board_info); | ||
1099 | if (result) { | ||
1100 | printk(KERN_ERR "%s:Cannot allocate ai context\n", __func__); | ||
1101 | goto PROBE_ERROR_4; | ||
1102 | } | ||
1103 | |||
1104 | /* Allocate digital I/O context */ | ||
1105 | result = alloc_dio_context(board_info); | ||
1106 | if (result) { | ||
1107 | printk(KERN_ERR "%s:Cannot allocate dio context\n", __func__); | ||
1108 | goto PROBE_ERROR_5; | ||
1109 | } | ||
1110 | |||
1111 | /* Allocate counter context */ | ||
1112 | result = alloc_cnt_context(board_info); | ||
1113 | if (result) { | ||
1114 | printk(KERN_ERR "%s:Cannot allocate cnt context\n", __func__); | ||
1115 | goto PROBE_ERROR_6; | ||
1116 | } | ||
1117 | |||
1118 | /* Allocate external interrupt context */ | ||
1119 | result = alloc_ext_int_context(board_info); | ||
1120 | if (result) { | ||
1121 | printk(KERN_ERR | ||
1122 | "%s:Cannot allocate ext_int context\n", __func__); | ||
1123 | goto PROBE_ERROR_7; | ||
1124 | } | ||
1125 | |||
1126 | return 0; | ||
1127 | |||
1128 | PROBE_ERROR_7: | ||
1129 | kfree(board_info->cnt_context); | ||
1130 | |||
1131 | PROBE_ERROR_6: | ||
1132 | kfree(board_info->dio_context); | ||
1133 | |||
1134 | PROBE_ERROR_5: | ||
1135 | kfree(board_info->ai_context); | ||
1136 | |||
1137 | PROBE_ERROR_4: | ||
1138 | release_ao_contexts(board_info); | ||
1139 | |||
1140 | PROBE_ERROR_3: | ||
1141 | pci_release_regions(dev); | ||
1142 | |||
1143 | PROBE_ERROR_2: | ||
1144 | list_del(&board_info->list); | ||
1145 | kfree(board_info); | ||
1146 | |||
1147 | PROBE_ERROR_1: | ||
1148 | return result; | ||
1149 | } | ||
1150 | |||
1151 | static int me4000_xilinx_download(struct me4000_info *info) | ||
1152 | { | ||
1153 | int size = 0; | ||
1154 | u32 value = 0; | ||
1155 | int idx = 0; | ||
1156 | unsigned char *firm; | ||
1157 | wait_queue_head_t queue; | ||
1158 | |||
1159 | CALL_PDEBUG("me4000_xilinx_download() is executed\n"); | ||
1160 | |||
1161 | init_waitqueue_head(&queue); | ||
1162 | |||
1163 | firm = (info->device_id == 0x4610) ? xilinx_firm_4610 : xilinx_firm; | ||
1164 | |||
1165 | /* | ||
1166 | * Set PLX local interrupt 2 polarity to high. | ||
1167 | * Interrupt is thrown by init pin of xilinx. | ||
1168 | */ | ||
1169 | outl(0x10, info->plx_regbase + PLX_INTCSR); | ||
1170 | |||
1171 | /* Set /CS and /WRITE of the Xilinx */ | ||
1172 | value = inl(info->plx_regbase + PLX_ICR); | ||
1173 | value |= 0x100; | ||
1174 | outl(value, info->plx_regbase + PLX_ICR); | ||
1175 | |||
1176 | /* Init Xilinx with CS1 */ | ||
1177 | inb(info->program_regbase + 0xC8); | ||
1178 | |||
1179 | /* Wait until /INIT pin is set */ | ||
1180 | udelay(20); | ||
1181 | if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) { | ||
1182 | printk(KERN_ERR "%s:Can't init Xilinx\n", __func__); | ||
1183 | return -EIO; | ||
1184 | } | ||
1185 | |||
1186 | /* Reset /CS and /WRITE of the Xilinx */ | ||
1187 | value = inl(info->plx_regbase + PLX_ICR); | ||
1188 | value &= ~0x100; | ||
1189 | outl(value, info->plx_regbase + PLX_ICR); | ||
1190 | |||
1191 | /* Download Xilinx firmware */ | ||
1192 | size = (firm[0] << 24) + (firm[1] << 16) + (firm[2] << 8) + firm[3]; | ||
1193 | udelay(10); | ||
1194 | |||
1195 | for (idx = 0; idx < size; idx++) { | ||
1196 | outb(firm[16 + idx], info->program_regbase); | ||
1197 | |||
1198 | udelay(10); | ||
1199 | |||
1200 | /* Check if BUSY flag is low */ | ||
1201 | if (inl(info->plx_regbase + PLX_ICR) & 0x20) { | ||
1202 | printk(KERN_ERR | ||
1203 | "%s:Xilinx is still busy (idx = %d)\n", __func__, | ||
1204 | idx); | ||
1205 | return -EIO; | ||
1206 | } | ||
1207 | } | ||
1208 | |||
1209 | PDEBUG("me4000_xilinx_download():%d bytes written\n", idx); | ||
1210 | |||
1211 | /* If done flag is high download was successful */ | ||
1212 | if (inl(info->plx_regbase + PLX_ICR) & 0x4) { | ||
1213 | PDEBUG("me4000_xilinx_download():Done flag is set\n"); | ||
1214 | PDEBUG("me4000_xilinx_download():Download was successful\n"); | ||
1215 | } else { | ||
1216 | printk(KERN_ERR | ||
1217 | "ME4000:%s:DONE flag is not set\n", __func__); | ||
1218 | printk(KERN_ERR | ||
1219 | "ME4000:%s:Download not succesful\n", __func__); | ||
1220 | return -EIO; | ||
1221 | } | ||
1222 | |||
1223 | /* Set /CS and /WRITE */ | ||
1224 | value = inl(info->plx_regbase + PLX_ICR); | ||
1225 | value |= 0x100; | ||
1226 | outl(value, info->plx_regbase + PLX_ICR); | ||
1227 | |||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | static int me4000_reset_board(struct me4000_info *info) | ||
1232 | { | ||
1233 | unsigned long icr; | ||
1234 | |||
1235 | CALL_PDEBUG("me4000_reset_board() is executed\n"); | ||
1236 | |||
1237 | /* Make a hardware reset */ | ||
1238 | icr = me4000_inl(info->plx_regbase + PLX_ICR); | ||
1239 | icr |= 0x40000000; | ||
1240 | me4000_outl(icr, info->plx_regbase + PLX_ICR); | ||
1241 | icr &= ~0x40000000; | ||
1242 | me4000_outl(icr, info->plx_regbase + PLX_ICR); | ||
1243 | |||
1244 | /* Set both stop bits in the analog input control register */ | ||
1245 | me4000_outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP, | ||
1246 | info->me4000_regbase + ME4000_AI_CTRL_REG); | ||
1247 | |||
1248 | /* Set both stop bits in the analog output control register */ | ||
1249 | me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, | ||
1250 | info->me4000_regbase + ME4000_AO_00_CTRL_REG); | ||
1251 | me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, | ||
1252 | info->me4000_regbase + ME4000_AO_01_CTRL_REG); | ||
1253 | me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, | ||
1254 | info->me4000_regbase + ME4000_AO_02_CTRL_REG); | ||
1255 | me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP, | ||
1256 | info->me4000_regbase + ME4000_AO_03_CTRL_REG); | ||
1257 | |||
1258 | /* 0x8000 to the DACs means an output voltage of 0V */ | ||
1259 | me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG); | ||
1260 | me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG); | ||
1261 | me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG); | ||
1262 | me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG); | ||
1263 | |||
1264 | /* Enable interrupts on the PLX */ | ||
1265 | me4000_outl(0x43, info->plx_regbase + PLX_INTCSR); | ||
1266 | |||
1267 | /* Set the adustment register for AO demux */ | ||
1268 | me4000_outl(ME4000_AO_DEMUX_ADJUST_VALUE, | ||
1269 | info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG); | ||
1270 | |||
1271 | /* Set digital I/O direction for port 0 to output on isolated versions */ | ||
1272 | if (!(me4000_inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) | ||
1273 | me4000_outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG); | ||
1274 | |||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | static int me4000_open(struct inode *inode_p, struct file *file_p) | ||
1279 | { | ||
1280 | int board, dev, mode; | ||
1281 | int err = 0; | ||
1282 | int i; | ||
1283 | struct list_head *ptr; | ||
1284 | struct me4000_info *board_info = NULL; | ||
1285 | struct me4000_ao_context *ao_context = NULL; | ||
1286 | struct me4000_ai_context *ai_context = NULL; | ||
1287 | struct me4000_dio_context *dio_context = NULL; | ||
1288 | struct me4000_cnt_context *cnt_context = NULL; | ||
1289 | struct me4000_ext_int_context *ext_int_context = NULL; | ||
1290 | |||
1291 | CALL_PDEBUG("me4000_open() is executed\n"); | ||
1292 | |||
1293 | /* Analog output */ | ||
1294 | if (MAJOR(inode_p->i_rdev) == me4000_ao_major_driver_no) { | ||
1295 | board = AO_BOARD(inode_p->i_rdev); | ||
1296 | dev = AO_PORT(inode_p->i_rdev); | ||
1297 | mode = AO_MODE(inode_p->i_rdev); | ||
1298 | |||
1299 | PDEBUG("me4000_open():board = %d ao = %d mode = %d\n", board, | ||
1300 | dev, mode); | ||
1301 | |||
1302 | /* Search for the board context */ | ||
1303 | i = 0; | ||
1304 | list_for_each(ptr, &me4000_board_info_list) { | ||
1305 | if (i == board) | ||
1306 | break; | ||
1307 | i++; | ||
1308 | } | ||
1309 | board_info = list_entry(ptr, struct me4000_info, list); | ||
1310 | |||
1311 | if (ptr == &me4000_board_info_list) { | ||
1312 | printk(KERN_ERR | ||
1313 | "ME4000:me4000_open():Board %d not in device list\n", | ||
1314 | board); | ||
1315 | return -ENODEV; | ||
1316 | } | ||
1317 | |||
1318 | /* Search for the dac context */ | ||
1319 | i = 0; | ||
1320 | list_for_each(ptr, &board_info->ao_context_list) { | ||
1321 | if (i == dev) | ||
1322 | break; | ||
1323 | i++; | ||
1324 | } | ||
1325 | ao_context = list_entry(ptr, struct me4000_ao_context, list); | ||
1326 | |||
1327 | if (ptr == &board_info->ao_context_list) { | ||
1328 | printk(KERN_ERR | ||
1329 | "ME4000:me4000_open():Device %d not in device list\n", | ||
1330 | dev); | ||
1331 | return -ENODEV; | ||
1332 | } | ||
1333 | |||
1334 | /* Check if mode is valid */ | ||
1335 | if (mode > 2) { | ||
1336 | printk(KERN_ERR | ||
1337 | "ME4000:me4000_open():Mode is not valid\n"); | ||
1338 | return -ENODEV; | ||
1339 | } | ||
1340 | |||
1341 | /* Check if mode is valid for this AO */ | ||
1342 | if ((mode != ME4000_AO_CONV_MODE_SINGLE) | ||
1343 | && (dev >= board_info->board_p->ao.fifo_count)) { | ||
1344 | printk(KERN_ERR | ||
1345 | "ME4000:me4000_open():AO %d only in single mode available\n", | ||
1346 | dev); | ||
1347 | return -ENODEV; | ||
1348 | } | ||
1349 | |||
1350 | /* Check if already opened */ | ||
1351 | spin_lock(&ao_context->use_lock); | ||
1352 | if (ao_context->dac_in_use) { | ||
1353 | printk(KERN_ERR | ||
1354 | "ME4000:me4000_open():AO %d already in use\n", | ||
1355 | dev); | ||
1356 | spin_unlock(&ao_context->use_lock); | ||
1357 | return -EBUSY; | ||
1358 | } | ||
1359 | ao_context->dac_in_use = 1; | ||
1360 | spin_unlock(&ao_context->use_lock); | ||
1361 | |||
1362 | ao_context->mode = mode; | ||
1363 | |||
1364 | /* Hold the context in private data */ | ||
1365 | file_p->private_data = ao_context; | ||
1366 | |||
1367 | /* Set file operations pointer */ | ||
1368 | file_p->f_op = me4000_ao_fops_array[mode]; | ||
1369 | |||
1370 | err = me4000_ao_prepare(ao_context); | ||
1371 | if (err) { | ||
1372 | ao_context->dac_in_use = 0; | ||
1373 | return 1; | ||
1374 | } | ||
1375 | } | ||
1376 | /* Analog input */ | ||
1377 | else if (MAJOR(inode_p->i_rdev) == me4000_ai_major_driver_no) { | ||
1378 | board = AI_BOARD(inode_p->i_rdev); | ||
1379 | mode = AI_MODE(inode_p->i_rdev); | ||
1380 | |||
1381 | PDEBUG("me4000_open():ai board = %d mode = %d\n", board, mode); | ||
1382 | |||
1383 | /* Search for the board context */ | ||
1384 | i = 0; | ||
1385 | list_for_each(ptr, &me4000_board_info_list) { | ||
1386 | if (i == board) | ||
1387 | break; | ||
1388 | i++; | ||
1389 | } | ||
1390 | board_info = list_entry(ptr, struct me4000_info, list); | ||
1391 | |||
1392 | if (ptr == &me4000_board_info_list) { | ||
1393 | printk(KERN_ERR | ||
1394 | "ME4000:me4000_open():Board %d not in device list\n", | ||
1395 | board); | ||
1396 | return -ENODEV; | ||
1397 | } | ||
1398 | |||
1399 | ai_context = board_info->ai_context; | ||
1400 | |||
1401 | /* Check if mode is valid */ | ||
1402 | if (mode > 5) { | ||
1403 | printk(KERN_ERR | ||
1404 | "ME4000:me4000_open():Mode is not valid\n"); | ||
1405 | return -EINVAL; | ||
1406 | } | ||
1407 | |||
1408 | /* Check if already opened */ | ||
1409 | spin_lock(&ai_context->use_lock); | ||
1410 | if (ai_context->in_use) { | ||
1411 | printk(KERN_ERR | ||
1412 | "ME4000:me4000_open():AI already in use\n"); | ||
1413 | spin_unlock(&ai_context->use_lock); | ||
1414 | return -EBUSY; | ||
1415 | } | ||
1416 | ai_context->in_use = 1; | ||
1417 | spin_unlock(&ai_context->use_lock); | ||
1418 | |||
1419 | ai_context->mode = mode; | ||
1420 | |||
1421 | /* Hold the context in private data */ | ||
1422 | file_p->private_data = ai_context; | ||
1423 | |||
1424 | /* Set file operations pointer */ | ||
1425 | file_p->f_op = me4000_ai_fops_array[mode]; | ||
1426 | |||
1427 | /* Prepare analog input */ | ||
1428 | me4000_ai_prepare(ai_context); | ||
1429 | } | ||
1430 | /* Digital I/O */ | ||
1431 | else if (MAJOR(inode_p->i_rdev) == me4000_dio_major_driver_no) { | ||
1432 | board = DIO_BOARD(inode_p->i_rdev); | ||
1433 | dev = 0; | ||
1434 | mode = 0; | ||
1435 | |||
1436 | PDEBUG("me4000_open():board = %d\n", board); | ||
1437 | |||
1438 | /* Search for the board context */ | ||
1439 | list_for_each_entry(board_info, &me4000_board_info_list, list) { | ||
1440 | if (board_info->board_count == board) | ||
1441 | break; | ||
1442 | } | ||
1443 | |||
1444 | if (&board_info->list == &me4000_board_info_list) { | ||
1445 | printk(KERN_ERR | ||
1446 | "ME4000:me4000_open():Board %d not in device list\n", | ||
1447 | board); | ||
1448 | return -ENODEV; | ||
1449 | } | ||
1450 | |||
1451 | /* Search for the dio context */ | ||
1452 | dio_context = board_info->dio_context; | ||
1453 | |||
1454 | /* Check if already opened */ | ||
1455 | spin_lock(&dio_context->use_lock); | ||
1456 | if (dio_context->in_use) { | ||
1457 | printk(KERN_ERR | ||
1458 | "ME4000:me4000_open():DIO already in use\n"); | ||
1459 | spin_unlock(&dio_context->use_lock); | ||
1460 | return -EBUSY; | ||
1461 | } | ||
1462 | dio_context->in_use = 1; | ||
1463 | spin_unlock(&dio_context->use_lock); | ||
1464 | |||
1465 | /* Hold the context in private data */ | ||
1466 | file_p->private_data = dio_context; | ||
1467 | |||
1468 | /* Set file operations pointer to single functions */ | ||
1469 | file_p->f_op = &me4000_dio_fops; | ||
1470 | |||
1471 | /* me4000_dio_reset(dio_context); */ | ||
1472 | } | ||
1473 | /* Counters */ | ||
1474 | else if (MAJOR(inode_p->i_rdev) == me4000_cnt_major_driver_no) { | ||
1475 | board = CNT_BOARD(inode_p->i_rdev); | ||
1476 | dev = 0; | ||
1477 | mode = 0; | ||
1478 | |||
1479 | PDEBUG("me4000_open():board = %d\n", board); | ||
1480 | |||
1481 | /* Search for the board context */ | ||
1482 | list_for_each_entry(board_info, &me4000_board_info_list, list) { | ||
1483 | if (board_info->board_count == board) | ||
1484 | break; | ||
1485 | } | ||
1486 | |||
1487 | if (&board_info->list == &me4000_board_info_list) { | ||
1488 | printk(KERN_ERR | ||
1489 | "ME4000:me4000_open():Board %d not in device list\n", | ||
1490 | board); | ||
1491 | return -ENODEV; | ||
1492 | } | ||
1493 | |||
1494 | /* Get the cnt context */ | ||
1495 | cnt_context = board_info->cnt_context; | ||
1496 | |||
1497 | /* Check if already opened */ | ||
1498 | spin_lock(&cnt_context->use_lock); | ||
1499 | if (cnt_context->in_use) { | ||
1500 | printk(KERN_ERR | ||
1501 | "ME4000:me4000_open():CNT already in use\n"); | ||
1502 | spin_unlock(&cnt_context->use_lock); | ||
1503 | return -EBUSY; | ||
1504 | } | ||
1505 | cnt_context->in_use = 1; | ||
1506 | spin_unlock(&cnt_context->use_lock); | ||
1507 | |||
1508 | /* Hold the context in private data */ | ||
1509 | file_p->private_data = cnt_context; | ||
1510 | |||
1511 | /* Set file operations pointer to single functions */ | ||
1512 | file_p->f_op = &me4000_cnt_fops; | ||
1513 | } | ||
1514 | /* External Interrupt */ | ||
1515 | else if (MAJOR(inode_p->i_rdev) == me4000_ext_int_major_driver_no) { | ||
1516 | board = EXT_INT_BOARD(inode_p->i_rdev); | ||
1517 | dev = 0; | ||
1518 | mode = 0; | ||
1519 | |||
1520 | PDEBUG("me4000_open():board = %d\n", board); | ||
1521 | |||
1522 | /* Search for the board context */ | ||
1523 | list_for_each_entry(board_info, &me4000_board_info_list, list) { | ||
1524 | if (board_info->board_count == board) | ||
1525 | break; | ||
1526 | } | ||
1527 | |||
1528 | if (&board_info->list == &me4000_board_info_list) { | ||
1529 | printk(KERN_ERR | ||
1530 | "ME4000:me4000_open():Board %d not in device list\n", | ||
1531 | board); | ||
1532 | return -ENODEV; | ||
1533 | } | ||
1534 | |||
1535 | /* Get the external interrupt context */ | ||
1536 | ext_int_context = board_info->ext_int_context; | ||
1537 | |||
1538 | /* Check if already opened */ | ||
1539 | spin_lock(&cnt_context->use_lock); | ||
1540 | if (ext_int_context->in_use) { | ||
1541 | printk(KERN_ERR | ||
1542 | "ME4000:me4000_open():External interrupt already in use\n"); | ||
1543 | spin_unlock(&ext_int_context->use_lock); | ||
1544 | return -EBUSY; | ||
1545 | } | ||
1546 | ext_int_context->in_use = 1; | ||
1547 | spin_unlock(&ext_int_context->use_lock); | ||
1548 | |||
1549 | /* Hold the context in private data */ | ||
1550 | file_p->private_data = ext_int_context; | ||
1551 | |||
1552 | /* Set file operations pointer to single functions */ | ||
1553 | file_p->f_op = &me4000_ext_int_fops; | ||
1554 | |||
1555 | /* Request the interrupt line */ | ||
1556 | err = | ||
1557 | request_irq(ext_int_context->irq, me4000_ext_int_isr, | ||
1558 | IRQF_DISABLED | IRQF_SHARED, ME4000_NAME, | ||
1559 | ext_int_context); | ||
1560 | if (err) { | ||
1561 | printk(KERN_ERR | ||
1562 | "ME4000:me4000_open():Can't get interrupt line"); | ||
1563 | ext_int_context->in_use = 0; | ||
1564 | return -ENODEV; | ||
1565 | } | ||
1566 | |||
1567 | /* Reset the counter */ | ||
1568 | me4000_ext_int_disable(ext_int_context); | ||
1569 | } else { | ||
1570 | printk(KERN_ERR "ME4000:me4000_open():Major number unknown\n"); | ||
1571 | return -EINVAL; | ||
1572 | } | ||
1573 | |||
1574 | return 0; | ||
1575 | } | ||
1576 | |||
1577 | static int me4000_release(struct inode *inode_p, struct file *file_p) | ||
1578 | { | ||
1579 | struct me4000_ao_context *ao_context; | ||
1580 | struct me4000_ai_context *ai_context; | ||
1581 | struct me4000_dio_context *dio_context; | ||
1582 | struct me4000_cnt_context *cnt_context; | ||
1583 | struct me4000_ext_int_context *ext_int_context; | ||
1584 | |||
1585 | CALL_PDEBUG("me4000_release() is executed\n"); | ||
1586 | |||
1587 | if (MAJOR(inode_p->i_rdev) == me4000_ao_major_driver_no) { | ||
1588 | ao_context = file_p->private_data; | ||
1589 | |||
1590 | /* Mark DAC as unused */ | ||
1591 | ao_context->dac_in_use = 0; | ||
1592 | } else if (MAJOR(inode_p->i_rdev) == me4000_ai_major_driver_no) { | ||
1593 | ai_context = file_p->private_data; | ||
1594 | |||
1595 | /* Reset the analog input */ | ||
1596 | me4000_ai_reset(ai_context); | ||
1597 | |||
1598 | /* Free the interrupt and the circular buffer */ | ||
1599 | if (ai_context->mode) { | ||
1600 | free_irq(ai_context->irq, ai_context); | ||
1601 | kfree(ai_context->circ_buf.buf); | ||
1602 | ai_context->circ_buf.buf = NULL; | ||
1603 | ai_context->circ_buf.head = 0; | ||
1604 | ai_context->circ_buf.tail = 0; | ||
1605 | } | ||
1606 | |||
1607 | /* Mark AI as unused */ | ||
1608 | ai_context->in_use = 0; | ||
1609 | } else if (MAJOR(inode_p->i_rdev) == me4000_dio_major_driver_no) { | ||
1610 | dio_context = file_p->private_data; | ||
1611 | |||
1612 | /* Mark digital I/O as unused */ | ||
1613 | dio_context->in_use = 0; | ||
1614 | } else if (MAJOR(inode_p->i_rdev) == me4000_cnt_major_driver_no) { | ||
1615 | cnt_context = file_p->private_data; | ||
1616 | |||
1617 | /* Mark counters as unused */ | ||
1618 | cnt_context->in_use = 0; | ||
1619 | } else if (MAJOR(inode_p->i_rdev) == me4000_ext_int_major_driver_no) { | ||
1620 | ext_int_context = file_p->private_data; | ||
1621 | |||
1622 | /* Disable the externel interrupt */ | ||
1623 | me4000_ext_int_disable(ext_int_context); | ||
1624 | |||
1625 | free_irq(ext_int_context->irq, ext_int_context); | ||
1626 | |||
1627 | /* Mark as unused */ | ||
1628 | ext_int_context->in_use = 0; | ||
1629 | } else { | ||
1630 | printk(KERN_ERR | ||
1631 | "ME4000:me4000_release():Major number unknown\n"); | ||
1632 | return -EINVAL; | ||
1633 | } | ||
1634 | |||
1635 | return 0; | ||
1636 | } | ||
1637 | |||
1638 | /*------------------------------- Analog output stuff --------------------------------------*/ | ||
1639 | |||
1640 | static int me4000_ao_prepare(struct me4000_ao_context *ao_context) | ||
1641 | { | ||
1642 | unsigned long flags; | ||
1643 | |||
1644 | CALL_PDEBUG("me4000_ao_prepare() is executed\n"); | ||
1645 | |||
1646 | if (ao_context->mode == ME4000_AO_CONV_MODE_CONTINUOUS) { | ||
1647 | /* Only do anything if not already in the correct mode */ | ||
1648 | unsigned long mode = me4000_inl(ao_context->ctrl_reg); | ||
1649 | if ((mode & ME4000_AO_CONV_MODE_CONTINUOUS) | ||
1650 | && (mode & ME4000_AO_CTRL_BIT_ENABLE_FIFO)) { | ||
1651 | return 0; | ||
1652 | } | ||
1653 | |||
1654 | /* Stop any conversion */ | ||
1655 | me4000_ao_immediate_stop(ao_context); | ||
1656 | |||
1657 | /* Set the control register to default state */ | ||
1658 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
1659 | me4000_outl(ME4000_AO_CONV_MODE_CONTINUOUS | | ||
1660 | ME4000_AO_CTRL_BIT_ENABLE_FIFO | | ||
1661 | ME4000_AO_CTRL_BIT_STOP | | ||
1662 | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP, | ||
1663 | ao_context->ctrl_reg); | ||
1664 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
1665 | |||
1666 | /* Set to fastest sample rate */ | ||
1667 | me4000_outl(65, ao_context->timer_reg); | ||
1668 | } else if (ao_context->mode == ME4000_AO_CONV_MODE_WRAPAROUND) { | ||
1669 | /* Only do anything if not already in the correct mode */ | ||
1670 | unsigned long mode = me4000_inl(ao_context->ctrl_reg); | ||
1671 | if ((mode & ME4000_AO_CONV_MODE_WRAPAROUND) | ||
1672 | && (mode & ME4000_AO_CTRL_BIT_ENABLE_FIFO)) { | ||
1673 | return 0; | ||
1674 | } | ||
1675 | |||
1676 | /* Stop any conversion */ | ||
1677 | me4000_ao_immediate_stop(ao_context); | ||
1678 | |||
1679 | /* Set the control register to default state */ | ||
1680 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
1681 | me4000_outl(ME4000_AO_CONV_MODE_WRAPAROUND | | ||
1682 | ME4000_AO_CTRL_BIT_ENABLE_FIFO | | ||
1683 | ME4000_AO_CTRL_BIT_STOP | | ||
1684 | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP, | ||
1685 | ao_context->ctrl_reg); | ||
1686 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
1687 | |||
1688 | /* Set to fastest sample rate */ | ||
1689 | me4000_outl(65, ao_context->timer_reg); | ||
1690 | } else if (ao_context->mode == ME4000_AO_CONV_MODE_SINGLE) { | ||
1691 | /* Only do anything if not already in the correct mode */ | ||
1692 | unsigned long mode = me4000_inl(ao_context->ctrl_reg); | ||
1693 | if (! | ||
1694 | (mode & | ||
1695 | (ME4000_AO_CONV_MODE_WRAPAROUND | | ||
1696 | ME4000_AO_CONV_MODE_CONTINUOUS))) { | ||
1697 | return 0; | ||
1698 | } | ||
1699 | |||
1700 | /* Stop any conversion */ | ||
1701 | me4000_ao_immediate_stop(ao_context); | ||
1702 | |||
1703 | /* Clear the control register */ | ||
1704 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
1705 | me4000_outl(0x0, ao_context->ctrl_reg); | ||
1706 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
1707 | |||
1708 | /* Set voltage to 0V */ | ||
1709 | me4000_outl(0x8000, ao_context->single_reg); | ||
1710 | } else { | ||
1711 | printk(KERN_ERR | ||
1712 | "ME4000:me4000_ao_prepare():Invalid mode specified\n"); | ||
1713 | return -EINVAL; | ||
1714 | } | ||
1715 | |||
1716 | return 0; | ||
1717 | } | ||
1718 | |||
1719 | static int me4000_ao_reset(struct me4000_ao_context *ao_context) | ||
1720 | { | ||
1721 | u32 tmp; | ||
1722 | wait_queue_head_t queue; | ||
1723 | unsigned long flags; | ||
1724 | |||
1725 | CALL_PDEBUG("me4000_ao_reset() is executed\n"); | ||
1726 | |||
1727 | init_waitqueue_head(&queue); | ||
1728 | |||
1729 | if (ao_context->mode == ME4000_AO_CONV_MODE_WRAPAROUND) { | ||
1730 | /* | ||
1731 | * First stop conversion of the DAC before reconfigure. | ||
1732 | * This is essantial, cause of the state machine. | ||
1733 | * If not stopped before configuring mode, it could | ||
1734 | * walk in a undefined state. | ||
1735 | */ | ||
1736 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
1737 | tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
1738 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
1739 | |||
1740 | wait_event_timeout(queue, | ||
1741 | (inl(ao_context->status_reg) & | ||
1742 | ME4000_AO_STATUS_BIT_FSM) == 0, | ||
1743 | 1); | ||
1744 | |||
1745 | /* Set to transparent mode */ | ||
1746 | me4000_ao_simultaneous_disable(ao_context); | ||
1747 | |||
1748 | /* Set to single mode in order to set default voltage */ | ||
1749 | me4000_outl(0x0, ao_context->ctrl_reg); | ||
1750 | |||
1751 | /* Set voltage to 0V */ | ||
1752 | me4000_outl(0x8000, ao_context->single_reg); | ||
1753 | |||
1754 | /* Set to fastest sample rate */ | ||
1755 | me4000_outl(65, ao_context->timer_reg); | ||
1756 | |||
1757 | /* Set the original mode and enable FIFO */ | ||
1758 | me4000_outl(ME4000_AO_CONV_MODE_WRAPAROUND | | ||
1759 | ME4000_AO_CTRL_BIT_ENABLE_FIFO | | ||
1760 | ME4000_AO_CTRL_BIT_STOP | | ||
1761 | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP, | ||
1762 | ao_context->ctrl_reg); | ||
1763 | } else if (ao_context->mode == ME4000_AO_CONV_MODE_CONTINUOUS) { | ||
1764 | /* | ||
1765 | * First stop conversion of the DAC before reconfigure. | ||
1766 | * This is essantial, cause of the state machine. | ||
1767 | * If not stopped before configuring mode, it could | ||
1768 | * walk in a undefined state. | ||
1769 | */ | ||
1770 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
1771 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
1772 | tmp |= ME4000_AO_CTRL_BIT_STOP; | ||
1773 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
1774 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
1775 | |||
1776 | wait_event_timeout(queue, | ||
1777 | (inl(ao_context->status_reg) & | ||
1778 | ME4000_AO_STATUS_BIT_FSM) == 0, | ||
1779 | 1); | ||
1780 | |||
1781 | /* Clear the circular buffer */ | ||
1782 | ao_context->circ_buf.head = 0; | ||
1783 | ao_context->circ_buf.tail = 0; | ||
1784 | |||
1785 | /* Set to transparent mode */ | ||
1786 | me4000_ao_simultaneous_disable(ao_context); | ||
1787 | |||
1788 | /* Set to single mode in order to set default voltage */ | ||
1789 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
1790 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
1791 | me4000_outl(0x0, ao_context->ctrl_reg); | ||
1792 | |||
1793 | /* Set voltage to 0V */ | ||
1794 | me4000_outl(0x8000, ao_context->single_reg); | ||
1795 | |||
1796 | /* Set to fastest sample rate */ | ||
1797 | me4000_outl(65, ao_context->timer_reg); | ||
1798 | |||
1799 | /* Set the original mode and enable FIFO */ | ||
1800 | me4000_outl(ME4000_AO_CONV_MODE_CONTINUOUS | | ||
1801 | ME4000_AO_CTRL_BIT_ENABLE_FIFO | | ||
1802 | ME4000_AO_CTRL_BIT_STOP | | ||
1803 | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP, | ||
1804 | ao_context->ctrl_reg); | ||
1805 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
1806 | } else { | ||
1807 | /* Set to transparent mode */ | ||
1808 | me4000_ao_simultaneous_disable(ao_context); | ||
1809 | |||
1810 | /* Set voltage to 0V */ | ||
1811 | me4000_outl(0x8000, ao_context->single_reg); | ||
1812 | } | ||
1813 | |||
1814 | return 0; | ||
1815 | } | ||
1816 | |||
1817 | static ssize_t me4000_ao_write_sing(struct file *filep, const char *buff, | ||
1818 | size_t cnt, loff_t *offp) | ||
1819 | { | ||
1820 | struct me4000_ao_context *ao_context = filep->private_data; | ||
1821 | u32 value; | ||
1822 | const u16 *buffer = (const u16 *)buff; | ||
1823 | |||
1824 | CALL_PDEBUG("me4000_ao_write_sing() is executed\n"); | ||
1825 | |||
1826 | if (cnt != 2) { | ||
1827 | printk(KERN_ERR | ||
1828 | "%s:Write count is not 2\n", __func__); | ||
1829 | return -EINVAL; | ||
1830 | } | ||
1831 | |||
1832 | if (get_user(value, buffer)) { | ||
1833 | printk(KERN_ERR | ||
1834 | "%s:Cannot copy data from user\n", __func__); | ||
1835 | return -EFAULT; | ||
1836 | } | ||
1837 | |||
1838 | me4000_outl(value, ao_context->single_reg); | ||
1839 | |||
1840 | return 2; | ||
1841 | } | ||
1842 | |||
1843 | static ssize_t me4000_ao_write_wrap(struct file *filep, const char *buff, | ||
1844 | size_t cnt, loff_t *offp) | ||
1845 | { | ||
1846 | struct me4000_ao_context *ao_context = filep->private_data; | ||
1847 | size_t i; | ||
1848 | u32 value; | ||
1849 | u32 tmp; | ||
1850 | const u16 *buffer = (const u16 *)buff; | ||
1851 | size_t count = cnt / 2; | ||
1852 | |||
1853 | CALL_PDEBUG("me4000_ao_write_wrap() is executed\n"); | ||
1854 | |||
1855 | /* Check if a conversion is already running */ | ||
1856 | if (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) { | ||
1857 | printk(KERN_ERR | ||
1858 | "%s:There is already a conversion running\n", __func__); | ||
1859 | return -EBUSY; | ||
1860 | } | ||
1861 | |||
1862 | if (count > ME4000_AO_FIFO_COUNT) { | ||
1863 | printk(KERN_ERR | ||
1864 | "%s:Can't load more than %d values\n", __func__, | ||
1865 | ME4000_AO_FIFO_COUNT); | ||
1866 | return -ENOSPC; | ||
1867 | } | ||
1868 | |||
1869 | /* Reset the FIFO */ | ||
1870 | tmp = inl(ao_context->ctrl_reg); | ||
1871 | tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_FIFO; | ||
1872 | outl(tmp, ao_context->ctrl_reg); | ||
1873 | tmp |= ME4000_AO_CTRL_BIT_ENABLE_FIFO; | ||
1874 | outl(tmp, ao_context->ctrl_reg); | ||
1875 | |||
1876 | for (i = 0; i < count; i++) { | ||
1877 | if (get_user(value, buffer + i)) { | ||
1878 | printk(KERN_ERR | ||
1879 | "%s:Cannot copy data from user\n", __func__); | ||
1880 | return -EFAULT; | ||
1881 | } | ||
1882 | if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG) | ||
1883 | || ((ao_context->fifo_reg & 0xFF) == ME4000_AO_03_FIFO_REG)) | ||
1884 | value = value << 16; | ||
1885 | outl(value, ao_context->fifo_reg); | ||
1886 | } | ||
1887 | CALL_PDEBUG("me4000_ao_write_wrap() is leaved with %d\n", i * 2); | ||
1888 | |||
1889 | return i * 2; | ||
1890 | } | ||
1891 | |||
1892 | static ssize_t me4000_ao_write_cont(struct file *filep, const char *buff, | ||
1893 | size_t cnt, loff_t *offp) | ||
1894 | { | ||
1895 | struct me4000_ao_context *ao_context = filep->private_data; | ||
1896 | const u16 *buffer = (const u16 *)buff; | ||
1897 | size_t count = cnt / 2; | ||
1898 | unsigned long flags; | ||
1899 | u32 tmp; | ||
1900 | int c = 0; | ||
1901 | int k = 0; | ||
1902 | int ret = 0; | ||
1903 | u16 svalue; | ||
1904 | u32 lvalue; | ||
1905 | int i; | ||
1906 | wait_queue_head_t queue; | ||
1907 | |||
1908 | CALL_PDEBUG("me4000_ao_write_cont() is executed\n"); | ||
1909 | |||
1910 | init_waitqueue_head(&queue); | ||
1911 | |||
1912 | /* Check count */ | ||
1913 | if (count <= 0) { | ||
1914 | PDEBUG("me4000_ao_write_cont():Count is 0\n"); | ||
1915 | return 0; | ||
1916 | } | ||
1917 | |||
1918 | if (filep->f_flags & O_APPEND) { | ||
1919 | PDEBUG("me4000_ao_write_cont():Append data to data stream\n"); | ||
1920 | while (count > 0) { | ||
1921 | if (filep->f_flags & O_NONBLOCK) { | ||
1922 | if (ao_context->pipe_flag) { | ||
1923 | printk(KERN_ERR | ||
1924 | "ME4000:me4000_ao_write_cont():Broken pipe in nonblocking write\n"); | ||
1925 | return -EPIPE; | ||
1926 | } | ||
1927 | c = me4000_space_to_end(ao_context->circ_buf, | ||
1928 | ME4000_AO_BUFFER_COUNT); | ||
1929 | if (!c) { | ||
1930 | PDEBUG | ||
1931 | ("me4000_ao_write_cont():Returning from nonblocking write\n"); | ||
1932 | break; | ||
1933 | } | ||
1934 | } else { | ||
1935 | wait_event_interruptible(ao_context->wait_queue, | ||
1936 | (c = | ||
1937 | me4000_space_to_end | ||
1938 | (ao_context->circ_buf, | ||
1939 | ME4000_AO_BUFFER_COUNT))); | ||
1940 | if (ao_context->pipe_flag) { | ||
1941 | printk(KERN_ERR | ||
1942 | "me4000_ao_write_cont():Broken pipe in blocking write\n"); | ||
1943 | return -EPIPE; | ||
1944 | } | ||
1945 | if (signal_pending(current)) { | ||
1946 | printk(KERN_ERR | ||
1947 | "me4000_ao_write_cont():Wait for free buffer interrupted from signal\n"); | ||
1948 | return -EINTR; | ||
1949 | } | ||
1950 | } | ||
1951 | |||
1952 | PDEBUG("me4000_ao_write_cont():Space to end = %d\n", c); | ||
1953 | |||
1954 | /* Only able to write size of free buffer or size of count */ | ||
1955 | if (count < c) | ||
1956 | c = count; | ||
1957 | |||
1958 | k = 2 * c; | ||
1959 | k -= copy_from_user(ao_context->circ_buf.buf + | ||
1960 | ao_context->circ_buf.head, buffer, | ||
1961 | k); | ||
1962 | c = k / 2; | ||
1963 | PDEBUG | ||
1964 | ("me4000_ao_write_cont():Copy %d values from user space\n", | ||
1965 | c); | ||
1966 | |||
1967 | if (!c) | ||
1968 | return -EFAULT; | ||
1969 | |||
1970 | ao_context->circ_buf.head = | ||
1971 | (ao_context->circ_buf.head + | ||
1972 | c) & (ME4000_AO_BUFFER_COUNT - 1); | ||
1973 | buffer += c; | ||
1974 | count -= c; | ||
1975 | ret += c; | ||
1976 | |||
1977 | /* Values are now available so enable interrupts */ | ||
1978 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
1979 | if (me4000_buf_count | ||
1980 | (ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) { | ||
1981 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
1982 | tmp |= ME4000_AO_CTRL_BIT_ENABLE_IRQ; | ||
1983 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
1984 | } | ||
1985 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
1986 | } | ||
1987 | |||
1988 | /* Wait until the state machine is stopped if O_SYNC is set */ | ||
1989 | if (filep->f_flags & O_SYNC) { | ||
1990 | while (inl(ao_context->status_reg) & | ||
1991 | ME4000_AO_STATUS_BIT_FSM) { | ||
1992 | interruptible_sleep_on_timeout(&queue, 1); | ||
1993 | if (ao_context->pipe_flag) { | ||
1994 | PDEBUG | ||
1995 | ("me4000_ao_write_cont():Broken pipe detected after sync\n"); | ||
1996 | return -EPIPE; | ||
1997 | } | ||
1998 | if (signal_pending(current)) { | ||
1999 | printk(KERN_ERR | ||
2000 | "me4000_ao_write_cont():Wait on state machine after sync interrupted\n"); | ||
2001 | return -EINTR; | ||
2002 | } | ||
2003 | } | ||
2004 | } | ||
2005 | } else { | ||
2006 | PDEBUG("me4000_ao_write_cont():Preload DAC FIFO\n"); | ||
2007 | if ((me4000_inl(ao_context->status_reg) & | ||
2008 | ME4000_AO_STATUS_BIT_FSM)) { | ||
2009 | printk(KERN_ERR | ||
2010 | "me4000_ao_write_cont():Can't Preload DAC FIFO while conversion is running\n"); | ||
2011 | return -EBUSY; | ||
2012 | } | ||
2013 | |||
2014 | /* Clear the FIFO */ | ||
2015 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2016 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2017 | tmp &= | ||
2018 | ~(ME4000_AO_CTRL_BIT_ENABLE_FIFO | | ||
2019 | ME4000_AO_CTRL_BIT_ENABLE_IRQ); | ||
2020 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2021 | tmp |= ME4000_AO_CTRL_BIT_ENABLE_FIFO; | ||
2022 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2023 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2024 | |||
2025 | /* Clear the circular buffer */ | ||
2026 | ao_context->circ_buf.head = 0; | ||
2027 | ao_context->circ_buf.tail = 0; | ||
2028 | |||
2029 | /* Reset the broken pipe flag */ | ||
2030 | ao_context->pipe_flag = 0; | ||
2031 | |||
2032 | /* Only able to write size of fifo or count */ | ||
2033 | c = ME4000_AO_FIFO_COUNT; | ||
2034 | if (count < c) | ||
2035 | c = count; | ||
2036 | |||
2037 | PDEBUG | ||
2038 | ("me4000_ao_write_cont():Write %d values to DAC on 0x%lX\n", | ||
2039 | c, ao_context->fifo_reg); | ||
2040 | |||
2041 | /* Write values to the fifo */ | ||
2042 | for (i = 0; i < c; i++) { | ||
2043 | if (get_user(svalue, buffer)) | ||
2044 | return -EFAULT; | ||
2045 | |||
2046 | if (((ao_context->fifo_reg & 0xFF) == | ||
2047 | ME4000_AO_01_FIFO_REG) | ||
2048 | || ((ao_context->fifo_reg & 0xFF) == | ||
2049 | ME4000_AO_03_FIFO_REG)) { | ||
2050 | lvalue = ((u32) svalue) << 16; | ||
2051 | } else | ||
2052 | lvalue = (u32) svalue; | ||
2053 | |||
2054 | outl(lvalue, ao_context->fifo_reg); | ||
2055 | buffer++; | ||
2056 | } | ||
2057 | count -= c; | ||
2058 | ret += c; | ||
2059 | |||
2060 | while (1) { | ||
2061 | /* Get free buffer */ | ||
2062 | c = me4000_space_to_end(ao_context->circ_buf, | ||
2063 | ME4000_AO_BUFFER_COUNT); | ||
2064 | |||
2065 | if (c == 0) | ||
2066 | return 2 * ret; | ||
2067 | |||
2068 | /* Only able to write size of free buffer or size of count */ | ||
2069 | if (count < c) | ||
2070 | c = count; | ||
2071 | |||
2072 | /* If count = 0 return to user */ | ||
2073 | if (c <= 0) { | ||
2074 | PDEBUG | ||
2075 | ("me4000_ao_write_cont():Count reached 0\n"); | ||
2076 | break; | ||
2077 | } | ||
2078 | |||
2079 | k = 2 * c; | ||
2080 | k -= copy_from_user(ao_context->circ_buf.buf + | ||
2081 | ao_context->circ_buf.head, buffer, | ||
2082 | k); | ||
2083 | c = k / 2; | ||
2084 | PDEBUG | ||
2085 | ("me4000_ao_write_cont():Wrote %d values to buffer\n", | ||
2086 | c); | ||
2087 | |||
2088 | if (!c) | ||
2089 | return -EFAULT; | ||
2090 | |||
2091 | ao_context->circ_buf.head = | ||
2092 | (ao_context->circ_buf.head + | ||
2093 | c) & (ME4000_AO_BUFFER_COUNT - 1); | ||
2094 | buffer += c; | ||
2095 | count -= c; | ||
2096 | ret += c; | ||
2097 | |||
2098 | /* If values in the buffer are available so enable interrupts */ | ||
2099 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2100 | if (me4000_buf_count | ||
2101 | (ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) { | ||
2102 | PDEBUG | ||
2103 | ("me4000_ao_write_cont():Enable Interrupts\n"); | ||
2104 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2105 | tmp |= ME4000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2106 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2107 | } | ||
2108 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2109 | } | ||
2110 | } | ||
2111 | |||
2112 | if (filep->f_flags & O_NONBLOCK) | ||
2113 | return (ret == 0) ? -EAGAIN : 2 * ret; | ||
2114 | |||
2115 | return 2 * ret; | ||
2116 | } | ||
2117 | |||
2118 | static unsigned int me4000_ao_poll_cont(struct file *file_p, poll_table *wait) | ||
2119 | { | ||
2120 | struct me4000_ao_context *ao_context; | ||
2121 | unsigned long mask = 0; | ||
2122 | |||
2123 | CALL_PDEBUG("me4000_ao_poll_cont() is executed\n"); | ||
2124 | |||
2125 | ao_context = file_p->private_data; | ||
2126 | |||
2127 | poll_wait(file_p, &ao_context->wait_queue, wait); | ||
2128 | |||
2129 | /* Get free buffer */ | ||
2130 | if (me4000_space_to_end(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) | ||
2131 | mask |= POLLOUT | POLLWRNORM; | ||
2132 | |||
2133 | CALL_PDEBUG("me4000_ao_poll_cont():Return mask %lX\n", mask); | ||
2134 | |||
2135 | return mask; | ||
2136 | } | ||
2137 | |||
2138 | static int me4000_ao_fsync_cont(struct file *file_p, struct dentry *dentry_p, | ||
2139 | int datasync) | ||
2140 | { | ||
2141 | struct me4000_ao_context *ao_context; | ||
2142 | wait_queue_head_t queue; | ||
2143 | |||
2144 | CALL_PDEBUG("me4000_ao_fsync_cont() is executed\n"); | ||
2145 | |||
2146 | ao_context = file_p->private_data; | ||
2147 | init_waitqueue_head(&queue); | ||
2148 | |||
2149 | while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) { | ||
2150 | interruptible_sleep_on_timeout(&queue, 1); | ||
2151 | wait_event_interruptible_timeout(queue, | ||
2152 | !(inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM), | ||
2153 | 1); | ||
2154 | if (ao_context->pipe_flag) { | ||
2155 | printk(KERN_ERR | ||
2156 | "%s:Broken pipe detected\n", __func__); | ||
2157 | return -EPIPE; | ||
2158 | } | ||
2159 | |||
2160 | if (signal_pending(current)) { | ||
2161 | printk(KERN_ERR | ||
2162 | "%s:Wait on state machine interrupted\n", | ||
2163 | __func__); | ||
2164 | return -EINTR; | ||
2165 | } | ||
2166 | } | ||
2167 | |||
2168 | return 0; | ||
2169 | } | ||
2170 | |||
2171 | static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p, | ||
2172 | unsigned int service, unsigned long arg) | ||
2173 | { | ||
2174 | struct me4000_ao_context *ao_context; | ||
2175 | |||
2176 | CALL_PDEBUG("me4000_ao_ioctl_sing() is executed\n"); | ||
2177 | |||
2178 | ao_context = file_p->private_data; | ||
2179 | |||
2180 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
2181 | return -ENOTTY; | ||
2182 | PDEBUG("me4000_ao_ioctl_sing():Wrong magic number\n"); | ||
2183 | } | ||
2184 | |||
2185 | switch (service) { | ||
2186 | case ME4000_AO_EX_TRIG_SETUP: | ||
2187 | return me4000_ao_ex_trig_set_edge((int *)arg, ao_context); | ||
2188 | case ME4000_AO_EX_TRIG_ENABLE: | ||
2189 | return me4000_ao_ex_trig_enable(ao_context); | ||
2190 | case ME4000_AO_EX_TRIG_DISABLE: | ||
2191 | return me4000_ao_ex_trig_disable(ao_context); | ||
2192 | case ME4000_AO_PRELOAD: | ||
2193 | return me4000_ao_preload(ao_context); | ||
2194 | case ME4000_AO_PRELOAD_UPDATE: | ||
2195 | return me4000_ao_preload_update(ao_context); | ||
2196 | case ME4000_GET_USER_INFO: | ||
2197 | return me4000_get_user_info((struct me4000_user_info *)arg, | ||
2198 | ao_context->board_info); | ||
2199 | case ME4000_AO_SIMULTANEOUS_EX_TRIG: | ||
2200 | return me4000_ao_simultaneous_ex_trig(ao_context); | ||
2201 | case ME4000_AO_SIMULTANEOUS_SW: | ||
2202 | return me4000_ao_simultaneous_sw(ao_context); | ||
2203 | case ME4000_AO_SIMULTANEOUS_DISABLE: | ||
2204 | return me4000_ao_simultaneous_disable(ao_context); | ||
2205 | case ME4000_AO_SIMULTANEOUS_UPDATE: | ||
2206 | return | ||
2207 | me4000_ao_simultaneous_update( | ||
2208 | (struct me4000_ao_channel_list *)arg, | ||
2209 | ao_context); | ||
2210 | case ME4000_AO_EX_TRIG_TIMEOUT: | ||
2211 | return me4000_ao_ex_trig_timeout((unsigned long *)arg, | ||
2212 | ao_context); | ||
2213 | case ME4000_AO_DISABLE_DO: | ||
2214 | return me4000_ao_disable_do(ao_context); | ||
2215 | default: | ||
2216 | printk(KERN_ERR | ||
2217 | "me4000_ao_ioctl_sing():Service number invalid\n"); | ||
2218 | return -ENOTTY; | ||
2219 | } | ||
2220 | |||
2221 | return 0; | ||
2222 | } | ||
2223 | |||
2224 | static int me4000_ao_ioctl_wrap(struct inode *inode_p, struct file *file_p, | ||
2225 | unsigned int service, unsigned long arg) | ||
2226 | { | ||
2227 | struct me4000_ao_context *ao_context; | ||
2228 | |||
2229 | CALL_PDEBUG("me4000_ao_ioctl_wrap() is executed\n"); | ||
2230 | |||
2231 | ao_context = file_p->private_data; | ||
2232 | |||
2233 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
2234 | return -ENOTTY; | ||
2235 | PDEBUG("me4000_ao_ioctl_wrap():Wrong magic number\n"); | ||
2236 | } | ||
2237 | |||
2238 | switch (service) { | ||
2239 | case ME4000_AO_START: | ||
2240 | return me4000_ao_start((unsigned long *)arg, ao_context); | ||
2241 | case ME4000_AO_STOP: | ||
2242 | return me4000_ao_stop(ao_context); | ||
2243 | case ME4000_AO_IMMEDIATE_STOP: | ||
2244 | return me4000_ao_immediate_stop(ao_context); | ||
2245 | case ME4000_AO_RESET: | ||
2246 | return me4000_ao_reset(ao_context); | ||
2247 | case ME4000_AO_TIMER_SET_DIVISOR: | ||
2248 | return me4000_ao_timer_set_divisor((u32 *) arg, ao_context); | ||
2249 | case ME4000_AO_EX_TRIG_SETUP: | ||
2250 | return me4000_ao_ex_trig_set_edge((int *)arg, ao_context); | ||
2251 | case ME4000_AO_EX_TRIG_ENABLE: | ||
2252 | return me4000_ao_ex_trig_enable(ao_context); | ||
2253 | case ME4000_AO_EX_TRIG_DISABLE: | ||
2254 | return me4000_ao_ex_trig_disable(ao_context); | ||
2255 | case ME4000_GET_USER_INFO: | ||
2256 | return me4000_get_user_info((struct me4000_user_info *)arg, | ||
2257 | ao_context->board_info); | ||
2258 | case ME4000_AO_FSM_STATE: | ||
2259 | return me4000_ao_fsm_state((int *)arg, ao_context); | ||
2260 | case ME4000_AO_ENABLE_DO: | ||
2261 | return me4000_ao_enable_do(ao_context); | ||
2262 | case ME4000_AO_DISABLE_DO: | ||
2263 | return me4000_ao_disable_do(ao_context); | ||
2264 | case ME4000_AO_SYNCHRONOUS_EX_TRIG: | ||
2265 | return me4000_ao_synchronous_ex_trig(ao_context); | ||
2266 | case ME4000_AO_SYNCHRONOUS_SW: | ||
2267 | return me4000_ao_synchronous_sw(ao_context); | ||
2268 | case ME4000_AO_SYNCHRONOUS_DISABLE: | ||
2269 | return me4000_ao_synchronous_disable(ao_context); | ||
2270 | default: | ||
2271 | return -ENOTTY; | ||
2272 | } | ||
2273 | return 0; | ||
2274 | } | ||
2275 | |||
2276 | static int me4000_ao_ioctl_cont(struct inode *inode_p, struct file *file_p, | ||
2277 | unsigned int service, unsigned long arg) | ||
2278 | { | ||
2279 | struct me4000_ao_context *ao_context; | ||
2280 | |||
2281 | CALL_PDEBUG("me4000_ao_ioctl_cont() is executed\n"); | ||
2282 | |||
2283 | ao_context = file_p->private_data; | ||
2284 | |||
2285 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
2286 | return -ENOTTY; | ||
2287 | PDEBUG("me4000_ao_ioctl_cont():Wrong magic number\n"); | ||
2288 | } | ||
2289 | |||
2290 | switch (service) { | ||
2291 | case ME4000_AO_START: | ||
2292 | return me4000_ao_start((unsigned long *)arg, ao_context); | ||
2293 | case ME4000_AO_STOP: | ||
2294 | return me4000_ao_stop(ao_context); | ||
2295 | case ME4000_AO_IMMEDIATE_STOP: | ||
2296 | return me4000_ao_immediate_stop(ao_context); | ||
2297 | case ME4000_AO_RESET: | ||
2298 | return me4000_ao_reset(ao_context); | ||
2299 | case ME4000_AO_TIMER_SET_DIVISOR: | ||
2300 | return me4000_ao_timer_set_divisor((u32 *) arg, ao_context); | ||
2301 | case ME4000_AO_EX_TRIG_SETUP: | ||
2302 | return me4000_ao_ex_trig_set_edge((int *)arg, ao_context); | ||
2303 | case ME4000_AO_EX_TRIG_ENABLE: | ||
2304 | return me4000_ao_ex_trig_enable(ao_context); | ||
2305 | case ME4000_AO_EX_TRIG_DISABLE: | ||
2306 | return me4000_ao_ex_trig_disable(ao_context); | ||
2307 | case ME4000_AO_ENABLE_DO: | ||
2308 | return me4000_ao_enable_do(ao_context); | ||
2309 | case ME4000_AO_DISABLE_DO: | ||
2310 | return me4000_ao_disable_do(ao_context); | ||
2311 | case ME4000_AO_FSM_STATE: | ||
2312 | return me4000_ao_fsm_state((int *)arg, ao_context); | ||
2313 | case ME4000_GET_USER_INFO: | ||
2314 | return me4000_get_user_info((struct me4000_user_info *)arg, | ||
2315 | ao_context->board_info); | ||
2316 | case ME4000_AO_SYNCHRONOUS_EX_TRIG: | ||
2317 | return me4000_ao_synchronous_ex_trig(ao_context); | ||
2318 | case ME4000_AO_SYNCHRONOUS_SW: | ||
2319 | return me4000_ao_synchronous_sw(ao_context); | ||
2320 | case ME4000_AO_SYNCHRONOUS_DISABLE: | ||
2321 | return me4000_ao_synchronous_disable(ao_context); | ||
2322 | case ME4000_AO_GET_FREE_BUFFER: | ||
2323 | return me4000_ao_get_free_buffer((unsigned long *)arg, | ||
2324 | ao_context); | ||
2325 | default: | ||
2326 | return -ENOTTY; | ||
2327 | } | ||
2328 | return 0; | ||
2329 | } | ||
2330 | |||
2331 | static int me4000_ao_start(unsigned long *arg, | ||
2332 | struct me4000_ao_context *ao_context) | ||
2333 | { | ||
2334 | u32 tmp; | ||
2335 | wait_queue_head_t queue; | ||
2336 | unsigned long ref; | ||
2337 | unsigned long timeout; | ||
2338 | unsigned long flags; | ||
2339 | |||
2340 | CALL_PDEBUG("me4000_ao_start() is executed\n"); | ||
2341 | |||
2342 | if (get_user(timeout, arg)) { | ||
2343 | printk(KERN_ERR | ||
2344 | "me4000_ao_start():Cannot copy data from user\n"); | ||
2345 | return -EFAULT; | ||
2346 | } | ||
2347 | |||
2348 | init_waitqueue_head(&queue); | ||
2349 | |||
2350 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2351 | tmp = inl(ao_context->ctrl_reg); | ||
2352 | tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
2353 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2354 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2355 | |||
2356 | if ((tmp & ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG)) { | ||
2357 | if (timeout) { | ||
2358 | ref = jiffies; | ||
2359 | while (! | ||
2360 | (inl(ao_context->status_reg) & | ||
2361 | ME4000_AO_STATUS_BIT_FSM)) { | ||
2362 | interruptible_sleep_on_timeout(&queue, 1); | ||
2363 | if (signal_pending(current)) { | ||
2364 | printk(KERN_ERR | ||
2365 | "ME4000:me4000_ao_start():Wait on start of state machine interrupted\n"); | ||
2366 | return -EINTR; | ||
2367 | } | ||
2368 | /* kernel 2.6 has different definitions for HZ | ||
2369 | * in user and kernel space */ | ||
2370 | if ((jiffies - ref) > (timeout * HZ / USER_HZ)) { | ||
2371 | printk(KERN_ERR | ||
2372 | "ME4000:me4000_ao_start():Timeout reached\n"); | ||
2373 | return -EIO; | ||
2374 | } | ||
2375 | } | ||
2376 | } | ||
2377 | } else { | ||
2378 | me4000_outl(0x8000, ao_context->single_reg); | ||
2379 | } | ||
2380 | |||
2381 | return 0; | ||
2382 | } | ||
2383 | |||
2384 | static int me4000_ao_stop(struct me4000_ao_context *ao_context) | ||
2385 | { | ||
2386 | u32 tmp; | ||
2387 | wait_queue_head_t queue; | ||
2388 | unsigned long flags; | ||
2389 | |||
2390 | init_waitqueue_head(&queue); | ||
2391 | |||
2392 | CALL_PDEBUG("me4000_ao_stop() is executed\n"); | ||
2393 | |||
2394 | /* Set the stop bit */ | ||
2395 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2396 | tmp = inl(ao_context->ctrl_reg); | ||
2397 | tmp |= ME4000_AO_CTRL_BIT_STOP; | ||
2398 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2399 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2400 | |||
2401 | while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) { | ||
2402 | interruptible_sleep_on_timeout(&queue, 1); | ||
2403 | if (signal_pending(current)) { | ||
2404 | printk(KERN_ERR | ||
2405 | "me4000_ao_stop():Wait on state machine after stop interrupted\n"); | ||
2406 | return -EINTR; | ||
2407 | } | ||
2408 | } | ||
2409 | |||
2410 | /* Clear the stop bit */ | ||
2411 | /* tmp &= ~ME4000_AO_CTRL_BIT_STOP; */ | ||
2412 | /* me4000_outl(tmp, ao_context->ctrl_reg); */ | ||
2413 | |||
2414 | return 0; | ||
2415 | } | ||
2416 | |||
2417 | static int me4000_ao_immediate_stop(struct me4000_ao_context *ao_context) | ||
2418 | { | ||
2419 | u32 tmp; | ||
2420 | wait_queue_head_t queue; | ||
2421 | unsigned long flags; | ||
2422 | |||
2423 | init_waitqueue_head(&queue); | ||
2424 | |||
2425 | CALL_PDEBUG("me4000_ao_immediate_stop() is executed\n"); | ||
2426 | |||
2427 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2428 | tmp = inl(ao_context->ctrl_reg); | ||
2429 | tmp |= ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
2430 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2431 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2432 | |||
2433 | while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) { | ||
2434 | interruptible_sleep_on_timeout(&queue, 1); | ||
2435 | if (signal_pending(current)) { | ||
2436 | printk(KERN_ERR | ||
2437 | "me4000_ao_immediate_stop():Wait on state machine after stop interrupted\n"); | ||
2438 | return -EINTR; | ||
2439 | } | ||
2440 | } | ||
2441 | |||
2442 | /* Clear the stop bits */ | ||
2443 | /* tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP); */ | ||
2444 | /* me4000_outl(tmp, ao_context->ctrl_reg); */ | ||
2445 | |||
2446 | return 0; | ||
2447 | } | ||
2448 | |||
2449 | static int me4000_ao_timer_set_divisor(u32 *arg, | ||
2450 | struct me4000_ao_context *ao_context) | ||
2451 | { | ||
2452 | u32 divisor; | ||
2453 | u32 tmp; | ||
2454 | |||
2455 | CALL_PDEBUG("me4000_ao_timer set_divisor() is executed\n"); | ||
2456 | |||
2457 | if (get_user(divisor, arg)) | ||
2458 | return -EFAULT; | ||
2459 | |||
2460 | /* Check if the state machine is stopped */ | ||
2461 | tmp = me4000_inl(ao_context->status_reg); | ||
2462 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2463 | printk(KERN_ERR | ||
2464 | "me4000_ao_timer_set_divisor():Can't set timer while DAC is running\n"); | ||
2465 | return -EBUSY; | ||
2466 | } | ||
2467 | |||
2468 | PDEBUG("me4000_ao_timer set_divisor():Divisor from user = %d\n", | ||
2469 | divisor); | ||
2470 | |||
2471 | /* Check if the divisor is right. ME4000_AO_MIN_TICKS is the lowest */ | ||
2472 | if (divisor < ME4000_AO_MIN_TICKS) { | ||
2473 | printk(KERN_ERR | ||
2474 | "ME4000:me4000_ao_timer set_divisor():Divisor to low\n"); | ||
2475 | return -EINVAL; | ||
2476 | } | ||
2477 | |||
2478 | /* Fix bug in Firmware */ | ||
2479 | divisor -= 2; | ||
2480 | |||
2481 | PDEBUG("me4000_ao_timer set_divisor():Divisor to HW = %d\n", divisor); | ||
2482 | |||
2483 | /* Write the divisor */ | ||
2484 | me4000_outl(divisor, ao_context->timer_reg); | ||
2485 | |||
2486 | return 0; | ||
2487 | } | ||
2488 | |||
2489 | static int me4000_ao_ex_trig_set_edge(int *arg, | ||
2490 | struct me4000_ao_context *ao_context) | ||
2491 | { | ||
2492 | int mode; | ||
2493 | u32 tmp; | ||
2494 | unsigned long flags; | ||
2495 | |||
2496 | CALL_PDEBUG("me4000_ao_ex_trig_set_edge() is executed\n"); | ||
2497 | |||
2498 | if (get_user(mode, arg)) | ||
2499 | return -EFAULT; | ||
2500 | |||
2501 | /* Check if the state machine is stopped */ | ||
2502 | tmp = me4000_inl(ao_context->status_reg); | ||
2503 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2504 | printk(KERN_ERR | ||
2505 | "me4000_ao_ex_trig_set_edge():Can't set trigger while DAC is running\n"); | ||
2506 | return -EBUSY; | ||
2507 | } | ||
2508 | |||
2509 | if (mode == ME4000_AO_TRIGGER_EXT_EDGE_RISING) { | ||
2510 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2511 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2512 | tmp &= | ||
2513 | ~(ME4000_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
2514 | ME4000_AO_CTRL_BIT_EX_TRIG_BOTH); | ||
2515 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2516 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2517 | } else if (mode == ME4000_AO_TRIGGER_EXT_EDGE_FALLING) { | ||
2518 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2519 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2520 | tmp &= ~ME4000_AO_CTRL_BIT_EX_TRIG_BOTH; | ||
2521 | tmp |= ME4000_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
2522 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2523 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2524 | } else if (mode == ME4000_AO_TRIGGER_EXT_EDGE_BOTH) { | ||
2525 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2526 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2527 | tmp |= | ||
2528 | ME4000_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
2529 | ME4000_AO_CTRL_BIT_EX_TRIG_BOTH; | ||
2530 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2531 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2532 | } else { | ||
2533 | printk(KERN_ERR | ||
2534 | "me4000_ao_ex_trig_set_edge():Invalid trigger mode\n"); | ||
2535 | return -EINVAL; | ||
2536 | } | ||
2537 | |||
2538 | return 0; | ||
2539 | } | ||
2540 | |||
2541 | static int me4000_ao_ex_trig_enable(struct me4000_ao_context *ao_context) | ||
2542 | { | ||
2543 | u32 tmp; | ||
2544 | unsigned long flags; | ||
2545 | |||
2546 | CALL_PDEBUG("me4000_ao_ex_trig_enable() is executed\n"); | ||
2547 | |||
2548 | /* Check if the state machine is stopped */ | ||
2549 | tmp = me4000_inl(ao_context->status_reg); | ||
2550 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2551 | printk(KERN_ERR | ||
2552 | "me4000_ao_ex_trig_enable():Can't enable trigger while DAC is running\n"); | ||
2553 | return -EBUSY; | ||
2554 | } | ||
2555 | |||
2556 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2557 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2558 | tmp |= ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
2559 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2560 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2561 | |||
2562 | return 0; | ||
2563 | } | ||
2564 | |||
2565 | static int me4000_ao_ex_trig_disable(struct me4000_ao_context *ao_context) | ||
2566 | { | ||
2567 | u32 tmp; | ||
2568 | unsigned long flags; | ||
2569 | |||
2570 | CALL_PDEBUG("me4000_ao_ex_trig_disable() is executed\n"); | ||
2571 | |||
2572 | /* Check if the state machine is stopped */ | ||
2573 | tmp = me4000_inl(ao_context->status_reg); | ||
2574 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2575 | printk(KERN_ERR | ||
2576 | "me4000_ao_ex_trig_disable():Can't disable trigger while DAC is running\n"); | ||
2577 | return -EBUSY; | ||
2578 | } | ||
2579 | |||
2580 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2581 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2582 | tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
2583 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2584 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2585 | |||
2586 | return 0; | ||
2587 | } | ||
2588 | |||
2589 | static int me4000_ao_simultaneous_disable(struct me4000_ao_context *ao_context) | ||
2590 | { | ||
2591 | u32 tmp; | ||
2592 | |||
2593 | CALL_PDEBUG("me4000_ao_simultaneous_disable() is executed\n"); | ||
2594 | |||
2595 | /* Check if the state machine is stopped */ | ||
2596 | /* Be careful here because this function is called from | ||
2597 | me4000_ao_synchronous disable */ | ||
2598 | tmp = me4000_inl(ao_context->status_reg); | ||
2599 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2600 | printk(KERN_ERR | ||
2601 | "me4000_ao_simultaneous_disable():Can't disable while DAC is running\n"); | ||
2602 | return -EBUSY; | ||
2603 | } | ||
2604 | |||
2605 | spin_lock(&ao_context->board_info->preload_lock); | ||
2606 | tmp = me4000_inl(ao_context->preload_reg); | ||
2607 | /* Disable preload bit */ | ||
2608 | tmp &= ~(0x1 << ao_context->index); | ||
2609 | /* Disable hw simultaneous bit */ | ||
2610 | tmp &= ~(0x1 << (ao_context->index + 16)); | ||
2611 | me4000_outl(tmp, ao_context->preload_reg); | ||
2612 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2613 | |||
2614 | return 0; | ||
2615 | } | ||
2616 | |||
2617 | static int me4000_ao_simultaneous_ex_trig(struct me4000_ao_context *ao_context) | ||
2618 | { | ||
2619 | u32 tmp; | ||
2620 | |||
2621 | CALL_PDEBUG("me4000_ao_simultaneous_ex_trig() is executed\n"); | ||
2622 | |||
2623 | spin_lock(&ao_context->board_info->preload_lock); | ||
2624 | tmp = me4000_inl(ao_context->preload_reg); | ||
2625 | /* Enable preload bit */ | ||
2626 | tmp |= (0x1 << ao_context->index); | ||
2627 | /* Enable hw simulatenous bit */ | ||
2628 | tmp |= (0x1 << (ao_context->index + 16)); | ||
2629 | me4000_outl(tmp, ao_context->preload_reg); | ||
2630 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2631 | |||
2632 | return 0; | ||
2633 | } | ||
2634 | |||
2635 | static int me4000_ao_simultaneous_sw(struct me4000_ao_context *ao_context) | ||
2636 | { | ||
2637 | u32 tmp; | ||
2638 | |||
2639 | CALL_PDEBUG("me4000_ao_simultaneous_sw() is executed\n"); | ||
2640 | |||
2641 | spin_lock(&ao_context->board_info->preload_lock); | ||
2642 | tmp = me4000_inl(ao_context->preload_reg); | ||
2643 | /* Enable preload bit */ | ||
2644 | tmp |= (0x1 << ao_context->index); | ||
2645 | /* Enable hw simulatenous bit */ | ||
2646 | tmp &= ~(0x1 << (ao_context->index + 16)); | ||
2647 | me4000_outl(tmp, ao_context->preload_reg); | ||
2648 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2649 | |||
2650 | return 0; | ||
2651 | } | ||
2652 | |||
2653 | static int me4000_ao_preload(struct me4000_ao_context *ao_context) | ||
2654 | { | ||
2655 | CALL_PDEBUG("me4000_ao_preload() is executed\n"); | ||
2656 | return me4000_ao_simultaneous_sw(ao_context); | ||
2657 | } | ||
2658 | |||
2659 | static int me4000_ao_preload_update(struct me4000_ao_context *ao_context) | ||
2660 | { | ||
2661 | u32 tmp; | ||
2662 | u32 ctrl; | ||
2663 | struct list_head *entry; | ||
2664 | |||
2665 | CALL_PDEBUG("me4000_ao_preload_update() is executed\n"); | ||
2666 | |||
2667 | spin_lock(&ao_context->board_info->preload_lock); | ||
2668 | tmp = me4000_inl(ao_context->preload_reg); | ||
2669 | list_for_each(entry, &ao_context->board_info->ao_context_list) { | ||
2670 | /* The channels we update must be in the following state : | ||
2671 | - Mode A | ||
2672 | - Hardware trigger is disabled | ||
2673 | - Corresponding simultaneous bit is reset | ||
2674 | */ | ||
2675 | ctrl = me4000_inl(ao_context->ctrl_reg); | ||
2676 | if (! | ||
2677 | (ctrl & | ||
2678 | (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1 | | ||
2679 | ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG))) { | ||
2680 | if (! | ||
2681 | (tmp & | ||
2682 | (0x1 << | ||
2683 | (((struct me4000_ao_context *)entry)->index | ||
2684 | + 16)))) { | ||
2685 | tmp &= | ||
2686 | ~(0x1 << | ||
2687 | (((struct me4000_ao_context *)entry)-> | ||
2688 | index)); | ||
2689 | } | ||
2690 | } | ||
2691 | } | ||
2692 | me4000_outl(tmp, ao_context->preload_reg); | ||
2693 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2694 | |||
2695 | return 0; | ||
2696 | } | ||
2697 | |||
2698 | static int me4000_ao_simultaneous_update(struct me4000_ao_channel_list *arg, | ||
2699 | struct me4000_ao_context *ao_context) | ||
2700 | { | ||
2701 | int err; | ||
2702 | int i; | ||
2703 | u32 tmp; | ||
2704 | struct me4000_ao_channel_list channels; | ||
2705 | |||
2706 | CALL_PDEBUG("me4000_ao_simultaneous_update() is executed\n"); | ||
2707 | |||
2708 | /* Copy data from user */ | ||
2709 | err = copy_from_user(&channels, arg, | ||
2710 | sizeof(struct me4000_ao_channel_list)); | ||
2711 | if (err) { | ||
2712 | printk(KERN_ERR | ||
2713 | "ME4000:me4000_ao_simultaneous_update():Can't copy command\n"); | ||
2714 | return -EFAULT; | ||
2715 | } | ||
2716 | |||
2717 | channels.list = | ||
2718 | kzalloc(sizeof(unsigned long) * channels.count, GFP_KERNEL); | ||
2719 | if (!channels.list) { | ||
2720 | printk(KERN_ERR | ||
2721 | "ME4000:me4000_ao_simultaneous_update():Can't get buffer\n"); | ||
2722 | return -ENOMEM; | ||
2723 | } | ||
2724 | |||
2725 | /* Copy channel list from user */ | ||
2726 | err = | ||
2727 | copy_from_user(channels.list, arg->list, | ||
2728 | sizeof(unsigned long) * channels.count); | ||
2729 | if (err) { | ||
2730 | printk(KERN_ERR | ||
2731 | "ME4000:me4000_ao_simultaneous_update():Can't copy list\n"); | ||
2732 | kfree(channels.list); | ||
2733 | return -EFAULT; | ||
2734 | } | ||
2735 | |||
2736 | spin_lock(&ao_context->board_info->preload_lock); | ||
2737 | tmp = me4000_inl(ao_context->preload_reg); | ||
2738 | for (i = 0; i < channels.count; i++) { | ||
2739 | if (channels.list[i] > | ||
2740 | ao_context->board_info->board_p->ao.count) { | ||
2741 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2742 | kfree(channels.list); | ||
2743 | printk(KERN_ERR | ||
2744 | "ME4000:me4000_ao_simultaneous_update():Invalid board number specified\n"); | ||
2745 | return -EFAULT; | ||
2746 | } | ||
2747 | /* Clear the preload bit */ | ||
2748 | tmp &= ~(0x1 << channels.list[i]); | ||
2749 | /* Clear the hw simultaneous bit */ | ||
2750 | tmp &= ~(0x1 << (channels.list[i] + 16)); | ||
2751 | } | ||
2752 | me4000_outl(tmp, ao_context->preload_reg); | ||
2753 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2754 | kfree(channels.list); | ||
2755 | |||
2756 | return 0; | ||
2757 | } | ||
2758 | |||
2759 | static int me4000_ao_synchronous_ex_trig(struct me4000_ao_context *ao_context) | ||
2760 | { | ||
2761 | u32 tmp; | ||
2762 | unsigned long flags; | ||
2763 | |||
2764 | CALL_PDEBUG("me4000_ao_synchronous_ex_trig() is executed\n"); | ||
2765 | |||
2766 | /* Check if the state machine is stopped */ | ||
2767 | tmp = me4000_inl(ao_context->status_reg); | ||
2768 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2769 | printk(KERN_ERR | ||
2770 | "me4000_ao_synchronous_ex_trig(): DAC is running\n"); | ||
2771 | return -EBUSY; | ||
2772 | } | ||
2773 | |||
2774 | spin_lock(&ao_context->board_info->preload_lock); | ||
2775 | tmp = me4000_inl(ao_context->preload_reg); | ||
2776 | /* Disable synchronous sw bit */ | ||
2777 | tmp &= ~(0x1 << ao_context->index); | ||
2778 | /* Enable synchronous hw bit */ | ||
2779 | tmp |= 0x1 << (ao_context->index + 16); | ||
2780 | me4000_outl(tmp, ao_context->preload_reg); | ||
2781 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2782 | |||
2783 | /* Make runnable */ | ||
2784 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2785 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2786 | if (tmp & (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1)) { | ||
2787 | tmp &= | ||
2788 | ~(ME4000_AO_CTRL_BIT_STOP | | ||
2789 | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
2790 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2791 | } | ||
2792 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2793 | |||
2794 | return 0; | ||
2795 | } | ||
2796 | |||
2797 | static int me4000_ao_synchronous_sw(struct me4000_ao_context *ao_context) | ||
2798 | { | ||
2799 | u32 tmp; | ||
2800 | unsigned long flags; | ||
2801 | |||
2802 | CALL_PDEBUG("me4000_ao_synchronous_sw() is executed\n"); | ||
2803 | |||
2804 | /* Check if the state machine is stopped */ | ||
2805 | tmp = me4000_inl(ao_context->status_reg); | ||
2806 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2807 | printk(KERN_ERR "me4000_ao_synchronous_sw(): DAC is running\n"); | ||
2808 | return -EBUSY; | ||
2809 | } | ||
2810 | |||
2811 | spin_lock(&ao_context->board_info->preload_lock); | ||
2812 | tmp = me4000_inl(ao_context->preload_reg); | ||
2813 | /* Enable synchronous sw bit */ | ||
2814 | tmp |= 0x1 << ao_context->index; | ||
2815 | /* Disable synchronous hw bit */ | ||
2816 | tmp &= ~(0x1 << (ao_context->index + 16)); | ||
2817 | me4000_outl(tmp, ao_context->preload_reg); | ||
2818 | spin_unlock(&ao_context->board_info->preload_lock); | ||
2819 | |||
2820 | /* Make runnable */ | ||
2821 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2822 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
2823 | if (tmp & (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1)) { | ||
2824 | tmp &= | ||
2825 | ~(ME4000_AO_CTRL_BIT_STOP | | ||
2826 | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
2827 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2828 | } | ||
2829 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2830 | |||
2831 | return 0; | ||
2832 | } | ||
2833 | |||
2834 | static int me4000_ao_synchronous_disable(struct me4000_ao_context *ao_context) | ||
2835 | { | ||
2836 | return me4000_ao_simultaneous_disable(ao_context); | ||
2837 | } | ||
2838 | |||
2839 | static int me4000_ao_get_free_buffer(unsigned long *arg, | ||
2840 | struct me4000_ao_context *ao_context) | ||
2841 | { | ||
2842 | unsigned long c; | ||
2843 | int err; | ||
2844 | |||
2845 | c = me4000_buf_space(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT); | ||
2846 | |||
2847 | err = copy_to_user(arg, &c, sizeof(unsigned long)); | ||
2848 | if (err) { | ||
2849 | printk(KERN_ERR | ||
2850 | "%s:Can't copy to user space\n", __func__); | ||
2851 | return -EFAULT; | ||
2852 | } | ||
2853 | |||
2854 | return 0; | ||
2855 | } | ||
2856 | |||
2857 | static int me4000_ao_ex_trig_timeout(unsigned long *arg, | ||
2858 | struct me4000_ao_context *ao_context) | ||
2859 | { | ||
2860 | u32 tmp; | ||
2861 | wait_queue_head_t queue; | ||
2862 | unsigned long ref; | ||
2863 | unsigned long timeout; | ||
2864 | |||
2865 | CALL_PDEBUG("me4000_ao_ex_trig_timeout() is executed\n"); | ||
2866 | |||
2867 | if (get_user(timeout, arg)) { | ||
2868 | printk(KERN_ERR | ||
2869 | "me4000_ao_ex_trig_timeout():Cannot copy data from user\n"); | ||
2870 | return -EFAULT; | ||
2871 | } | ||
2872 | |||
2873 | init_waitqueue_head(&queue); | ||
2874 | |||
2875 | tmp = inl(ao_context->ctrl_reg); | ||
2876 | |||
2877 | if ((tmp & ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG)) { | ||
2878 | if (timeout) { | ||
2879 | ref = jiffies; | ||
2880 | while ((inl(ao_context->status_reg) & | ||
2881 | ME4000_AO_STATUS_BIT_FSM)) { | ||
2882 | interruptible_sleep_on_timeout(&queue, 1); | ||
2883 | if (signal_pending(current)) { | ||
2884 | printk(KERN_ERR | ||
2885 | "ME4000:me4000_ao_ex_trig_timeout():Wait on start of state machine interrupted\n"); | ||
2886 | return -EINTR; | ||
2887 | } | ||
2888 | /* kernel 2.6 has different definitions for HZ | ||
2889 | * in user and kernel space */ | ||
2890 | if ((jiffies - ref) > (timeout * HZ / USER_HZ)) { | ||
2891 | printk(KERN_ERR | ||
2892 | "ME4000:me4000_ao_ex_trig_timeout():Timeout reached\n"); | ||
2893 | return -EIO; | ||
2894 | } | ||
2895 | } | ||
2896 | } else { | ||
2897 | while ((inl(ao_context->status_reg) & | ||
2898 | ME4000_AO_STATUS_BIT_FSM)) { | ||
2899 | interruptible_sleep_on_timeout(&queue, 1); | ||
2900 | if (signal_pending(current)) { | ||
2901 | printk(KERN_ERR | ||
2902 | "ME4000:me4000_ao_ex_trig_timeout():Wait on start of state machine interrupted\n"); | ||
2903 | return -EINTR; | ||
2904 | } | ||
2905 | } | ||
2906 | } | ||
2907 | } else { | ||
2908 | printk(KERN_ERR | ||
2909 | "ME4000:me4000_ao_ex_trig_timeout():External Trigger is not enabled\n"); | ||
2910 | return -EINVAL; | ||
2911 | } | ||
2912 | |||
2913 | return 0; | ||
2914 | } | ||
2915 | |||
2916 | static int me4000_ao_enable_do(struct me4000_ao_context *ao_context) | ||
2917 | { | ||
2918 | u32 tmp; | ||
2919 | unsigned long flags; | ||
2920 | |||
2921 | CALL_PDEBUG("me4000_ao_enable_do() is executed\n"); | ||
2922 | |||
2923 | /* Only available for analog output 3 */ | ||
2924 | if (ao_context->index != 3) { | ||
2925 | printk(KERN_ERR | ||
2926 | "me4000_ao_enable_do():Only available for analog output 3\n"); | ||
2927 | return -ENOTTY; | ||
2928 | } | ||
2929 | |||
2930 | /* Check if the state machine is stopped */ | ||
2931 | tmp = me4000_inl(ao_context->status_reg); | ||
2932 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2933 | printk(KERN_ERR "me4000_ao_enable_do(): DAC is running\n"); | ||
2934 | return -EBUSY; | ||
2935 | } | ||
2936 | |||
2937 | /* Set the stop bit */ | ||
2938 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2939 | tmp = inl(ao_context->ctrl_reg); | ||
2940 | tmp |= ME4000_AO_CTRL_BIT_ENABLE_DO; | ||
2941 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2942 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2943 | |||
2944 | return 0; | ||
2945 | } | ||
2946 | |||
2947 | static int me4000_ao_disable_do(struct me4000_ao_context *ao_context) | ||
2948 | { | ||
2949 | u32 tmp; | ||
2950 | unsigned long flags; | ||
2951 | |||
2952 | CALL_PDEBUG("me4000_ao_disable_do() is executed\n"); | ||
2953 | |||
2954 | /* Only available for analog output 3 */ | ||
2955 | if (ao_context->index != 3) { | ||
2956 | printk(KERN_ERR | ||
2957 | "me4000_ao_disable():Only available for analog output 3\n"); | ||
2958 | return -ENOTTY; | ||
2959 | } | ||
2960 | |||
2961 | /* Check if the state machine is stopped */ | ||
2962 | tmp = me4000_inl(ao_context->status_reg); | ||
2963 | if (tmp & ME4000_AO_STATUS_BIT_FSM) { | ||
2964 | printk(KERN_ERR "me4000_ao_disable_do(): DAC is running\n"); | ||
2965 | return -EBUSY; | ||
2966 | } | ||
2967 | |||
2968 | spin_lock_irqsave(&ao_context->int_lock, flags); | ||
2969 | tmp = inl(ao_context->ctrl_reg); | ||
2970 | tmp &= ~(ME4000_AO_CTRL_BIT_ENABLE_DO); | ||
2971 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
2972 | spin_unlock_irqrestore(&ao_context->int_lock, flags); | ||
2973 | |||
2974 | return 0; | ||
2975 | } | ||
2976 | |||
2977 | static int me4000_ao_fsm_state(int *arg, struct me4000_ao_context *ao_context) | ||
2978 | { | ||
2979 | unsigned long tmp; | ||
2980 | |||
2981 | CALL_PDEBUG("me4000_ao_fsm_state() is executed\n"); | ||
2982 | |||
2983 | tmp = | ||
2984 | (me4000_inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) ? 1 | ||
2985 | : 0; | ||
2986 | |||
2987 | if (ao_context->pipe_flag) { | ||
2988 | printk(KERN_ERR "me4000_ao_fsm_state():Broken pipe detected\n"); | ||
2989 | return -EPIPE; | ||
2990 | } | ||
2991 | |||
2992 | if (put_user(tmp, arg)) { | ||
2993 | printk(KERN_ERR "me4000_ao_fsm_state():Cannot copy to user\n"); | ||
2994 | return -EFAULT; | ||
2995 | } | ||
2996 | |||
2997 | return 0; | ||
2998 | } | ||
2999 | |||
3000 | /*------------------------- Analog input stuff -------------------------------*/ | ||
3001 | |||
3002 | static int me4000_ai_prepare(struct me4000_ai_context *ai_context) | ||
3003 | { | ||
3004 | wait_queue_head_t queue; | ||
3005 | int err; | ||
3006 | |||
3007 | CALL_PDEBUG("me4000_ai_prepare() is executed\n"); | ||
3008 | |||
3009 | init_waitqueue_head(&queue); | ||
3010 | |||
3011 | /* Set the new mode and stop bits */ | ||
3012 | me4000_outl(ai_context-> | ||
3013 | mode | ME4000_AI_CTRL_BIT_STOP | | ||
3014 | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP, ai_context->ctrl_reg); | ||
3015 | |||
3016 | /* Set the timer registers */ | ||
3017 | ai_context->chan_timer = 66; | ||
3018 | ai_context->chan_pre_timer = 66; | ||
3019 | ai_context->scan_timer_low = 0; | ||
3020 | ai_context->scan_timer_high = 0; | ||
3021 | |||
3022 | me4000_outl(65, ai_context->chan_timer_reg); | ||
3023 | me4000_outl(65, ai_context->chan_pre_timer_reg); | ||
3024 | me4000_outl(0, ai_context->scan_timer_low_reg); | ||
3025 | me4000_outl(0, ai_context->scan_timer_high_reg); | ||
3026 | me4000_outl(0, ai_context->scan_pre_timer_low_reg); | ||
3027 | me4000_outl(0, ai_context->scan_pre_timer_high_reg); | ||
3028 | |||
3029 | ai_context->channel_list_count = 0; | ||
3030 | |||
3031 | if (ai_context->mode) { | ||
3032 | /* Request the interrupt line */ | ||
3033 | err = | ||
3034 | request_irq(ai_context->irq, me4000_ai_isr, | ||
3035 | IRQF_DISABLED | IRQF_SHARED, ME4000_NAME, | ||
3036 | ai_context); | ||
3037 | if (err) { | ||
3038 | printk(KERN_ERR | ||
3039 | "ME4000:me4000_ai_prepare():Can't get interrupt line"); | ||
3040 | return -ENODEV; | ||
3041 | } | ||
3042 | |||
3043 | /* Allocate circular buffer */ | ||
3044 | ai_context->circ_buf.buf = | ||
3045 | kzalloc(ME4000_AI_BUFFER_SIZE, GFP_KERNEL); | ||
3046 | if (!ai_context->circ_buf.buf) { | ||
3047 | printk(KERN_ERR | ||
3048 | "ME4000:me4000_ai_prepare():Can't get circular buffer\n"); | ||
3049 | free_irq(ai_context->irq, ai_context); | ||
3050 | return -ENOMEM; | ||
3051 | } | ||
3052 | |||
3053 | /* Clear the circular buffer */ | ||
3054 | ai_context->circ_buf.head = 0; | ||
3055 | ai_context->circ_buf.tail = 0; | ||
3056 | } | ||
3057 | |||
3058 | return 0; | ||
3059 | } | ||
3060 | |||
3061 | static int me4000_ai_reset(struct me4000_ai_context *ai_context) | ||
3062 | { | ||
3063 | wait_queue_head_t queue; | ||
3064 | u32 tmp; | ||
3065 | unsigned long flags; | ||
3066 | |||
3067 | CALL_PDEBUG("me4000_ai_reset() is executed\n"); | ||
3068 | |||
3069 | init_waitqueue_head(&queue); | ||
3070 | |||
3071 | /* | ||
3072 | * First stop conversion of the state machine before reconfigure. | ||
3073 | * If not stopped before configuring mode, it could | ||
3074 | * walk in a undefined state. | ||
3075 | */ | ||
3076 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
3077 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3078 | tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
3079 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3080 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3081 | |||
3082 | while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) { | ||
3083 | interruptible_sleep_on_timeout(&queue, 1); | ||
3084 | if (signal_pending(current)) { | ||
3085 | printk(KERN_ERR | ||
3086 | "me4000_ai_reset():Wait on state machine after stop interrupted\n"); | ||
3087 | return -EINTR; | ||
3088 | } | ||
3089 | } | ||
3090 | |||
3091 | /* Clear the control register and set the stop bits */ | ||
3092 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
3093 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3094 | me4000_outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP, | ||
3095 | ai_context->ctrl_reg); | ||
3096 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3097 | |||
3098 | /* Reset timer registers */ | ||
3099 | ai_context->chan_timer = 66; | ||
3100 | ai_context->chan_pre_timer = 66; | ||
3101 | ai_context->scan_timer_low = 0; | ||
3102 | ai_context->scan_timer_high = 0; | ||
3103 | ai_context->sample_counter = 0; | ||
3104 | ai_context->sample_counter_reload = 0; | ||
3105 | |||
3106 | me4000_outl(65, ai_context->chan_timer_reg); | ||
3107 | me4000_outl(65, ai_context->chan_pre_timer_reg); | ||
3108 | me4000_outl(0, ai_context->scan_timer_low_reg); | ||
3109 | me4000_outl(0, ai_context->scan_timer_high_reg); | ||
3110 | me4000_outl(0, ai_context->scan_pre_timer_low_reg); | ||
3111 | me4000_outl(0, ai_context->scan_pre_timer_high_reg); | ||
3112 | me4000_outl(0, ai_context->sample_counter_reg); | ||
3113 | |||
3114 | ai_context->channel_list_count = 0; | ||
3115 | |||
3116 | /* Clear the circular buffer */ | ||
3117 | ai_context->circ_buf.head = 0; | ||
3118 | ai_context->circ_buf.tail = 0; | ||
3119 | |||
3120 | return 0; | ||
3121 | } | ||
3122 | |||
3123 | static int me4000_ai_ioctl_sing(struct inode *inode_p, struct file *file_p, | ||
3124 | unsigned int service, unsigned long arg) | ||
3125 | { | ||
3126 | struct me4000_ai_context *ai_context; | ||
3127 | |||
3128 | CALL_PDEBUG("me4000_ai_ioctl_sing() is executed\n"); | ||
3129 | |||
3130 | ai_context = file_p->private_data; | ||
3131 | |||
3132 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
3133 | printk(KERN_ERR "me4000_ai_ioctl_sing():Wrong magic number\n"); | ||
3134 | return -ENOTTY; | ||
3135 | } | ||
3136 | if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) { | ||
3137 | printk(KERN_ERR | ||
3138 | "me4000_ai_ioctl_sing():Service number to high\n"); | ||
3139 | return -ENOTTY; | ||
3140 | } | ||
3141 | |||
3142 | switch (service) { | ||
3143 | case ME4000_AI_SINGLE: | ||
3144 | return me4000_ai_single((struct me4000_ai_single *)arg, | ||
3145 | ai_context); | ||
3146 | case ME4000_AI_EX_TRIG_ENABLE: | ||
3147 | return me4000_ai_ex_trig_enable(ai_context); | ||
3148 | case ME4000_AI_EX_TRIG_DISABLE: | ||
3149 | return me4000_ai_ex_trig_disable(ai_context); | ||
3150 | case ME4000_AI_EX_TRIG_SETUP: | ||
3151 | return me4000_ai_ex_trig_setup((struct me4000_ai_trigger *)arg, | ||
3152 | ai_context); | ||
3153 | case ME4000_GET_USER_INFO: | ||
3154 | return me4000_get_user_info((struct me4000_user_info *)arg, | ||
3155 | ai_context->board_info); | ||
3156 | case ME4000_AI_OFFSET_ENABLE: | ||
3157 | return me4000_ai_offset_enable(ai_context); | ||
3158 | case ME4000_AI_OFFSET_DISABLE: | ||
3159 | return me4000_ai_offset_disable(ai_context); | ||
3160 | case ME4000_AI_FULLSCALE_ENABLE: | ||
3161 | return me4000_ai_fullscale_enable(ai_context); | ||
3162 | case ME4000_AI_FULLSCALE_DISABLE: | ||
3163 | return me4000_ai_fullscale_disable(ai_context); | ||
3164 | case ME4000_AI_EEPROM_READ: | ||
3165 | return me4000_eeprom_read((struct me4000_eeprom *)arg, | ||
3166 | ai_context); | ||
3167 | case ME4000_AI_EEPROM_WRITE: | ||
3168 | return me4000_eeprom_write((struct me4000_eeprom *)arg, | ||
3169 | ai_context); | ||
3170 | default: | ||
3171 | printk(KERN_ERR | ||
3172 | "me4000_ai_ioctl_sing():Invalid service number\n"); | ||
3173 | return -ENOTTY; | ||
3174 | } | ||
3175 | return 0; | ||
3176 | } | ||
3177 | |||
3178 | static int me4000_ai_single(struct me4000_ai_single *arg, | ||
3179 | struct me4000_ai_context *ai_context) | ||
3180 | { | ||
3181 | struct me4000_ai_single cmd; | ||
3182 | int err; | ||
3183 | u32 tmp; | ||
3184 | wait_queue_head_t queue; | ||
3185 | unsigned long jiffy; | ||
3186 | |||
3187 | CALL_PDEBUG("me4000_ai_single() is executed\n"); | ||
3188 | |||
3189 | init_waitqueue_head(&queue); | ||
3190 | |||
3191 | /* Copy data from user */ | ||
3192 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_single)); | ||
3193 | if (err) { | ||
3194 | printk(KERN_ERR | ||
3195 | "ME4000:me4000_ai_single():Can't copy from user space\n"); | ||
3196 | return -EFAULT; | ||
3197 | } | ||
3198 | |||
3199 | /* Check range parameter */ | ||
3200 | switch (cmd.range) { | ||
3201 | case ME4000_AI_LIST_RANGE_BIPOLAR_10: | ||
3202 | case ME4000_AI_LIST_RANGE_BIPOLAR_2_5: | ||
3203 | case ME4000_AI_LIST_RANGE_UNIPOLAR_10: | ||
3204 | case ME4000_AI_LIST_RANGE_UNIPOLAR_2_5: | ||
3205 | break; | ||
3206 | default: | ||
3207 | printk(KERN_ERR | ||
3208 | "ME4000:me4000_ai_single():Invalid range specified\n"); | ||
3209 | return -EINVAL; | ||
3210 | } | ||
3211 | |||
3212 | /* Check mode and channel number */ | ||
3213 | switch (cmd.mode) { | ||
3214 | case ME4000_AI_LIST_INPUT_SINGLE_ENDED: | ||
3215 | if (cmd.channel >= ai_context->board_info->board_p->ai.count) { | ||
3216 | printk(KERN_ERR | ||
3217 | "ME4000:me4000_ai_single():Analog input is not available\n"); | ||
3218 | return -EINVAL; | ||
3219 | } | ||
3220 | break; | ||
3221 | case ME4000_AI_LIST_INPUT_DIFFERENTIAL: | ||
3222 | if (cmd.channel >= | ||
3223 | ai_context->board_info->board_p->ai.diff_count) { | ||
3224 | printk(KERN_ERR | ||
3225 | "ME4000:me4000_ai_single():Analog input is not available in differential mode\n"); | ||
3226 | return -EINVAL; | ||
3227 | } | ||
3228 | break; | ||
3229 | default: | ||
3230 | printk(KERN_ERR | ||
3231 | "ME4000:me4000_ai_single():Invalid mode specified\n"); | ||
3232 | return -EINVAL; | ||
3233 | } | ||
3234 | |||
3235 | /* Clear channel list, data fifo and both stop bits */ | ||
3236 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3237 | tmp &= | ||
3238 | ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO | | ||
3239 | ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); | ||
3240 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3241 | |||
3242 | /* Enable channel list and data fifo */ | ||
3243 | tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO; | ||
3244 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3245 | |||
3246 | /* Generate channel list entry */ | ||
3247 | me4000_outl(cmd.channel | cmd.range | cmd. | ||
3248 | mode | ME4000_AI_LIST_LAST_ENTRY, | ||
3249 | ai_context->channel_list_reg); | ||
3250 | |||
3251 | /* Set the timer to maximum */ | ||
3252 | me4000_outl(66, ai_context->chan_timer_reg); | ||
3253 | me4000_outl(66, ai_context->chan_pre_timer_reg); | ||
3254 | |||
3255 | if (tmp & ME4000_AI_CTRL_BIT_EX_TRIG) { | ||
3256 | jiffy = jiffies; | ||
3257 | while (! | ||
3258 | (me4000_inl(ai_context->status_reg) & | ||
3259 | ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
3260 | interruptible_sleep_on_timeout(&queue, 1); | ||
3261 | if (signal_pending(current)) { | ||
3262 | printk(KERN_ERR | ||
3263 | "ME4000:me4000_ai_single():Wait on start of state machine interrupted\n"); | ||
3264 | return -EINTR; | ||
3265 | } | ||
3266 | /* 2.6 has different definitions for HZ in user and kernel space */ | ||
3267 | if (((jiffies - jiffy) > (cmd.timeout * HZ / USER_HZ)) && cmd.timeout) { | ||
3268 | printk(KERN_ERR | ||
3269 | "ME4000:me4000_ai_single():Timeout reached\n"); | ||
3270 | return -EIO; | ||
3271 | } | ||
3272 | } | ||
3273 | } else { | ||
3274 | /* Start conversion */ | ||
3275 | me4000_inl(ai_context->start_reg); | ||
3276 | |||
3277 | /* Wait until ready */ | ||
3278 | udelay(10); | ||
3279 | if (! | ||
3280 | (me4000_inl(ai_context->status_reg) & | ||
3281 | ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
3282 | printk(KERN_ERR | ||
3283 | "ME4000:me4000_ai_single():Value not available after wait\n"); | ||
3284 | return -EIO; | ||
3285 | } | ||
3286 | } | ||
3287 | |||
3288 | /* Read value from data fifo */ | ||
3289 | cmd.value = me4000_inl(ai_context->data_reg) & 0xFFFF; | ||
3290 | |||
3291 | /* Copy result back to user */ | ||
3292 | err = copy_to_user(arg, &cmd, sizeof(struct me4000_ai_single)); | ||
3293 | if (err) { | ||
3294 | printk(KERN_ERR | ||
3295 | "ME4000:me4000_ai_single():Can't copy to user space\n"); | ||
3296 | return -EFAULT; | ||
3297 | } | ||
3298 | |||
3299 | return 0; | ||
3300 | } | ||
3301 | |||
3302 | static int me4000_ai_ioctl_sw(struct inode *inode_p, struct file *file_p, | ||
3303 | unsigned int service, unsigned long arg) | ||
3304 | { | ||
3305 | struct me4000_ai_context *ai_context; | ||
3306 | |||
3307 | CALL_PDEBUG("me4000_ai_ioctl_sw() is executed\n"); | ||
3308 | |||
3309 | ai_context = file_p->private_data; | ||
3310 | |||
3311 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
3312 | printk(KERN_ERR "me4000_ai_ioctl_sw():Wrong magic number\n"); | ||
3313 | return -ENOTTY; | ||
3314 | } | ||
3315 | if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) { | ||
3316 | printk(KERN_ERR | ||
3317 | "me4000_ai_ioctl_sw():Service number to high\n"); | ||
3318 | return -ENOTTY; | ||
3319 | } | ||
3320 | |||
3321 | switch (service) { | ||
3322 | case ME4000_AI_SC_SETUP: | ||
3323 | return me4000_ai_sc_setup((struct me4000_ai_sc *)arg, | ||
3324 | ai_context); | ||
3325 | case ME4000_AI_CONFIG: | ||
3326 | return me4000_ai_config((struct me4000_ai_config *)arg, | ||
3327 | ai_context); | ||
3328 | case ME4000_AI_START: | ||
3329 | return me4000_ai_start(ai_context); | ||
3330 | case ME4000_AI_STOP: | ||
3331 | return me4000_ai_stop(ai_context); | ||
3332 | case ME4000_AI_IMMEDIATE_STOP: | ||
3333 | return me4000_ai_immediate_stop(ai_context); | ||
3334 | case ME4000_AI_FSM_STATE: | ||
3335 | return me4000_ai_fsm_state((int *)arg, ai_context); | ||
3336 | case ME4000_GET_USER_INFO: | ||
3337 | return me4000_get_user_info((struct me4000_user_info *)arg, | ||
3338 | ai_context->board_info); | ||
3339 | case ME4000_AI_EEPROM_READ: | ||
3340 | return me4000_eeprom_read((struct me4000_eeprom *)arg, | ||
3341 | ai_context); | ||
3342 | case ME4000_AI_EEPROM_WRITE: | ||
3343 | return me4000_eeprom_write((struct me4000_eeprom *)arg, | ||
3344 | ai_context); | ||
3345 | case ME4000_AI_GET_COUNT_BUFFER: | ||
3346 | return me4000_ai_get_count_buffer((unsigned long *)arg, | ||
3347 | ai_context); | ||
3348 | default: | ||
3349 | printk(KERN_ERR | ||
3350 | "%s:Invalid service number %d\n", __func__, service); | ||
3351 | return -ENOTTY; | ||
3352 | } | ||
3353 | return 0; | ||
3354 | } | ||
3355 | |||
3356 | static int me4000_ai_ioctl_ext(struct inode *inode_p, struct file *file_p, | ||
3357 | unsigned int service, unsigned long arg) | ||
3358 | { | ||
3359 | struct me4000_ai_context *ai_context; | ||
3360 | |||
3361 | CALL_PDEBUG("me4000_ai_ioctl_ext() is executed\n"); | ||
3362 | |||
3363 | ai_context = file_p->private_data; | ||
3364 | |||
3365 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
3366 | printk(KERN_ERR "me4000_ai_ioctl_ext():Wrong magic number\n"); | ||
3367 | return -ENOTTY; | ||
3368 | } | ||
3369 | if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) { | ||
3370 | printk(KERN_ERR | ||
3371 | "me4000_ai_ioctl_ext():Service number to high\n"); | ||
3372 | return -ENOTTY; | ||
3373 | } | ||
3374 | |||
3375 | switch (service) { | ||
3376 | case ME4000_AI_SC_SETUP: | ||
3377 | return me4000_ai_sc_setup((struct me4000_ai_sc *)arg, | ||
3378 | ai_context); | ||
3379 | case ME4000_AI_CONFIG: | ||
3380 | return me4000_ai_config((struct me4000_ai_config *)arg, | ||
3381 | ai_context); | ||
3382 | case ME4000_AI_START: | ||
3383 | return me4000_ai_start_ex((unsigned long *)arg, ai_context); | ||
3384 | case ME4000_AI_STOP: | ||
3385 | return me4000_ai_stop(ai_context); | ||
3386 | case ME4000_AI_IMMEDIATE_STOP: | ||
3387 | return me4000_ai_immediate_stop(ai_context); | ||
3388 | case ME4000_AI_EX_TRIG_ENABLE: | ||
3389 | return me4000_ai_ex_trig_enable(ai_context); | ||
3390 | case ME4000_AI_EX_TRIG_DISABLE: | ||
3391 | return me4000_ai_ex_trig_disable(ai_context); | ||
3392 | case ME4000_AI_EX_TRIG_SETUP: | ||
3393 | return me4000_ai_ex_trig_setup((struct me4000_ai_trigger *)arg, | ||
3394 | ai_context); | ||
3395 | case ME4000_AI_FSM_STATE: | ||
3396 | return me4000_ai_fsm_state((int *)arg, ai_context); | ||
3397 | case ME4000_GET_USER_INFO: | ||
3398 | return me4000_get_user_info((struct me4000_user_info *)arg, | ||
3399 | ai_context->board_info); | ||
3400 | case ME4000_AI_GET_COUNT_BUFFER: | ||
3401 | return me4000_ai_get_count_buffer((unsigned long *)arg, | ||
3402 | ai_context); | ||
3403 | default: | ||
3404 | printk(KERN_ERR | ||
3405 | "%s:Invalid service number %d\n", __func__ , service); | ||
3406 | return -ENOTTY; | ||
3407 | } | ||
3408 | return 0; | ||
3409 | } | ||
3410 | |||
3411 | static int me4000_ai_fasync(int fd, struct file *file_p, int mode) | ||
3412 | { | ||
3413 | struct me4000_ai_context *ai_context; | ||
3414 | |||
3415 | CALL_PDEBUG("me4000_ao_fasync_cont() is executed\n"); | ||
3416 | |||
3417 | ai_context = file_p->private_data; | ||
3418 | return fasync_helper(fd, file_p, mode, &ai_context->fasync_p); | ||
3419 | } | ||
3420 | |||
3421 | static int me4000_ai_config(struct me4000_ai_config *arg, | ||
3422 | struct me4000_ai_context *ai_context) | ||
3423 | { | ||
3424 | struct me4000_ai_config cmd; | ||
3425 | u32 *list = NULL; | ||
3426 | u32 mode; | ||
3427 | int i; | ||
3428 | int err; | ||
3429 | wait_queue_head_t queue; | ||
3430 | u64 scan; | ||
3431 | u32 tmp; | ||
3432 | |||
3433 | CALL_PDEBUG("me4000_ai_config() is executed\n"); | ||
3434 | |||
3435 | init_waitqueue_head(&queue); | ||
3436 | |||
3437 | /* Check if conversion is stopped */ | ||
3438 | if (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_FSM) { | ||
3439 | printk(KERN_ERR | ||
3440 | "ME4000:me4000_ai_config():Conversion is not stopped\n"); | ||
3441 | err = -EBUSY; | ||
3442 | goto AI_CONFIG_ERR; | ||
3443 | } | ||
3444 | |||
3445 | /* Copy data from user */ | ||
3446 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_config)); | ||
3447 | if (err) { | ||
3448 | printk(KERN_ERR | ||
3449 | "ME4000:me4000_ai_config():Can't copy from user space\n"); | ||
3450 | err = -EFAULT; | ||
3451 | goto AI_CONFIG_ERR; | ||
3452 | } | ||
3453 | |||
3454 | PDEBUG | ||
3455 | ("me4000_ai_config():chan = %ld, pre_chan = %ld, scan_low = %ld, scan_high = %ld, count = %ld\n", | ||
3456 | cmd.timer.chan, cmd.timer.pre_chan, cmd.timer.scan_low, | ||
3457 | cmd.timer.scan_high, cmd.channel_list.count); | ||
3458 | |||
3459 | /* Check whether sample and hold is available for this board */ | ||
3460 | if (cmd.sh) { | ||
3461 | if (!ai_context->board_info->board_p->ai.sh_count) { | ||
3462 | printk(KERN_ERR | ||
3463 | "ME4000:me4000_ai_config():Sample and Hold is not available for this board\n"); | ||
3464 | err = -ENODEV; | ||
3465 | goto AI_CONFIG_ERR; | ||
3466 | } | ||
3467 | } | ||
3468 | |||
3469 | /* Check the channel list size */ | ||
3470 | if (cmd.channel_list.count > ME4000_AI_CHANNEL_LIST_COUNT) { | ||
3471 | printk(KERN_ERR | ||
3472 | "me4000_ai_config():Channel list is to large\n"); | ||
3473 | err = -EINVAL; | ||
3474 | goto AI_CONFIG_ERR; | ||
3475 | } | ||
3476 | |||
3477 | /* Copy channel list from user */ | ||
3478 | list = kmalloc(sizeof(u32) * cmd.channel_list.count, GFP_KERNEL); | ||
3479 | if (!list) { | ||
3480 | printk(KERN_ERR | ||
3481 | "ME4000:me4000_ai_config():Can't get memory for channel list\n"); | ||
3482 | err = -ENOMEM; | ||
3483 | goto AI_CONFIG_ERR; | ||
3484 | } | ||
3485 | err = | ||
3486 | copy_from_user(list, cmd.channel_list.list, | ||
3487 | sizeof(u32) * cmd.channel_list.count); | ||
3488 | if (err) { | ||
3489 | printk(KERN_ERR | ||
3490 | "ME4000:me4000_ai_config():Can't copy from user space\n"); | ||
3491 | err = -EFAULT; | ||
3492 | goto AI_CONFIG_ERR; | ||
3493 | } | ||
3494 | |||
3495 | /* Check if last entry bit is set */ | ||
3496 | if (!(list[cmd.channel_list.count - 1] & ME4000_AI_LIST_LAST_ENTRY)) { | ||
3497 | printk(KERN_WARNING | ||
3498 | "me4000_ai_config():Last entry bit is not set\n"); | ||
3499 | list[cmd.channel_list.count - 1] |= ME4000_AI_LIST_LAST_ENTRY; | ||
3500 | } | ||
3501 | |||
3502 | /* Check whether mode is equal for all entries */ | ||
3503 | mode = list[0] & 0x20; | ||
3504 | for (i = 0; i < cmd.channel_list.count; i++) { | ||
3505 | if ((list[i] & 0x20) != mode) { | ||
3506 | printk(KERN_ERR | ||
3507 | "ME4000:me4000_ai_config():Mode is not equal for all entries\n"); | ||
3508 | err = -EINVAL; | ||
3509 | goto AI_CONFIG_ERR; | ||
3510 | } | ||
3511 | } | ||
3512 | |||
3513 | /* Check whether channels are available for this mode */ | ||
3514 | if (mode == ME4000_AI_LIST_INPUT_SINGLE_ENDED) { | ||
3515 | for (i = 0; i < cmd.channel_list.count; i++) { | ||
3516 | if ((list[i] & 0x1F) >= | ||
3517 | ai_context->board_info->board_p->ai.count) { | ||
3518 | printk(KERN_ERR | ||
3519 | "ME4000:me4000_ai_config():Channel is not available for single ended\n"); | ||
3520 | err = -EINVAL; | ||
3521 | goto AI_CONFIG_ERR; | ||
3522 | } | ||
3523 | } | ||
3524 | } else if (mode == ME4000_AI_LIST_INPUT_DIFFERENTIAL) { | ||
3525 | for (i = 0; i < cmd.channel_list.count; i++) { | ||
3526 | if ((list[i] & 0x1F) >= | ||
3527 | ai_context->board_info->board_p->ai.diff_count) { | ||
3528 | printk(KERN_ERR | ||
3529 | "ME4000:me4000_ai_config():Channel is not available for differential\n"); | ||
3530 | err = -EINVAL; | ||
3531 | goto AI_CONFIG_ERR; | ||
3532 | } | ||
3533 | } | ||
3534 | } | ||
3535 | |||
3536 | /* Check if bipolar is set for all entries when in differential mode */ | ||
3537 | if (mode == ME4000_AI_LIST_INPUT_DIFFERENTIAL) { | ||
3538 | for (i = 0; i < cmd.channel_list.count; i++) { | ||
3539 | if ((list[i] & 0xC0) != ME4000_AI_LIST_RANGE_BIPOLAR_10 | ||
3540 | && (list[i] & 0xC0) != | ||
3541 | ME4000_AI_LIST_RANGE_BIPOLAR_2_5) { | ||
3542 | printk(KERN_ERR | ||
3543 | "ME4000:me4000_ai_config():Bipolar is not selected in differential mode\n"); | ||
3544 | err = -EINVAL; | ||
3545 | goto AI_CONFIG_ERR; | ||
3546 | } | ||
3547 | } | ||
3548 | } | ||
3549 | |||
3550 | if (ai_context->mode != ME4000_AI_ACQ_MODE_EXT_SINGLE_VALUE) { | ||
3551 | /* Check for minimum channel divisor */ | ||
3552 | if (cmd.timer.chan < ME4000_AI_MIN_TICKS) { | ||
3553 | printk(KERN_ERR | ||
3554 | "ME4000:me4000_ai_config():Channel timer divisor is to low\n"); | ||
3555 | err = -EINVAL; | ||
3556 | goto AI_CONFIG_ERR; | ||
3557 | } | ||
3558 | |||
3559 | /* Check if minimum channel divisor is adjusted when sample and hold is activated */ | ||
3560 | if ((cmd.sh) && (cmd.timer.chan != ME4000_AI_MIN_TICKS)) { | ||
3561 | printk(KERN_ERR | ||
3562 | "ME4000:me4000_ai_config():Channel timer divisor must be at minimum when sample and hold is activated\n"); | ||
3563 | err = -EINVAL; | ||
3564 | goto AI_CONFIG_ERR; | ||
3565 | } | ||
3566 | |||
3567 | /* Check for minimum channel pre divisor */ | ||
3568 | if (cmd.timer.pre_chan < ME4000_AI_MIN_TICKS) { | ||
3569 | printk(KERN_ERR | ||
3570 | "ME4000:me4000_ai_config():Channel pre timer divisor is to low\n"); | ||
3571 | err = -EINVAL; | ||
3572 | goto AI_CONFIG_ERR; | ||
3573 | } | ||
3574 | |||
3575 | /* Write the channel timers */ | ||
3576 | me4000_outl(cmd.timer.chan - 1, ai_context->chan_timer_reg); | ||
3577 | me4000_outl(cmd.timer.pre_chan - 1, | ||
3578 | ai_context->chan_pre_timer_reg); | ||
3579 | |||
3580 | /* Save the timer values in the board context */ | ||
3581 | ai_context->chan_timer = cmd.timer.chan; | ||
3582 | ai_context->chan_pre_timer = cmd.timer.pre_chan; | ||
3583 | |||
3584 | if (ai_context->mode != ME4000_AI_ACQ_MODE_EXT_SINGLE_CHANLIST) { | ||
3585 | /* Check for scan timer divisor */ | ||
3586 | scan = | ||
3587 | (u64) cmd.timer.scan_low | ((u64) cmd.timer. | ||
3588 | scan_high << 32); | ||
3589 | if (scan != 0) { | ||
3590 | if (scan < | ||
3591 | cmd.channel_list.count * cmd.timer.chan + | ||
3592 | 1) { | ||
3593 | printk(KERN_ERR | ||
3594 | "ME4000:me4000_ai_config():Scan timer divisor is to low\n"); | ||
3595 | err = -EINVAL; | ||
3596 | goto AI_CONFIG_ERR; | ||
3597 | } | ||
3598 | } | ||
3599 | |||
3600 | /* Write the scan timers */ | ||
3601 | if (scan != 0) { | ||
3602 | scan--; | ||
3603 | tmp = (u32) (scan & 0xFFFFFFFF); | ||
3604 | me4000_outl(tmp, | ||
3605 | ai_context->scan_timer_low_reg); | ||
3606 | tmp = (u32) ((scan >> 32) & 0xFFFFFFFF); | ||
3607 | me4000_outl(tmp, | ||
3608 | ai_context->scan_timer_high_reg); | ||
3609 | |||
3610 | scan = | ||
3611 | scan - (cmd.timer.chan - 1) + | ||
3612 | (cmd.timer.pre_chan - 1); | ||
3613 | tmp = (u32) (scan & 0xFFFFFFFF); | ||
3614 | me4000_outl(tmp, | ||
3615 | ai_context->scan_pre_timer_low_reg); | ||
3616 | tmp = (u32) ((scan >> 32) & 0xFFFFFFFF); | ||
3617 | me4000_outl(tmp, | ||
3618 | ai_context-> | ||
3619 | scan_pre_timer_high_reg); | ||
3620 | } else { | ||
3621 | me4000_outl(0x0, | ||
3622 | ai_context->scan_timer_low_reg); | ||
3623 | me4000_outl(0x0, | ||
3624 | ai_context->scan_timer_high_reg); | ||
3625 | |||
3626 | me4000_outl(0x0, | ||
3627 | ai_context->scan_pre_timer_low_reg); | ||
3628 | me4000_outl(0x0, | ||
3629 | ai_context-> | ||
3630 | scan_pre_timer_high_reg); | ||
3631 | } | ||
3632 | |||
3633 | ai_context->scan_timer_low = cmd.timer.scan_low; | ||
3634 | ai_context->scan_timer_high = cmd.timer.scan_high; | ||
3635 | } | ||
3636 | } | ||
3637 | |||
3638 | /* Clear the channel list */ | ||
3639 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3640 | tmp &= ~ME4000_AI_CTRL_BIT_CHANNEL_FIFO; | ||
3641 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3642 | tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO; | ||
3643 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3644 | |||
3645 | /* Write the channel list */ | ||
3646 | for (i = 0; i < cmd.channel_list.count; i++) | ||
3647 | me4000_outl(list[i], ai_context->channel_list_reg); | ||
3648 | |||
3649 | /* Setup sample and hold */ | ||
3650 | if (cmd.sh) { | ||
3651 | tmp |= ME4000_AI_CTRL_BIT_SAMPLE_HOLD; | ||
3652 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3653 | } else { | ||
3654 | tmp &= ~ME4000_AI_CTRL_BIT_SAMPLE_HOLD; | ||
3655 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3656 | } | ||
3657 | |||
3658 | /* Save the channel list size in the board context */ | ||
3659 | ai_context->channel_list_count = cmd.channel_list.count; | ||
3660 | |||
3661 | kfree(list); | ||
3662 | |||
3663 | return 0; | ||
3664 | |||
3665 | AI_CONFIG_ERR: | ||
3666 | |||
3667 | /* Reset the timers */ | ||
3668 | ai_context->chan_timer = 66; | ||
3669 | ai_context->chan_pre_timer = 66; | ||
3670 | ai_context->scan_timer_low = 0; | ||
3671 | ai_context->scan_timer_high = 0; | ||
3672 | |||
3673 | me4000_outl(65, ai_context->chan_timer_reg); | ||
3674 | me4000_outl(65, ai_context->chan_pre_timer_reg); | ||
3675 | me4000_outl(0, ai_context->scan_timer_high_reg); | ||
3676 | me4000_outl(0, ai_context->scan_timer_low_reg); | ||
3677 | me4000_outl(0, ai_context->scan_pre_timer_high_reg); | ||
3678 | me4000_outl(0, ai_context->scan_pre_timer_low_reg); | ||
3679 | |||
3680 | ai_context->channel_list_count = 0; | ||
3681 | |||
3682 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3683 | tmp &= | ||
3684 | ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_SAMPLE_HOLD); | ||
3685 | |||
3686 | kfree(list); | ||
3687 | |||
3688 | return err; | ||
3689 | |||
3690 | } | ||
3691 | |||
3692 | static int ai_common_start(struct me4000_ai_context *ai_context) | ||
3693 | { | ||
3694 | u32 tmp; | ||
3695 | CALL_PDEBUG("ai_common_start() is executed\n"); | ||
3696 | |||
3697 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3698 | |||
3699 | /* Check if conversion is stopped */ | ||
3700 | if (tmp & ME4000_AI_STATUS_BIT_FSM) { | ||
3701 | printk(KERN_ERR | ||
3702 | "ME4000:ai_common_start():Conversion is not stopped\n"); | ||
3703 | return -EBUSY; | ||
3704 | } | ||
3705 | |||
3706 | /* Clear data fifo, disable all interrupts, clear sample counter reload */ | ||
3707 | tmp &= ~(ME4000_AI_CTRL_BIT_DATA_FIFO | ME4000_AI_CTRL_BIT_LE_IRQ | | ||
3708 | ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ | | ||
3709 | ME4000_AI_CTRL_BIT_SC_RELOAD); | ||
3710 | |||
3711 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3712 | |||
3713 | /* Clear circular buffer */ | ||
3714 | ai_context->circ_buf.head = 0; | ||
3715 | ai_context->circ_buf.tail = 0; | ||
3716 | |||
3717 | /* Enable data fifo */ | ||
3718 | tmp |= ME4000_AI_CTRL_BIT_DATA_FIFO; | ||
3719 | |||
3720 | /* Determine interrupt setup */ | ||
3721 | if (ai_context->sample_counter && !ai_context->sample_counter_reload) { | ||
3722 | /* Enable Half Full Interrupt and Sample Counter Interrupt */ | ||
3723 | tmp |= ME4000_AI_CTRL_BIT_SC_IRQ | ME4000_AI_CTRL_BIT_HF_IRQ; | ||
3724 | } else if (ai_context->sample_counter | ||
3725 | && ai_context->sample_counter_reload) { | ||
3726 | if (ai_context->sample_counter <= ME4000_AI_FIFO_COUNT / 2) { | ||
3727 | /* Enable only Sample Counter Interrupt */ | ||
3728 | tmp |= | ||
3729 | ME4000_AI_CTRL_BIT_SC_IRQ | | ||
3730 | ME4000_AI_CTRL_BIT_SC_RELOAD; | ||
3731 | } else { | ||
3732 | /* Enable Half Full Interrupt and Sample Counter Interrupt */ | ||
3733 | tmp |= | ||
3734 | ME4000_AI_CTRL_BIT_SC_IRQ | | ||
3735 | ME4000_AI_CTRL_BIT_HF_IRQ | | ||
3736 | ME4000_AI_CTRL_BIT_SC_RELOAD; | ||
3737 | } | ||
3738 | } else { | ||
3739 | /* Enable only Half Full Interrupt */ | ||
3740 | tmp |= ME4000_AI_CTRL_BIT_HF_IRQ; | ||
3741 | } | ||
3742 | |||
3743 | /* Clear the stop bits */ | ||
3744 | tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); | ||
3745 | |||
3746 | /* Write setup to hardware */ | ||
3747 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3748 | |||
3749 | /* Write sample counter */ | ||
3750 | me4000_outl(ai_context->sample_counter, ai_context->sample_counter_reg); | ||
3751 | |||
3752 | return 0; | ||
3753 | } | ||
3754 | |||
3755 | static int me4000_ai_start(struct me4000_ai_context *ai_context) | ||
3756 | { | ||
3757 | int err; | ||
3758 | CALL_PDEBUG("me4000_ai_start() is executed\n"); | ||
3759 | |||
3760 | /* Prepare Hardware */ | ||
3761 | err = ai_common_start(ai_context); | ||
3762 | if (err) | ||
3763 | return err; | ||
3764 | |||
3765 | /* Start conversion by dummy read */ | ||
3766 | me4000_inl(ai_context->start_reg); | ||
3767 | |||
3768 | return 0; | ||
3769 | } | ||
3770 | |||
3771 | static int me4000_ai_start_ex(unsigned long *arg, | ||
3772 | struct me4000_ai_context *ai_context) | ||
3773 | { | ||
3774 | int err; | ||
3775 | wait_queue_head_t queue; | ||
3776 | unsigned long ref; | ||
3777 | unsigned long timeout; | ||
3778 | |||
3779 | CALL_PDEBUG("me4000_ai_start_ex() is executed\n"); | ||
3780 | |||
3781 | if (get_user(timeout, arg)) { | ||
3782 | printk(KERN_ERR | ||
3783 | "me4000_ai_start_ex():Cannot copy data from user\n"); | ||
3784 | return -EFAULT; | ||
3785 | } | ||
3786 | |||
3787 | init_waitqueue_head(&queue); | ||
3788 | |||
3789 | /* Prepare Hardware */ | ||
3790 | err = ai_common_start(ai_context); | ||
3791 | if (err) | ||
3792 | return err; | ||
3793 | |||
3794 | if (timeout) { | ||
3795 | ref = jiffies; | ||
3796 | while (!(inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) { | ||
3797 | interruptible_sleep_on_timeout(&queue, 1); | ||
3798 | if (signal_pending(current)) { | ||
3799 | printk(KERN_ERR | ||
3800 | "ME4000:me4000_ai_start_ex():Wait on start of state machine interrupted\n"); | ||
3801 | return -EINTR; | ||
3802 | } | ||
3803 | /* 2.6 has different definitions for HZ in user and kernel space */ | ||
3804 | if ((jiffies - ref) > (timeout * HZ / USER_HZ)) { | ||
3805 | printk(KERN_ERR | ||
3806 | "ME4000:me4000_ai_start_ex():Timeout reached\n"); | ||
3807 | return -EIO; | ||
3808 | } | ||
3809 | } | ||
3810 | } else { | ||
3811 | while (!(inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) { | ||
3812 | interruptible_sleep_on_timeout(&queue, 1); | ||
3813 | if (signal_pending(current)) { | ||
3814 | printk(KERN_ERR | ||
3815 | "ME4000:me4000_ai_start_ex():Wait on start of state machine interrupted\n"); | ||
3816 | return -EINTR; | ||
3817 | } | ||
3818 | } | ||
3819 | } | ||
3820 | |||
3821 | return 0; | ||
3822 | } | ||
3823 | |||
3824 | static int me4000_ai_stop(struct me4000_ai_context *ai_context) | ||
3825 | { | ||
3826 | wait_queue_head_t queue; | ||
3827 | u32 tmp; | ||
3828 | unsigned long flags; | ||
3829 | |||
3830 | CALL_PDEBUG("me4000_ai_stop() is executed\n"); | ||
3831 | |||
3832 | init_waitqueue_head(&queue); | ||
3833 | |||
3834 | /* Disable irqs and clear data fifo */ | ||
3835 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
3836 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3837 | tmp &= | ||
3838 | ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ | | ||
3839 | ME4000_AI_CTRL_BIT_DATA_FIFO); | ||
3840 | /* Stop conversion of the state machine */ | ||
3841 | tmp |= ME4000_AI_CTRL_BIT_STOP; | ||
3842 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3843 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3844 | |||
3845 | /* Clear circular buffer */ | ||
3846 | ai_context->circ_buf.head = 0; | ||
3847 | ai_context->circ_buf.tail = 0; | ||
3848 | |||
3849 | while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) { | ||
3850 | interruptible_sleep_on_timeout(&queue, 1); | ||
3851 | if (signal_pending(current)) { | ||
3852 | printk(KERN_ERR | ||
3853 | "ME4000:me4000_ai_stop():Wait on state machine after stop interrupted\n"); | ||
3854 | return -EINTR; | ||
3855 | } | ||
3856 | } | ||
3857 | |||
3858 | return 0; | ||
3859 | } | ||
3860 | |||
3861 | static int me4000_ai_immediate_stop(struct me4000_ai_context *ai_context) | ||
3862 | { | ||
3863 | wait_queue_head_t queue; | ||
3864 | u32 tmp; | ||
3865 | unsigned long flags; | ||
3866 | |||
3867 | CALL_PDEBUG("me4000_ai_stop() is executed\n"); | ||
3868 | |||
3869 | init_waitqueue_head(&queue); | ||
3870 | |||
3871 | /* Disable irqs and clear data fifo */ | ||
3872 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
3873 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3874 | tmp &= | ||
3875 | ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ | | ||
3876 | ME4000_AI_CTRL_BIT_DATA_FIFO); | ||
3877 | /* Stop conversion of the state machine */ | ||
3878 | tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
3879 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3880 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3881 | |||
3882 | /* Clear circular buffer */ | ||
3883 | ai_context->circ_buf.head = 0; | ||
3884 | ai_context->circ_buf.tail = 0; | ||
3885 | |||
3886 | while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) { | ||
3887 | interruptible_sleep_on_timeout(&queue, 1); | ||
3888 | if (signal_pending(current)) { | ||
3889 | printk(KERN_ERR | ||
3890 | "ME4000:me4000_ai_stop():Wait on state machine after stop interrupted\n"); | ||
3891 | return -EINTR; | ||
3892 | } | ||
3893 | } | ||
3894 | |||
3895 | return 0; | ||
3896 | } | ||
3897 | |||
3898 | static int me4000_ai_ex_trig_enable(struct me4000_ai_context *ai_context) | ||
3899 | { | ||
3900 | u32 tmp; | ||
3901 | unsigned long flags; | ||
3902 | |||
3903 | CALL_PDEBUG("me4000_ai_ex_trig_enable() is executed\n"); | ||
3904 | |||
3905 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
3906 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3907 | tmp |= ME4000_AI_CTRL_BIT_EX_TRIG; | ||
3908 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3909 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3910 | |||
3911 | return 0; | ||
3912 | } | ||
3913 | |||
3914 | static int me4000_ai_ex_trig_disable(struct me4000_ai_context *ai_context) | ||
3915 | { | ||
3916 | u32 tmp; | ||
3917 | unsigned long flags; | ||
3918 | |||
3919 | CALL_PDEBUG("me4000_ai_ex_trig_disable() is executed\n"); | ||
3920 | |||
3921 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
3922 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3923 | tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG; | ||
3924 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3925 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3926 | |||
3927 | return 0; | ||
3928 | } | ||
3929 | |||
3930 | static int me4000_ai_ex_trig_setup(struct me4000_ai_trigger *arg, | ||
3931 | struct me4000_ai_context *ai_context) | ||
3932 | { | ||
3933 | struct me4000_ai_trigger cmd; | ||
3934 | int err; | ||
3935 | u32 tmp; | ||
3936 | unsigned long flags; | ||
3937 | |||
3938 | CALL_PDEBUG("me4000_ai_ex_trig_setup() is executed\n"); | ||
3939 | |||
3940 | /* Copy data from user */ | ||
3941 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_trigger)); | ||
3942 | if (err) { | ||
3943 | printk(KERN_ERR | ||
3944 | "ME4000:me4000_ai_ex_trig_setup():Can't copy from user space\n"); | ||
3945 | return -EFAULT; | ||
3946 | } | ||
3947 | |||
3948 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
3949 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
3950 | |||
3951 | if (cmd.mode == ME4000_AI_TRIGGER_EXT_DIGITAL) { | ||
3952 | tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG; | ||
3953 | } else if (cmd.mode == ME4000_AI_TRIGGER_EXT_ANALOG) { | ||
3954 | if (!ai_context->board_info->board_p->ai.ex_trig_analog) { | ||
3955 | printk(KERN_ERR | ||
3956 | "ME4000:me4000_ai_ex_trig_setup():No analog trigger available\n"); | ||
3957 | return -EINVAL; | ||
3958 | } | ||
3959 | tmp |= ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG; | ||
3960 | } else { | ||
3961 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3962 | printk(KERN_ERR | ||
3963 | "ME4000:me4000_ai_ex_trig_setup():Invalid trigger mode specified\n"); | ||
3964 | return -EINVAL; | ||
3965 | } | ||
3966 | |||
3967 | if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_RISING) { | ||
3968 | tmp &= | ||
3969 | ~(ME4000_AI_CTRL_BIT_EX_TRIG_BOTH | | ||
3970 | ME4000_AI_CTRL_BIT_EX_TRIG_FALLING); | ||
3971 | } else if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_FALLING) { | ||
3972 | tmp |= ME4000_AI_CTRL_BIT_EX_TRIG_FALLING; | ||
3973 | tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG_BOTH; | ||
3974 | } else if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_BOTH) { | ||
3975 | tmp |= | ||
3976 | ME4000_AI_CTRL_BIT_EX_TRIG_BOTH | | ||
3977 | ME4000_AI_CTRL_BIT_EX_TRIG_FALLING; | ||
3978 | } else { | ||
3979 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3980 | printk(KERN_ERR | ||
3981 | "ME4000:me4000_ai_ex_trig_setup():Invalid trigger edge specified\n"); | ||
3982 | return -EINVAL; | ||
3983 | } | ||
3984 | |||
3985 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
3986 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
3987 | return 0; | ||
3988 | } | ||
3989 | |||
3990 | static int me4000_ai_sc_setup(struct me4000_ai_sc *arg, | ||
3991 | struct me4000_ai_context *ai_context) | ||
3992 | { | ||
3993 | struct me4000_ai_sc cmd; | ||
3994 | int err; | ||
3995 | |||
3996 | CALL_PDEBUG("me4000_ai_sc_setup() is executed\n"); | ||
3997 | |||
3998 | /* Copy data from user */ | ||
3999 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_sc)); | ||
4000 | if (err) { | ||
4001 | printk(KERN_ERR | ||
4002 | "ME4000:me4000_ai_sc_setup():Can't copy from user space\n"); | ||
4003 | return -EFAULT; | ||
4004 | } | ||
4005 | |||
4006 | ai_context->sample_counter = cmd.value; | ||
4007 | ai_context->sample_counter_reload = cmd.reload; | ||
4008 | |||
4009 | return 0; | ||
4010 | } | ||
4011 | |||
4012 | static ssize_t me4000_ai_read(struct file *filep, char *buff, size_t cnt, | ||
4013 | loff_t *offp) | ||
4014 | { | ||
4015 | struct me4000_ai_context *ai_context = filep->private_data; | ||
4016 | s16 *buffer = (s16 *) buff; | ||
4017 | size_t count = cnt / 2; | ||
4018 | unsigned long flags; | ||
4019 | int tmp; | ||
4020 | int c = 0; | ||
4021 | int k = 0; | ||
4022 | int ret = 0; | ||
4023 | wait_queue_t wait; | ||
4024 | |||
4025 | CALL_PDEBUG("me4000_ai_read() is executed\n"); | ||
4026 | |||
4027 | init_waitqueue_entry(&wait, current); | ||
4028 | |||
4029 | /* Check count */ | ||
4030 | if (count <= 0) { | ||
4031 | PDEBUG("me4000_ai_read():Count is 0\n"); | ||
4032 | return 0; | ||
4033 | } | ||
4034 | |||
4035 | while (count > 0) { | ||
4036 | if (filep->f_flags & O_NONBLOCK) { | ||
4037 | c = me4000_values_to_end(ai_context->circ_buf, | ||
4038 | ME4000_AI_BUFFER_COUNT); | ||
4039 | if (!c) { | ||
4040 | PDEBUG | ||
4041 | ("me4000_ai_read():Returning from nonblocking read\n"); | ||
4042 | break; | ||
4043 | } | ||
4044 | } else { | ||
4045 | /* Check if conversion is still running */ | ||
4046 | if (! | ||
4047 | (me4000_inl(ai_context->status_reg) & | ||
4048 | ME4000_AI_STATUS_BIT_FSM)) { | ||
4049 | printk(KERN_ERR | ||
4050 | "ME4000:me4000_ai_read():Conversion interrupted\n"); | ||
4051 | return -EPIPE; | ||
4052 | } | ||
4053 | |||
4054 | wait_event_interruptible(ai_context->wait_queue, | ||
4055 | (me4000_values_to_end | ||
4056 | (ai_context->circ_buf, | ||
4057 | ME4000_AI_BUFFER_COUNT))); | ||
4058 | if (signal_pending(current)) { | ||
4059 | printk(KERN_ERR | ||
4060 | "ME4000:me4000_ai_read():Wait on values interrupted from signal\n"); | ||
4061 | return -EINTR; | ||
4062 | } | ||
4063 | } | ||
4064 | |||
4065 | /* Only read count values or as much as available */ | ||
4066 | c = me4000_values_to_end(ai_context->circ_buf, | ||
4067 | ME4000_AI_BUFFER_COUNT); | ||
4068 | PDEBUG("me4000_ai_read():%d values to end\n", c); | ||
4069 | if (count < c) | ||
4070 | c = count; | ||
4071 | |||
4072 | PDEBUG("me4000_ai_read():Copy %d values to user space\n", c); | ||
4073 | k = 2 * c; | ||
4074 | k -= copy_to_user(buffer, | ||
4075 | ai_context->circ_buf.buf + | ||
4076 | ai_context->circ_buf.tail, k); | ||
4077 | c = k / 2; | ||
4078 | if (!c) { | ||
4079 | printk(KERN_ERR | ||
4080 | "ME4000:me4000_ai_read():Cannot copy new values to user\n"); | ||
4081 | return -EFAULT; | ||
4082 | } | ||
4083 | |||
4084 | ai_context->circ_buf.tail = | ||
4085 | (ai_context->circ_buf.tail + c) & (ME4000_AI_BUFFER_COUNT - | ||
4086 | 1); | ||
4087 | buffer += c; | ||
4088 | count -= c; | ||
4089 | ret += c; | ||
4090 | |||
4091 | spin_lock_irqsave(&ai_context->int_lock, flags); | ||
4092 | if (me4000_buf_space | ||
4093 | (ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) { | ||
4094 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
4095 | |||
4096 | /* Determine interrupt setup */ | ||
4097 | if (ai_context->sample_counter | ||
4098 | && !ai_context->sample_counter_reload) { | ||
4099 | /* Enable Half Full Interrupt and Sample Counter Interrupt */ | ||
4100 | tmp |= | ||
4101 | ME4000_AI_CTRL_BIT_SC_IRQ | | ||
4102 | ME4000_AI_CTRL_BIT_HF_IRQ; | ||
4103 | } else if (ai_context->sample_counter | ||
4104 | && ai_context->sample_counter_reload) { | ||
4105 | if (ai_context->sample_counter < | ||
4106 | ME4000_AI_FIFO_COUNT / 2) { | ||
4107 | /* Enable only Sample Counter Interrupt */ | ||
4108 | tmp |= ME4000_AI_CTRL_BIT_SC_IRQ; | ||
4109 | } else { | ||
4110 | /* Enable Half Full Interrupt and Sample Counter Interrupt */ | ||
4111 | tmp |= | ||
4112 | ME4000_AI_CTRL_BIT_SC_IRQ | | ||
4113 | ME4000_AI_CTRL_BIT_HF_IRQ; | ||
4114 | } | ||
4115 | } else { | ||
4116 | /* Enable only Half Full Interrupt */ | ||
4117 | tmp |= ME4000_AI_CTRL_BIT_HF_IRQ; | ||
4118 | } | ||
4119 | |||
4120 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
4121 | } | ||
4122 | spin_unlock_irqrestore(&ai_context->int_lock, flags); | ||
4123 | } | ||
4124 | |||
4125 | /* Check if conversion is still running */ | ||
4126 | if (!(me4000_inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) { | ||
4127 | printk(KERN_ERR | ||
4128 | "ME4000:me4000_ai_read():Conversion not running after complete read\n"); | ||
4129 | return -EPIPE; | ||
4130 | } | ||
4131 | |||
4132 | if (filep->f_flags & O_NONBLOCK) | ||
4133 | return (k == 0) ? -EAGAIN : 2 * ret; | ||
4134 | |||
4135 | CALL_PDEBUG("me4000_ai_read() is leaved\n"); | ||
4136 | return ret * 2; | ||
4137 | } | ||
4138 | |||
4139 | static unsigned int me4000_ai_poll(struct file *file_p, poll_table *wait) | ||
4140 | { | ||
4141 | struct me4000_ai_context *ai_context; | ||
4142 | unsigned long mask = 0; | ||
4143 | |||
4144 | CALL_PDEBUG("me4000_ai_poll() is executed\n"); | ||
4145 | |||
4146 | ai_context = file_p->private_data; | ||
4147 | |||
4148 | /* Register wait queue */ | ||
4149 | poll_wait(file_p, &ai_context->wait_queue, wait); | ||
4150 | |||
4151 | /* Get available values */ | ||
4152 | if (me4000_values_to_end(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) | ||
4153 | mask |= POLLIN | POLLRDNORM; | ||
4154 | |||
4155 | PDEBUG("me4000_ai_poll():Return mask %lX\n", mask); | ||
4156 | |||
4157 | return mask; | ||
4158 | } | ||
4159 | |||
4160 | static int me4000_ai_offset_enable(struct me4000_ai_context *ai_context) | ||
4161 | { | ||
4162 | unsigned long tmp; | ||
4163 | |||
4164 | CALL_PDEBUG("me4000_ai_offset_enable() is executed\n"); | ||
4165 | |||
4166 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
4167 | tmp |= ME4000_AI_CTRL_BIT_OFFSET; | ||
4168 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
4169 | |||
4170 | return 0; | ||
4171 | } | ||
4172 | |||
4173 | static int me4000_ai_offset_disable(struct me4000_ai_context *ai_context) | ||
4174 | { | ||
4175 | unsigned long tmp; | ||
4176 | |||
4177 | CALL_PDEBUG("me4000_ai_offset_disable() is executed\n"); | ||
4178 | |||
4179 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
4180 | tmp &= ~ME4000_AI_CTRL_BIT_OFFSET; | ||
4181 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
4182 | |||
4183 | return 0; | ||
4184 | } | ||
4185 | |||
4186 | static int me4000_ai_fullscale_enable(struct me4000_ai_context *ai_context) | ||
4187 | { | ||
4188 | unsigned long tmp; | ||
4189 | |||
4190 | CALL_PDEBUG("me4000_ai_fullscale_enable() is executed\n"); | ||
4191 | |||
4192 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
4193 | tmp |= ME4000_AI_CTRL_BIT_FULLSCALE; | ||
4194 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
4195 | |||
4196 | return 0; | ||
4197 | } | ||
4198 | |||
4199 | static int me4000_ai_fullscale_disable(struct me4000_ai_context *ai_context) | ||
4200 | { | ||
4201 | unsigned long tmp; | ||
4202 | |||
4203 | CALL_PDEBUG("me4000_ai_fullscale_disable() is executed\n"); | ||
4204 | |||
4205 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
4206 | tmp &= ~ME4000_AI_CTRL_BIT_FULLSCALE; | ||
4207 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
4208 | |||
4209 | return 0; | ||
4210 | } | ||
4211 | |||
4212 | static int me4000_ai_fsm_state(int *arg, struct me4000_ai_context *ai_context) | ||
4213 | { | ||
4214 | unsigned long tmp; | ||
4215 | |||
4216 | CALL_PDEBUG("me4000_ai_fsm_state() is executed\n"); | ||
4217 | |||
4218 | tmp = | ||
4219 | (me4000_inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) ? 1 | ||
4220 | : 0; | ||
4221 | |||
4222 | if (put_user(tmp, arg)) { | ||
4223 | printk(KERN_ERR "me4000_ai_fsm_state():Cannot copy to user\n"); | ||
4224 | return -EFAULT; | ||
4225 | } | ||
4226 | |||
4227 | return 0; | ||
4228 | } | ||
4229 | |||
4230 | static int me4000_ai_get_count_buffer(unsigned long *arg, | ||
4231 | struct me4000_ai_context *ai_context) | ||
4232 | { | ||
4233 | unsigned long c; | ||
4234 | int err; | ||
4235 | |||
4236 | c = me4000_buf_count(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT); | ||
4237 | |||
4238 | err = copy_to_user(arg, &c, sizeof(unsigned long)); | ||
4239 | if (err) { | ||
4240 | printk(KERN_ERR | ||
4241 | "%s:Can't copy to user space\n", __func__); | ||
4242 | return -EFAULT; | ||
4243 | } | ||
4244 | |||
4245 | return 0; | ||
4246 | } | ||
4247 | |||
4248 | /*---------------------------------- EEPROM stuff ---------------------------*/ | ||
4249 | |||
4250 | static int eeprom_write_cmd(struct me4000_ai_context *ai_context, unsigned long cmd, | ||
4251 | int length) | ||
4252 | { | ||
4253 | int i; | ||
4254 | unsigned long value; | ||
4255 | |||
4256 | CALL_PDEBUG("eeprom_write_cmd() is executed\n"); | ||
4257 | |||
4258 | PDEBUG("eeprom_write_cmd():Write command 0x%08lX with length = %d\n", | ||
4259 | cmd, length); | ||
4260 | |||
4261 | /* Get the ICR register and clear the related bits */ | ||
4262 | value = me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR); | ||
4263 | value &= ~(PLX_ICR_MASK_EEPROM); | ||
4264 | me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR); | ||
4265 | |||
4266 | /* Raise the chip select */ | ||
4267 | value |= PLX_ICR_BIT_EEPROM_CHIP_SELECT; | ||
4268 | me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR); | ||
4269 | udelay(EEPROM_DELAY); | ||
4270 | |||
4271 | for (i = 0; i < length; i++) { | ||
4272 | if (cmd & ((0x1 << (length - 1)) >> i)) | ||
4273 | value |= PLX_ICR_BIT_EEPROM_WRITE; | ||
4274 | else | ||
4275 | value &= ~PLX_ICR_BIT_EEPROM_WRITE; | ||
4276 | |||
4277 | /* Write to EEPROM */ | ||
4278 | me4000_outl(value, | ||
4279 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4280 | udelay(EEPROM_DELAY); | ||
4281 | |||
4282 | /* Raising edge of the clock */ | ||
4283 | value |= PLX_ICR_BIT_EEPROM_CLOCK_SET; | ||
4284 | me4000_outl(value, | ||
4285 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4286 | udelay(EEPROM_DELAY); | ||
4287 | |||
4288 | /* Falling edge of the clock */ | ||
4289 | value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET; | ||
4290 | me4000_outl(value, | ||
4291 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4292 | udelay(EEPROM_DELAY); | ||
4293 | } | ||
4294 | |||
4295 | /* Clear the chip select */ | ||
4296 | value &= ~PLX_ICR_BIT_EEPROM_CHIP_SELECT; | ||
4297 | me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR); | ||
4298 | udelay(EEPROM_DELAY); | ||
4299 | |||
4300 | /* Wait until hardware is ready for sure */ | ||
4301 | mdelay(10); | ||
4302 | |||
4303 | return 0; | ||
4304 | } | ||
4305 | |||
4306 | static unsigned short eeprom_read_cmd(struct me4000_ai_context *ai_context, | ||
4307 | unsigned long cmd, int length) | ||
4308 | { | ||
4309 | int i; | ||
4310 | unsigned long value; | ||
4311 | unsigned short id = 0; | ||
4312 | |||
4313 | CALL_PDEBUG("eeprom_read_cmd() is executed\n"); | ||
4314 | |||
4315 | PDEBUG("eeprom_read_cmd():Read command 0x%08lX with length = %d\n", cmd, | ||
4316 | length); | ||
4317 | |||
4318 | /* Get the ICR register and clear the related bits */ | ||
4319 | value = me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR); | ||
4320 | value &= ~(PLX_ICR_MASK_EEPROM); | ||
4321 | |||
4322 | me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR); | ||
4323 | |||
4324 | /* Raise the chip select */ | ||
4325 | value |= PLX_ICR_BIT_EEPROM_CHIP_SELECT; | ||
4326 | me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR); | ||
4327 | udelay(EEPROM_DELAY); | ||
4328 | |||
4329 | /* Write the read command to the eeprom */ | ||
4330 | for (i = 0; i < length; i++) { | ||
4331 | if (cmd & ((0x1 << (length - 1)) >> i)) | ||
4332 | value |= PLX_ICR_BIT_EEPROM_WRITE; | ||
4333 | else | ||
4334 | value &= ~PLX_ICR_BIT_EEPROM_WRITE; | ||
4335 | |||
4336 | me4000_outl(value, | ||
4337 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4338 | udelay(EEPROM_DELAY); | ||
4339 | |||
4340 | /* Raising edge of the clock */ | ||
4341 | value |= PLX_ICR_BIT_EEPROM_CLOCK_SET; | ||
4342 | me4000_outl(value, | ||
4343 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4344 | udelay(EEPROM_DELAY); | ||
4345 | |||
4346 | /* Falling edge of the clock */ | ||
4347 | value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET; | ||
4348 | me4000_outl(value, | ||
4349 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4350 | udelay(EEPROM_DELAY); | ||
4351 | } | ||
4352 | |||
4353 | /* Read the value from the eeprom */ | ||
4354 | for (i = 0; i < 16; i++) { | ||
4355 | /* Raising edge of the clock */ | ||
4356 | value |= PLX_ICR_BIT_EEPROM_CLOCK_SET; | ||
4357 | me4000_outl(value, | ||
4358 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4359 | udelay(EEPROM_DELAY); | ||
4360 | |||
4361 | if (me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR) & | ||
4362 | PLX_ICR_BIT_EEPROM_READ) { | ||
4363 | id |= (0x8000 >> i); | ||
4364 | PDEBUG("eeprom_read_cmd():OR with 0x%04X\n", | ||
4365 | (0x8000 >> i)); | ||
4366 | } else { | ||
4367 | PDEBUG("eeprom_read_cmd():Dont't OR\n"); | ||
4368 | } | ||
4369 | |||
4370 | /* Falling edge of the clock */ | ||
4371 | value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET; | ||
4372 | me4000_outl(value, | ||
4373 | ai_context->board_info->plx_regbase + PLX_ICR); | ||
4374 | udelay(EEPROM_DELAY); | ||
4375 | } | ||
4376 | |||
4377 | /* Clear the chip select */ | ||
4378 | value &= ~PLX_ICR_BIT_EEPROM_CHIP_SELECT; | ||
4379 | me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR); | ||
4380 | udelay(EEPROM_DELAY); | ||
4381 | |||
4382 | return id; | ||
4383 | } | ||
4384 | |||
4385 | static int me4000_eeprom_write(struct me4000_eeprom *arg, | ||
4386 | struct me4000_ai_context *ai_context) | ||
4387 | { | ||
4388 | int err; | ||
4389 | struct me4000_eeprom setup; | ||
4390 | unsigned long cmd; | ||
4391 | unsigned long date_high; | ||
4392 | unsigned long date_low; | ||
4393 | |||
4394 | CALL_PDEBUG("me4000_eeprom_write() is executed\n"); | ||
4395 | |||
4396 | err = copy_from_user(&setup, arg, sizeof(setup)); | ||
4397 | if (err) { | ||
4398 | printk(KERN_ERR | ||
4399 | "ME4000:me4000_eeprom_write():Cannot copy from user\n"); | ||
4400 | return err; | ||
4401 | } | ||
4402 | |||
4403 | /* Enable writing */ | ||
4404 | eeprom_write_cmd(ai_context, ME4000_EEPROM_CMD_WRITE_ENABLE, | ||
4405 | ME4000_EEPROM_CMD_LENGTH_WRITE_ENABLE); | ||
4406 | |||
4407 | /* Command for date */ | ||
4408 | date_high = (setup.date & 0xFFFF0000) >> 16; | ||
4409 | date_low = (setup.date & 0x0000FFFF); | ||
4410 | |||
4411 | cmd = | ||
4412 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_DATE_HIGH << | ||
4413 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4414 | (unsigned | ||
4415 | long) | ||
4416 | date_high); | ||
4417 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4418 | if (err) | ||
4419 | return err; | ||
4420 | |||
4421 | cmd = | ||
4422 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_DATE_LOW << | ||
4423 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4424 | (unsigned | ||
4425 | long) | ||
4426 | date_low); | ||
4427 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4428 | if (err) | ||
4429 | return err; | ||
4430 | |||
4431 | /* Command for unipolar 10V offset */ | ||
4432 | cmd = | ||
4433 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_UNI_OFFSET << | ||
4434 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4435 | (unsigned | ||
4436 | long) | ||
4437 | setup. | ||
4438 | uni_10_offset); | ||
4439 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4440 | if (err) | ||
4441 | return err; | ||
4442 | |||
4443 | /* Command for unipolar 10V fullscale */ | ||
4444 | cmd = | ||
4445 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_UNI_FULLSCALE << | ||
4446 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4447 | (unsigned | ||
4448 | long) | ||
4449 | setup. | ||
4450 | uni_10_fullscale); | ||
4451 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4452 | if (err) | ||
4453 | return err; | ||
4454 | |||
4455 | /* Command for unipolar 2,5V offset */ | ||
4456 | cmd = | ||
4457 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_UNI_OFFSET << | ||
4458 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4459 | (unsigned | ||
4460 | long) | ||
4461 | setup. | ||
4462 | uni_2_5_offset); | ||
4463 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4464 | if (err) | ||
4465 | return err; | ||
4466 | |||
4467 | /* Command for unipolar 2,5V fullscale */ | ||
4468 | cmd = | ||
4469 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_UNI_FULLSCALE << | ||
4470 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4471 | (unsigned | ||
4472 | long) | ||
4473 | setup. | ||
4474 | uni_2_5_fullscale); | ||
4475 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4476 | if (err) | ||
4477 | return err; | ||
4478 | |||
4479 | /* Command for bipolar 10V offset */ | ||
4480 | cmd = | ||
4481 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_BI_OFFSET << | ||
4482 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4483 | (unsigned | ||
4484 | long) | ||
4485 | setup. | ||
4486 | bi_10_offset); | ||
4487 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4488 | if (err) | ||
4489 | return err; | ||
4490 | |||
4491 | /* Command for bipolar 10V fullscale */ | ||
4492 | cmd = | ||
4493 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_BI_FULLSCALE << | ||
4494 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4495 | (unsigned | ||
4496 | long) | ||
4497 | setup. | ||
4498 | bi_10_fullscale); | ||
4499 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4500 | if (err) | ||
4501 | return err; | ||
4502 | |||
4503 | /* Command for bipolar 2,5V offset */ | ||
4504 | cmd = | ||
4505 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_BI_OFFSET << | ||
4506 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4507 | (unsigned | ||
4508 | long) | ||
4509 | setup. | ||
4510 | bi_2_5_offset); | ||
4511 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4512 | if (err) | ||
4513 | return err; | ||
4514 | |||
4515 | /* Command for bipolar 2,5V fullscale */ | ||
4516 | cmd = | ||
4517 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_BI_FULLSCALE << | ||
4518 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4519 | (unsigned | ||
4520 | long) | ||
4521 | setup. | ||
4522 | bi_2_5_fullscale); | ||
4523 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4524 | if (err) | ||
4525 | return err; | ||
4526 | |||
4527 | /* Command for differential 10V offset */ | ||
4528 | cmd = | ||
4529 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_DIFF_OFFSET << | ||
4530 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4531 | (unsigned | ||
4532 | long) | ||
4533 | setup. | ||
4534 | diff_10_offset); | ||
4535 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4536 | if (err) | ||
4537 | return err; | ||
4538 | |||
4539 | /* Command for differential 10V fullscale */ | ||
4540 | cmd = | ||
4541 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_DIFF_FULLSCALE | ||
4542 | << ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4543 | (unsigned | ||
4544 | long) | ||
4545 | setup. | ||
4546 | diff_10_fullscale); | ||
4547 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4548 | if (err) | ||
4549 | return err; | ||
4550 | |||
4551 | /* Command for differential 2,5V offset */ | ||
4552 | cmd = | ||
4553 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_DIFF_OFFSET << | ||
4554 | ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4555 | (unsigned | ||
4556 | long) | ||
4557 | setup. | ||
4558 | diff_2_5_offset); | ||
4559 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4560 | if (err) | ||
4561 | return err; | ||
4562 | |||
4563 | /* Command for differential 2,5V fullscale */ | ||
4564 | cmd = | ||
4565 | ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_DIFF_FULLSCALE | ||
4566 | << ME4000_EEPROM_DATA_LENGTH) | (0xFFFF & | ||
4567 | (unsigned | ||
4568 | long) | ||
4569 | setup. | ||
4570 | diff_2_5_fullscale); | ||
4571 | err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE); | ||
4572 | if (err) | ||
4573 | return err; | ||
4574 | |||
4575 | /* Disable writing */ | ||
4576 | eeprom_write_cmd(ai_context, ME4000_EEPROM_CMD_WRITE_DISABLE, | ||
4577 | ME4000_EEPROM_CMD_LENGTH_WRITE_DISABLE); | ||
4578 | |||
4579 | return 0; | ||
4580 | } | ||
4581 | |||
4582 | static int me4000_eeprom_read(struct me4000_eeprom *arg, | ||
4583 | struct me4000_ai_context *ai_context) | ||
4584 | { | ||
4585 | int err; | ||
4586 | unsigned long cmd; | ||
4587 | struct me4000_eeprom setup; | ||
4588 | |||
4589 | CALL_PDEBUG("me4000_eeprom_read() is executed\n"); | ||
4590 | |||
4591 | /* Command for date */ | ||
4592 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_DATE_HIGH; | ||
4593 | setup.date = | ||
4594 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4595 | setup.date <<= 16; | ||
4596 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_DATE_LOW; | ||
4597 | setup.date |= | ||
4598 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4599 | |||
4600 | /* Command for unipolar 10V offset */ | ||
4601 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_UNI_OFFSET; | ||
4602 | setup.uni_10_offset = | ||
4603 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4604 | |||
4605 | /* Command for unipolar 10V fullscale */ | ||
4606 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_UNI_FULLSCALE; | ||
4607 | setup.uni_10_fullscale = | ||
4608 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4609 | |||
4610 | /* Command for unipolar 2,5V offset */ | ||
4611 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_UNI_OFFSET; | ||
4612 | setup.uni_2_5_offset = | ||
4613 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4614 | |||
4615 | /* Command for unipolar 2,5V fullscale */ | ||
4616 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_UNI_FULLSCALE; | ||
4617 | setup.uni_2_5_fullscale = | ||
4618 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4619 | |||
4620 | /* Command for bipolar 10V offset */ | ||
4621 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_BI_OFFSET; | ||
4622 | setup.bi_10_offset = | ||
4623 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4624 | |||
4625 | /* Command for bipolar 10V fullscale */ | ||
4626 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_BI_FULLSCALE; | ||
4627 | setup.bi_10_fullscale = | ||
4628 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4629 | |||
4630 | /* Command for bipolar 2,5V offset */ | ||
4631 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_BI_OFFSET; | ||
4632 | setup.bi_2_5_offset = | ||
4633 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4634 | |||
4635 | /* Command for bipolar 2,5V fullscale */ | ||
4636 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_BI_FULLSCALE; | ||
4637 | setup.bi_2_5_fullscale = | ||
4638 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4639 | |||
4640 | /* Command for differntial 10V offset */ | ||
4641 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_DIFF_OFFSET; | ||
4642 | setup.diff_10_offset = | ||
4643 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4644 | |||
4645 | /* Command for differential 10V fullscale */ | ||
4646 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_DIFF_FULLSCALE; | ||
4647 | setup.diff_10_fullscale = | ||
4648 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4649 | |||
4650 | /* Command for differntial 2,5V offset */ | ||
4651 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_DIFF_OFFSET; | ||
4652 | setup.diff_2_5_offset = | ||
4653 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4654 | |||
4655 | /* Command for differential 2,5V fullscale */ | ||
4656 | cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_DIFF_FULLSCALE; | ||
4657 | setup.diff_2_5_fullscale = | ||
4658 | eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ); | ||
4659 | |||
4660 | err = copy_to_user(arg, &setup, sizeof(setup)); | ||
4661 | if (err) { | ||
4662 | printk(KERN_ERR | ||
4663 | "ME4000:me4000_eeprom_read():Cannot copy to user\n"); | ||
4664 | return err; | ||
4665 | } | ||
4666 | |||
4667 | return 0; | ||
4668 | } | ||
4669 | |||
4670 | /*------------------------------------ DIO stuff ----------------------------------------------*/ | ||
4671 | |||
4672 | static int me4000_dio_ioctl(struct inode *inode_p, struct file *file_p, | ||
4673 | unsigned int service, unsigned long arg) | ||
4674 | { | ||
4675 | struct me4000_dio_context *dio_context; | ||
4676 | |||
4677 | CALL_PDEBUG("me4000_dio_ioctl() is executed\n"); | ||
4678 | |||
4679 | dio_context = file_p->private_data; | ||
4680 | |||
4681 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
4682 | printk(KERN_ERR "me4000_dio_ioctl():Wrong magic number\n"); | ||
4683 | return -ENOTTY; | ||
4684 | } | ||
4685 | if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) { | ||
4686 | printk(KERN_ERR "me4000_dio_ioctl():Service number to high\n"); | ||
4687 | return -ENOTTY; | ||
4688 | } | ||
4689 | |||
4690 | switch (service) { | ||
4691 | case ME4000_DIO_CONFIG: | ||
4692 | return me4000_dio_config((struct me4000_dio_config *)arg, | ||
4693 | dio_context); | ||
4694 | case ME4000_DIO_SET_BYTE: | ||
4695 | return me4000_dio_set_byte((struct me4000_dio_byte *)arg, | ||
4696 | dio_context); | ||
4697 | case ME4000_DIO_GET_BYTE: | ||
4698 | return me4000_dio_get_byte((struct me4000_dio_byte *)arg, | ||
4699 | dio_context); | ||
4700 | case ME4000_DIO_RESET: | ||
4701 | return me4000_dio_reset(dio_context); | ||
4702 | default: | ||
4703 | printk(KERN_ERR | ||
4704 | "ME4000:me4000_dio_ioctl():Invalid service number %d\n", | ||
4705 | service); | ||
4706 | return -ENOTTY; | ||
4707 | } | ||
4708 | return 0; | ||
4709 | } | ||
4710 | |||
4711 | static int me4000_dio_config(struct me4000_dio_config *arg, | ||
4712 | struct me4000_dio_context *dio_context) | ||
4713 | { | ||
4714 | struct me4000_dio_config cmd; | ||
4715 | u32 tmp; | ||
4716 | int err; | ||
4717 | |||
4718 | CALL_PDEBUG("me4000_dio_config() is executed\n"); | ||
4719 | |||
4720 | /* Copy data from user */ | ||
4721 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_config)); | ||
4722 | if (err) { | ||
4723 | printk(KERN_ERR | ||
4724 | "ME4000:me4000_dio_config():Can't copy from user space\n"); | ||
4725 | return -EFAULT; | ||
4726 | } | ||
4727 | |||
4728 | /* Check port parameter */ | ||
4729 | if (cmd.port >= dio_context->dio_count) { | ||
4730 | printk(KERN_ERR | ||
4731 | "ME4000:me4000_dio_config():Port %d is not available\n", | ||
4732 | cmd.port); | ||
4733 | return -EINVAL; | ||
4734 | } | ||
4735 | |||
4736 | PDEBUG("me4000_dio_config(): port %d, mode %d, function %d\n", cmd.port, | ||
4737 | cmd.mode, cmd.function); | ||
4738 | |||
4739 | if (cmd.port == ME4000_DIO_PORT_A) { | ||
4740 | if (cmd.mode == ME4000_DIO_PORT_INPUT) { | ||
4741 | /* Check if opto isolated version */ | ||
4742 | if (!(me4000_inl(dio_context->dir_reg) & 0x1)) { | ||
4743 | printk(KERN_ERR | ||
4744 | "ME4000:me4000_dio_config():Cannot set to input on opto isolated versions\n"); | ||
4745 | return -EIO; | ||
4746 | } | ||
4747 | |||
4748 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4749 | tmp &= | ||
4750 | ~(ME4000_DIO_CTRL_BIT_MODE_0 | | ||
4751 | ME4000_DIO_CTRL_BIT_MODE_1); | ||
4752 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4753 | } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) { | ||
4754 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4755 | tmp &= | ||
4756 | ~(ME4000_DIO_CTRL_BIT_MODE_0 | | ||
4757 | ME4000_DIO_CTRL_BIT_MODE_1); | ||
4758 | tmp |= ME4000_DIO_CTRL_BIT_MODE_0; | ||
4759 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4760 | } else if (cmd.mode == ME4000_DIO_FIFO_LOW) { | ||
4761 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4762 | tmp &= | ||
4763 | ~(ME4000_DIO_CTRL_BIT_MODE_0 | | ||
4764 | ME4000_DIO_CTRL_BIT_MODE_1 | | ||
4765 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_0); | ||
4766 | tmp |= | ||
4767 | ME4000_DIO_CTRL_BIT_MODE_0 | | ||
4768 | ME4000_DIO_CTRL_BIT_MODE_1; | ||
4769 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4770 | } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) { | ||
4771 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4772 | tmp |= | ||
4773 | ME4000_DIO_CTRL_BIT_MODE_0 | | ||
4774 | ME4000_DIO_CTRL_BIT_MODE_1 | | ||
4775 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_0; | ||
4776 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4777 | } else { | ||
4778 | printk(KERN_ERR | ||
4779 | "ME4000:me4000_dio_config():Mode %d is not available\n", | ||
4780 | cmd.mode); | ||
4781 | return -EINVAL; | ||
4782 | } | ||
4783 | } else if (cmd.port == ME4000_DIO_PORT_B) { | ||
4784 | if (cmd.mode == ME4000_DIO_PORT_INPUT) { | ||
4785 | /* Only do anything when TTL version is installed */ | ||
4786 | if ((me4000_inl(dio_context->dir_reg) & 0x1)) { | ||
4787 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4788 | tmp &= | ||
4789 | ~(ME4000_DIO_CTRL_BIT_MODE_2 | | ||
4790 | ME4000_DIO_CTRL_BIT_MODE_3); | ||
4791 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4792 | } | ||
4793 | } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) { | ||
4794 | /* Check if opto isolated version */ | ||
4795 | if (!(me4000_inl(dio_context->dir_reg) & 0x1)) { | ||
4796 | printk(KERN_ERR | ||
4797 | "ME4000:me4000_dio_config():Cannot set to output on opto isolated versions\n"); | ||
4798 | return -EIO; | ||
4799 | } | ||
4800 | |||
4801 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4802 | tmp &= | ||
4803 | ~(ME4000_DIO_CTRL_BIT_MODE_2 | | ||
4804 | ME4000_DIO_CTRL_BIT_MODE_3); | ||
4805 | tmp |= ME4000_DIO_CTRL_BIT_MODE_2; | ||
4806 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4807 | } else if (cmd.mode == ME4000_DIO_FIFO_LOW) { | ||
4808 | /* Check if opto isolated version */ | ||
4809 | if (!(me4000_inl(dio_context->dir_reg) & 0x1)) { | ||
4810 | printk(KERN_ERR | ||
4811 | "ME4000:me4000_dio_config():Cannot set to FIFO low output on opto isolated versions\n"); | ||
4812 | return -EIO; | ||
4813 | } | ||
4814 | |||
4815 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4816 | tmp &= | ||
4817 | ~(ME4000_DIO_CTRL_BIT_MODE_2 | | ||
4818 | ME4000_DIO_CTRL_BIT_MODE_3 | | ||
4819 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_1); | ||
4820 | tmp |= | ||
4821 | ME4000_DIO_CTRL_BIT_MODE_2 | | ||
4822 | ME4000_DIO_CTRL_BIT_MODE_3; | ||
4823 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4824 | } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) { | ||
4825 | /* Check if opto isolated version */ | ||
4826 | if (!(me4000_inl(dio_context->dir_reg) & 0x1)) { | ||
4827 | printk(KERN_ERR | ||
4828 | "ME4000:me4000_dio_config():Cannot set to FIFO high output on opto isolated versions\n"); | ||
4829 | return -EIO; | ||
4830 | } | ||
4831 | |||
4832 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4833 | tmp |= | ||
4834 | ME4000_DIO_CTRL_BIT_MODE_2 | | ||
4835 | ME4000_DIO_CTRL_BIT_MODE_3 | | ||
4836 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_1; | ||
4837 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4838 | } else { | ||
4839 | printk(KERN_ERR | ||
4840 | "ME4000:me4000_dio_config():Mode %d is not available\n", | ||
4841 | cmd.mode); | ||
4842 | return -EINVAL; | ||
4843 | } | ||
4844 | } else if (cmd.port == ME4000_DIO_PORT_C) { | ||
4845 | if (cmd.mode == ME4000_DIO_PORT_INPUT) { | ||
4846 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4847 | tmp &= | ||
4848 | ~(ME4000_DIO_CTRL_BIT_MODE_4 | | ||
4849 | ME4000_DIO_CTRL_BIT_MODE_5); | ||
4850 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4851 | } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) { | ||
4852 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4853 | tmp &= | ||
4854 | ~(ME4000_DIO_CTRL_BIT_MODE_4 | | ||
4855 | ME4000_DIO_CTRL_BIT_MODE_5); | ||
4856 | tmp |= ME4000_DIO_CTRL_BIT_MODE_4; | ||
4857 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4858 | } else if (cmd.mode == ME4000_DIO_FIFO_LOW) { | ||
4859 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4860 | tmp &= | ||
4861 | ~(ME4000_DIO_CTRL_BIT_MODE_4 | | ||
4862 | ME4000_DIO_CTRL_BIT_MODE_5 | | ||
4863 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_2); | ||
4864 | tmp |= | ||
4865 | ME4000_DIO_CTRL_BIT_MODE_4 | | ||
4866 | ME4000_DIO_CTRL_BIT_MODE_5; | ||
4867 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4868 | } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) { | ||
4869 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4870 | tmp |= | ||
4871 | ME4000_DIO_CTRL_BIT_MODE_4 | | ||
4872 | ME4000_DIO_CTRL_BIT_MODE_5 | | ||
4873 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_2; | ||
4874 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4875 | } else { | ||
4876 | printk(KERN_ERR | ||
4877 | "ME4000:me4000_dio_config():Mode %d is not available\n", | ||
4878 | cmd.mode); | ||
4879 | return -EINVAL; | ||
4880 | } | ||
4881 | } else if (cmd.port == ME4000_DIO_PORT_D) { | ||
4882 | if (cmd.mode == ME4000_DIO_PORT_INPUT) { | ||
4883 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4884 | tmp &= | ||
4885 | ~(ME4000_DIO_CTRL_BIT_MODE_6 | | ||
4886 | ME4000_DIO_CTRL_BIT_MODE_7); | ||
4887 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4888 | } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) { | ||
4889 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4890 | tmp &= | ||
4891 | ~(ME4000_DIO_CTRL_BIT_MODE_6 | | ||
4892 | ME4000_DIO_CTRL_BIT_MODE_7); | ||
4893 | tmp |= ME4000_DIO_CTRL_BIT_MODE_6; | ||
4894 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4895 | } else if (cmd.mode == ME4000_DIO_FIFO_LOW) { | ||
4896 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4897 | tmp &= | ||
4898 | ~(ME4000_DIO_CTRL_BIT_MODE_6 | | ||
4899 | ME4000_DIO_CTRL_BIT_MODE_7 | | ||
4900 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_3); | ||
4901 | tmp |= | ||
4902 | ME4000_DIO_CTRL_BIT_MODE_6 | | ||
4903 | ME4000_DIO_CTRL_BIT_MODE_7; | ||
4904 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4905 | } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) { | ||
4906 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4907 | tmp |= | ||
4908 | ME4000_DIO_CTRL_BIT_MODE_6 | | ||
4909 | ME4000_DIO_CTRL_BIT_MODE_7 | | ||
4910 | ME4000_DIO_CTRL_BIT_FIFO_HIGH_3; | ||
4911 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4912 | } else { | ||
4913 | printk(KERN_ERR | ||
4914 | "ME4000:me4000_dio_config():Mode %d is not available\n", | ||
4915 | cmd.mode); | ||
4916 | return -EINVAL; | ||
4917 | } | ||
4918 | } else { | ||
4919 | printk(KERN_ERR | ||
4920 | "ME4000:me4000_dio_config():Port %d is not available\n", | ||
4921 | cmd.port); | ||
4922 | return -EINVAL; | ||
4923 | } | ||
4924 | |||
4925 | PDEBUG("me4000_dio_config(): port %d, mode %d, function %d\n", cmd.port, | ||
4926 | cmd.mode, cmd.function); | ||
4927 | |||
4928 | if ((cmd.mode == ME4000_DIO_FIFO_HIGH) | ||
4929 | || (cmd.mode == ME4000_DIO_FIFO_LOW)) { | ||
4930 | tmp = me4000_inl(dio_context->ctrl_reg); | ||
4931 | tmp &= | ||
4932 | ~(ME4000_DIO_CTRL_BIT_FUNCTION_0 | | ||
4933 | ME4000_DIO_CTRL_BIT_FUNCTION_1); | ||
4934 | if (cmd.function == ME4000_DIO_FUNCTION_PATTERN) { | ||
4935 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4936 | } else if (cmd.function == ME4000_DIO_FUNCTION_DEMUX) { | ||
4937 | tmp |= ME4000_DIO_CTRL_BIT_FUNCTION_0; | ||
4938 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4939 | } else if (cmd.function == ME4000_DIO_FUNCTION_MUX) { | ||
4940 | tmp |= ME4000_DIO_CTRL_BIT_FUNCTION_1; | ||
4941 | me4000_outl(tmp, dio_context->ctrl_reg); | ||
4942 | } else { | ||
4943 | printk(KERN_ERR | ||
4944 | "ME4000:me4000_dio_config():Invalid port function specified\n"); | ||
4945 | return -EINVAL; | ||
4946 | } | ||
4947 | } | ||
4948 | |||
4949 | return 0; | ||
4950 | } | ||
4951 | |||
4952 | static int me4000_dio_set_byte(struct me4000_dio_byte *arg, | ||
4953 | struct me4000_dio_context *dio_context) | ||
4954 | { | ||
4955 | struct me4000_dio_byte cmd; | ||
4956 | int err; | ||
4957 | |||
4958 | CALL_PDEBUG("me4000_dio_set_byte() is executed\n"); | ||
4959 | |||
4960 | /* Copy data from user */ | ||
4961 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_byte)); | ||
4962 | if (err) { | ||
4963 | printk(KERN_ERR | ||
4964 | "ME4000:me4000_dio_set_byte():Can't copy from user space\n"); | ||
4965 | return -EFAULT; | ||
4966 | } | ||
4967 | |||
4968 | /* Check port parameter */ | ||
4969 | if (cmd.port >= dio_context->dio_count) { | ||
4970 | printk(KERN_ERR | ||
4971 | "ME4000:me4000_dio_set_byte():Port %d is not available\n", | ||
4972 | cmd.port); | ||
4973 | return -EINVAL; | ||
4974 | } | ||
4975 | |||
4976 | if (cmd.port == ME4000_DIO_PORT_A) { | ||
4977 | if ((me4000_inl(dio_context->ctrl_reg) & 0x3) != 0x1) { | ||
4978 | printk(KERN_ERR | ||
4979 | "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n", | ||
4980 | cmd.port); | ||
4981 | return -EIO; | ||
4982 | } | ||
4983 | me4000_outl(cmd.byte, dio_context->port_0_reg); | ||
4984 | } else if (cmd.port == ME4000_DIO_PORT_B) { | ||
4985 | if ((me4000_inl(dio_context->ctrl_reg) & 0xC) != 0x4) { | ||
4986 | printk(KERN_ERR | ||
4987 | "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n", | ||
4988 | cmd.port); | ||
4989 | return -EIO; | ||
4990 | } | ||
4991 | me4000_outl(cmd.byte, dio_context->port_1_reg); | ||
4992 | } else if (cmd.port == ME4000_DIO_PORT_C) { | ||
4993 | if ((me4000_inl(dio_context->ctrl_reg) & 0x30) != 0x10) { | ||
4994 | printk(KERN_ERR | ||
4995 | "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n", | ||
4996 | cmd.port); | ||
4997 | return -EIO; | ||
4998 | } | ||
4999 | me4000_outl(cmd.byte, dio_context->port_2_reg); | ||
5000 | } else if (cmd.port == ME4000_DIO_PORT_D) { | ||
5001 | if ((me4000_inl(dio_context->ctrl_reg) & 0xC0) != 0x40) { | ||
5002 | printk(KERN_ERR | ||
5003 | "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n", | ||
5004 | cmd.port); | ||
5005 | return -EIO; | ||
5006 | } | ||
5007 | me4000_outl(cmd.byte, dio_context->port_3_reg); | ||
5008 | } else { | ||
5009 | printk(KERN_ERR | ||
5010 | "ME4000:me4000_dio_set_byte():Port %d is not available\n", | ||
5011 | cmd.port); | ||
5012 | return -EINVAL; | ||
5013 | } | ||
5014 | |||
5015 | return 0; | ||
5016 | } | ||
5017 | |||
5018 | static int me4000_dio_get_byte(struct me4000_dio_byte *arg, | ||
5019 | struct me4000_dio_context *dio_context) | ||
5020 | { | ||
5021 | struct me4000_dio_byte cmd; | ||
5022 | int err; | ||
5023 | |||
5024 | CALL_PDEBUG("me4000_dio_get_byte() is executed\n"); | ||
5025 | |||
5026 | /* Copy data from user */ | ||
5027 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_byte)); | ||
5028 | if (err) { | ||
5029 | printk(KERN_ERR | ||
5030 | "ME4000:me4000_dio_get_byte():Can't copy from user space\n"); | ||
5031 | return -EFAULT; | ||
5032 | } | ||
5033 | |||
5034 | /* Check port parameter */ | ||
5035 | if (cmd.port >= dio_context->dio_count) { | ||
5036 | printk(KERN_ERR | ||
5037 | "ME4000:me4000_dio_get_byte():Port %d is not available\n", | ||
5038 | cmd.port); | ||
5039 | return -EINVAL; | ||
5040 | } | ||
5041 | |||
5042 | if (cmd.port == ME4000_DIO_PORT_A) { | ||
5043 | cmd.byte = me4000_inl(dio_context->port_0_reg) & 0xFF; | ||
5044 | } else if (cmd.port == ME4000_DIO_PORT_B) { | ||
5045 | cmd.byte = me4000_inl(dio_context->port_1_reg) & 0xFF; | ||
5046 | } else if (cmd.port == ME4000_DIO_PORT_C) { | ||
5047 | cmd.byte = me4000_inl(dio_context->port_2_reg) & 0xFF; | ||
5048 | } else if (cmd.port == ME4000_DIO_PORT_D) { | ||
5049 | cmd.byte = me4000_inl(dio_context->port_3_reg) & 0xFF; | ||
5050 | } else { | ||
5051 | printk(KERN_ERR | ||
5052 | "ME4000:me4000_dio_get_byte():Port %d is not available\n", | ||
5053 | cmd.port); | ||
5054 | return -EINVAL; | ||
5055 | } | ||
5056 | |||
5057 | /* Copy result back to user */ | ||
5058 | err = copy_to_user(arg, &cmd, sizeof(struct me4000_dio_byte)); | ||
5059 | if (err) { | ||
5060 | printk(KERN_ERR | ||
5061 | "ME4000:me4000_dio_get_byte():Can't copy to user space\n"); | ||
5062 | return -EFAULT; | ||
5063 | } | ||
5064 | |||
5065 | return 0; | ||
5066 | } | ||
5067 | |||
5068 | static int me4000_dio_reset(struct me4000_dio_context *dio_context) | ||
5069 | { | ||
5070 | CALL_PDEBUG("me4000_dio_reset() is executed\n"); | ||
5071 | |||
5072 | /* Clear the control register */ | ||
5073 | me4000_outl(0, dio_context->ctrl_reg); | ||
5074 | |||
5075 | /* Check for opto isolated version */ | ||
5076 | if (!(me4000_inl(dio_context->dir_reg) & 0x1)) { | ||
5077 | me4000_outl(0x1, dio_context->ctrl_reg); | ||
5078 | me4000_outl(0x0, dio_context->port_0_reg); | ||
5079 | } | ||
5080 | |||
5081 | return 0; | ||
5082 | } | ||
5083 | |||
5084 | /*------------------------------------ COUNTER STUFF ------------------------------------*/ | ||
5085 | |||
5086 | static int me4000_cnt_ioctl(struct inode *inode_p, struct file *file_p, | ||
5087 | unsigned int service, unsigned long arg) | ||
5088 | { | ||
5089 | struct me4000_cnt_context *cnt_context; | ||
5090 | |||
5091 | CALL_PDEBUG("me4000_cnt_ioctl() is executed\n"); | ||
5092 | |||
5093 | cnt_context = file_p->private_data; | ||
5094 | |||
5095 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
5096 | printk(KERN_ERR "me4000_dio_ioctl():Wrong magic number\n"); | ||
5097 | return -ENOTTY; | ||
5098 | } | ||
5099 | if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) { | ||
5100 | printk(KERN_ERR "me4000_dio_ioctl():Service number to high\n"); | ||
5101 | return -ENOTTY; | ||
5102 | } | ||
5103 | |||
5104 | switch (service) { | ||
5105 | case ME4000_CNT_READ: | ||
5106 | return me4000_cnt_read((struct me4000_cnt *)arg, cnt_context); | ||
5107 | case ME4000_CNT_WRITE: | ||
5108 | return me4000_cnt_write((struct me4000_cnt *)arg, cnt_context); | ||
5109 | case ME4000_CNT_CONFIG: | ||
5110 | return me4000_cnt_config((struct me4000_cnt_config *)arg, | ||
5111 | cnt_context); | ||
5112 | case ME4000_CNT_RESET: | ||
5113 | return me4000_cnt_reset(cnt_context); | ||
5114 | default: | ||
5115 | printk(KERN_ERR | ||
5116 | "ME4000:me4000_dio_ioctl():Invalid service number %d\n", | ||
5117 | service); | ||
5118 | return -ENOTTY; | ||
5119 | } | ||
5120 | return 0; | ||
5121 | } | ||
5122 | |||
5123 | static int me4000_cnt_config(struct me4000_cnt_config *arg, | ||
5124 | struct me4000_cnt_context *cnt_context) | ||
5125 | { | ||
5126 | struct me4000_cnt_config cmd; | ||
5127 | u8 counter; | ||
5128 | u8 mode; | ||
5129 | int err; | ||
5130 | |||
5131 | CALL_PDEBUG("me4000_cnt_config() is executed\n"); | ||
5132 | |||
5133 | /* Copy data from user */ | ||
5134 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt_config)); | ||
5135 | if (err) { | ||
5136 | printk(KERN_ERR | ||
5137 | "ME4000:me4000_cnt_config():Can't copy from user space\n"); | ||
5138 | return -EFAULT; | ||
5139 | } | ||
5140 | |||
5141 | /* Check counter parameter */ | ||
5142 | switch (cmd.counter) { | ||
5143 | case ME4000_CNT_COUNTER_0: | ||
5144 | counter = ME4000_CNT_CTRL_BIT_COUNTER_0; | ||
5145 | break; | ||
5146 | case ME4000_CNT_COUNTER_1: | ||
5147 | counter = ME4000_CNT_CTRL_BIT_COUNTER_1; | ||
5148 | break; | ||
5149 | case ME4000_CNT_COUNTER_2: | ||
5150 | counter = ME4000_CNT_CTRL_BIT_COUNTER_2; | ||
5151 | break; | ||
5152 | default: | ||
5153 | printk(KERN_ERR | ||
5154 | "ME4000:me4000_cnt_config():Counter %d is not available\n", | ||
5155 | cmd.counter); | ||
5156 | return -EINVAL; | ||
5157 | } | ||
5158 | |||
5159 | /* Check mode parameter */ | ||
5160 | switch (cmd.mode) { | ||
5161 | case ME4000_CNT_MODE_0: | ||
5162 | mode = ME4000_CNT_CTRL_BIT_MODE_0; | ||
5163 | break; | ||
5164 | case ME4000_CNT_MODE_1: | ||
5165 | mode = ME4000_CNT_CTRL_BIT_MODE_1; | ||
5166 | break; | ||
5167 | case ME4000_CNT_MODE_2: | ||
5168 | mode = ME4000_CNT_CTRL_BIT_MODE_2; | ||
5169 | break; | ||
5170 | case ME4000_CNT_MODE_3: | ||
5171 | mode = ME4000_CNT_CTRL_BIT_MODE_3; | ||
5172 | break; | ||
5173 | case ME4000_CNT_MODE_4: | ||
5174 | mode = ME4000_CNT_CTRL_BIT_MODE_4; | ||
5175 | break; | ||
5176 | case ME4000_CNT_MODE_5: | ||
5177 | mode = ME4000_CNT_CTRL_BIT_MODE_5; | ||
5178 | break; | ||
5179 | default: | ||
5180 | printk(KERN_ERR | ||
5181 | "ME4000:me4000_cnt_config():Mode %d is not available\n", | ||
5182 | cmd.mode); | ||
5183 | return -EINVAL; | ||
5184 | } | ||
5185 | |||
5186 | /* Write the control word */ | ||
5187 | me4000_outb((counter | mode | 0x30), cnt_context->ctrl_reg); | ||
5188 | |||
5189 | return 0; | ||
5190 | } | ||
5191 | |||
5192 | static int me4000_cnt_read(struct me4000_cnt *arg, | ||
5193 | struct me4000_cnt_context *cnt_context) | ||
5194 | { | ||
5195 | struct me4000_cnt cmd; | ||
5196 | u8 tmp; | ||
5197 | int err; | ||
5198 | |||
5199 | CALL_PDEBUG("me4000_cnt_read() is executed\n"); | ||
5200 | |||
5201 | /* Copy data from user */ | ||
5202 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt)); | ||
5203 | if (err) { | ||
5204 | printk(KERN_ERR | ||
5205 | "ME4000:me4000_cnt_read():Can't copy from user space\n"); | ||
5206 | return -EFAULT; | ||
5207 | } | ||
5208 | |||
5209 | /* Read counter */ | ||
5210 | switch (cmd.counter) { | ||
5211 | case ME4000_CNT_COUNTER_0: | ||
5212 | tmp = me4000_inb(cnt_context->counter_0_reg); | ||
5213 | cmd.value = tmp; | ||
5214 | tmp = me4000_inb(cnt_context->counter_0_reg); | ||
5215 | cmd.value |= ((u16) tmp) << 8; | ||
5216 | break; | ||
5217 | case ME4000_CNT_COUNTER_1: | ||
5218 | tmp = me4000_inb(cnt_context->counter_1_reg); | ||
5219 | cmd.value = tmp; | ||
5220 | tmp = me4000_inb(cnt_context->counter_1_reg); | ||
5221 | cmd.value |= ((u16) tmp) << 8; | ||
5222 | break; | ||
5223 | case ME4000_CNT_COUNTER_2: | ||
5224 | tmp = me4000_inb(cnt_context->counter_2_reg); | ||
5225 | cmd.value = tmp; | ||
5226 | tmp = me4000_inb(cnt_context->counter_2_reg); | ||
5227 | cmd.value |= ((u16) tmp) << 8; | ||
5228 | break; | ||
5229 | default: | ||
5230 | printk(KERN_ERR | ||
5231 | "ME4000:me4000_cnt_read():Counter %d is not available\n", | ||
5232 | cmd.counter); | ||
5233 | return -EINVAL; | ||
5234 | } | ||
5235 | |||
5236 | /* Copy result back to user */ | ||
5237 | err = copy_to_user(arg, &cmd, sizeof(struct me4000_cnt)); | ||
5238 | if (err) { | ||
5239 | printk(KERN_ERR | ||
5240 | "ME4000:me4000_cnt_read():Can't copy to user space\n"); | ||
5241 | return -EFAULT; | ||
5242 | } | ||
5243 | |||
5244 | return 0; | ||
5245 | } | ||
5246 | |||
5247 | static int me4000_cnt_write(struct me4000_cnt *arg, | ||
5248 | struct me4000_cnt_context *cnt_context) | ||
5249 | { | ||
5250 | struct me4000_cnt cmd; | ||
5251 | u8 tmp; | ||
5252 | int err; | ||
5253 | |||
5254 | CALL_PDEBUG("me4000_cnt_write() is executed\n"); | ||
5255 | |||
5256 | /* Copy data from user */ | ||
5257 | err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt)); | ||
5258 | if (err) { | ||
5259 | printk(KERN_ERR | ||
5260 | "ME4000:me4000_cnt_write():Can't copy from user space\n"); | ||
5261 | return -EFAULT; | ||
5262 | } | ||
5263 | |||
5264 | /* Write counter */ | ||
5265 | switch (cmd.counter) { | ||
5266 | case ME4000_CNT_COUNTER_0: | ||
5267 | tmp = cmd.value & 0xFF; | ||
5268 | me4000_outb(tmp, cnt_context->counter_0_reg); | ||
5269 | tmp = (cmd.value >> 8) & 0xFF; | ||
5270 | me4000_outb(tmp, cnt_context->counter_0_reg); | ||
5271 | break; | ||
5272 | case ME4000_CNT_COUNTER_1: | ||
5273 | tmp = cmd.value & 0xFF; | ||
5274 | me4000_outb(tmp, cnt_context->counter_1_reg); | ||
5275 | tmp = (cmd.value >> 8) & 0xFF; | ||
5276 | me4000_outb(tmp, cnt_context->counter_1_reg); | ||
5277 | break; | ||
5278 | case ME4000_CNT_COUNTER_2: | ||
5279 | tmp = cmd.value & 0xFF; | ||
5280 | me4000_outb(tmp, cnt_context->counter_2_reg); | ||
5281 | tmp = (cmd.value >> 8) & 0xFF; | ||
5282 | me4000_outb(tmp, cnt_context->counter_2_reg); | ||
5283 | break; | ||
5284 | default: | ||
5285 | printk(KERN_ERR | ||
5286 | "ME4000:me4000_cnt_write():Counter %d is not available\n", | ||
5287 | cmd.counter); | ||
5288 | return -EINVAL; | ||
5289 | } | ||
5290 | |||
5291 | return 0; | ||
5292 | } | ||
5293 | |||
5294 | static int me4000_cnt_reset(struct me4000_cnt_context *cnt_context) | ||
5295 | { | ||
5296 | CALL_PDEBUG("me4000_cnt_reset() is executed\n"); | ||
5297 | |||
5298 | /* Set the mode and value for counter 0 */ | ||
5299 | me4000_outb(0x30, cnt_context->ctrl_reg); | ||
5300 | me4000_outb(0x00, cnt_context->counter_0_reg); | ||
5301 | me4000_outb(0x00, cnt_context->counter_0_reg); | ||
5302 | |||
5303 | /* Set the mode and value for counter 1 */ | ||
5304 | me4000_outb(0x70, cnt_context->ctrl_reg); | ||
5305 | me4000_outb(0x00, cnt_context->counter_1_reg); | ||
5306 | me4000_outb(0x00, cnt_context->counter_1_reg); | ||
5307 | |||
5308 | /* Set the mode and value for counter 2 */ | ||
5309 | me4000_outb(0xB0, cnt_context->ctrl_reg); | ||
5310 | me4000_outb(0x00, cnt_context->counter_2_reg); | ||
5311 | me4000_outb(0x00, cnt_context->counter_2_reg); | ||
5312 | |||
5313 | return 0; | ||
5314 | } | ||
5315 | |||
5316 | /*------------------------------------ External Interrupt stuff ------------------------------------*/ | ||
5317 | |||
5318 | static int me4000_ext_int_ioctl(struct inode *inode_p, struct file *file_p, | ||
5319 | unsigned int service, unsigned long arg) | ||
5320 | { | ||
5321 | struct me4000_ext_int_context *ext_int_context; | ||
5322 | |||
5323 | CALL_PDEBUG("me4000_ext_int_ioctl() is executed\n"); | ||
5324 | |||
5325 | ext_int_context = file_p->private_data; | ||
5326 | |||
5327 | if (_IOC_TYPE(service) != ME4000_MAGIC) { | ||
5328 | printk(KERN_ERR "me4000_ext_int_ioctl():Wrong magic number\n"); | ||
5329 | return -ENOTTY; | ||
5330 | } | ||
5331 | if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) { | ||
5332 | printk(KERN_ERR | ||
5333 | "me4000_ext_int_ioctl():Service number to high\n"); | ||
5334 | return -ENOTTY; | ||
5335 | } | ||
5336 | |||
5337 | switch (service) { | ||
5338 | case ME4000_EXT_INT_ENABLE: | ||
5339 | return me4000_ext_int_enable(ext_int_context); | ||
5340 | case ME4000_EXT_INT_DISABLE: | ||
5341 | return me4000_ext_int_disable(ext_int_context); | ||
5342 | case ME4000_EXT_INT_COUNT: | ||
5343 | return me4000_ext_int_count((unsigned long *)arg, | ||
5344 | ext_int_context); | ||
5345 | default: | ||
5346 | printk(KERN_ERR | ||
5347 | "ME4000:me4000_ext_int_ioctl():Invalid service number %d\n", | ||
5348 | service); | ||
5349 | return -ENOTTY; | ||
5350 | } | ||
5351 | return 0; | ||
5352 | } | ||
5353 | |||
5354 | static int me4000_ext_int_enable(struct me4000_ext_int_context *ext_int_context) | ||
5355 | { | ||
5356 | unsigned long tmp; | ||
5357 | |||
5358 | CALL_PDEBUG("me4000_ext_int_enable() is executed\n"); | ||
5359 | |||
5360 | tmp = me4000_inl(ext_int_context->ctrl_reg); | ||
5361 | tmp |= ME4000_AI_CTRL_BIT_EX_IRQ; | ||
5362 | me4000_outl(tmp, ext_int_context->ctrl_reg); | ||
5363 | |||
5364 | return 0; | ||
5365 | } | ||
5366 | |||
5367 | static int me4000_ext_int_disable(struct me4000_ext_int_context *ext_int_context) | ||
5368 | { | ||
5369 | unsigned long tmp; | ||
5370 | |||
5371 | CALL_PDEBUG("me4000_ext_int_disable() is executed\n"); | ||
5372 | |||
5373 | tmp = me4000_inl(ext_int_context->ctrl_reg); | ||
5374 | tmp &= ~ME4000_AI_CTRL_BIT_EX_IRQ; | ||
5375 | me4000_outl(tmp, ext_int_context->ctrl_reg); | ||
5376 | |||
5377 | return 0; | ||
5378 | } | ||
5379 | |||
5380 | static int me4000_ext_int_count(unsigned long *arg, | ||
5381 | struct me4000_ext_int_context *ext_int_context) | ||
5382 | { | ||
5383 | |||
5384 | CALL_PDEBUG("me4000_ext_int_count() is executed\n"); | ||
5385 | |||
5386 | put_user(ext_int_context->int_count, arg); | ||
5387 | return 0; | ||
5388 | } | ||
5389 | |||
5390 | /*------------------------------------ General stuff ------------------------------------*/ | ||
5391 | |||
5392 | static int me4000_get_user_info(struct me4000_user_info *arg, | ||
5393 | struct me4000_info *board_info) | ||
5394 | { | ||
5395 | struct me4000_user_info user_info; | ||
5396 | |||
5397 | CALL_PDEBUG("me4000_get_user_info() is executed\n"); | ||
5398 | |||
5399 | user_info.board_count = board_info->board_count; | ||
5400 | user_info.plx_regbase = board_info->plx_regbase; | ||
5401 | user_info.plx_regbase_size = board_info->plx_regbase_size; | ||
5402 | user_info.me4000_regbase = board_info->me4000_regbase; | ||
5403 | user_info.me4000_regbase_size = board_info->me4000_regbase_size; | ||
5404 | user_info.serial_no = board_info->serial_no; | ||
5405 | user_info.hw_revision = board_info->hw_revision; | ||
5406 | user_info.vendor_id = board_info->vendor_id; | ||
5407 | user_info.device_id = board_info->device_id; | ||
5408 | user_info.pci_bus_no = board_info->pci_bus_no; | ||
5409 | user_info.pci_dev_no = board_info->pci_dev_no; | ||
5410 | user_info.pci_func_no = board_info->pci_func_no; | ||
5411 | user_info.irq = board_info->irq; | ||
5412 | user_info.irq_count = board_info->irq_count; | ||
5413 | user_info.driver_version = ME4000_DRIVER_VERSION; | ||
5414 | user_info.ao_count = board_info->board_p->ao.count; | ||
5415 | user_info.ao_fifo_count = board_info->board_p->ao.fifo_count; | ||
5416 | |||
5417 | user_info.ai_count = board_info->board_p->ai.count; | ||
5418 | user_info.ai_sh_count = board_info->board_p->ai.sh_count; | ||
5419 | user_info.ai_ex_trig_analog = board_info->board_p->ai.ex_trig_analog; | ||
5420 | |||
5421 | user_info.dio_count = board_info->board_p->dio.count; | ||
5422 | |||
5423 | user_info.cnt_count = board_info->board_p->cnt.count; | ||
5424 | |||
5425 | if (copy_to_user(arg, &user_info, sizeof(struct me4000_user_info))) | ||
5426 | return -EFAULT; | ||
5427 | |||
5428 | return 0; | ||
5429 | } | ||
5430 | |||
5431 | /*------------------------------------ ISR STUFF ------------------------------------*/ | ||
5432 | |||
5433 | static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode) | ||
5434 | { | ||
5435 | int result = 0; | ||
5436 | struct me4000_ext_int_context *ext_int_context; | ||
5437 | |||
5438 | CALL_PDEBUG("me4000_ext_int_fasync() is executed\n"); | ||
5439 | |||
5440 | ext_int_context = file_ptr->private_data; | ||
5441 | |||
5442 | result = | ||
5443 | fasync_helper(fd, file_ptr, mode, &ext_int_context->fasync_ptr); | ||
5444 | |||
5445 | CALL_PDEBUG("me4000_ext_int_fasync() is leaved\n"); | ||
5446 | return result; | ||
5447 | } | ||
5448 | |||
5449 | static irqreturn_t me4000_ao_isr(int irq, void *dev_id) | ||
5450 | { | ||
5451 | u32 tmp; | ||
5452 | u32 value; | ||
5453 | struct me4000_ao_context *ao_context; | ||
5454 | int i; | ||
5455 | int c = 0; | ||
5456 | int c1 = 0; | ||
5457 | |||
5458 | ISR_PDEBUG("me4000_ao_isr() is executed\n"); | ||
5459 | |||
5460 | ao_context = dev_id; | ||
5461 | |||
5462 | /* Check if irq number is right */ | ||
5463 | if (irq != ao_context->irq) { | ||
5464 | ISR_PDEBUG("me4000_ao_isr():incorrect interrupt num: %d\n", | ||
5465 | irq); | ||
5466 | return IRQ_NONE; | ||
5467 | } | ||
5468 | |||
5469 | /* Check if this DAC rised an interrupt */ | ||
5470 | if (! | ||
5471 | ((0x1 << (ao_context->index + 3)) & | ||
5472 | me4000_inl(ao_context->irq_status_reg))) { | ||
5473 | ISR_PDEBUG("me4000_ao_isr():Not this DAC\n"); | ||
5474 | return IRQ_NONE; | ||
5475 | } | ||
5476 | |||
5477 | /* Read status register to find out what happened */ | ||
5478 | tmp = me4000_inl(ao_context->status_reg); | ||
5479 | |||
5480 | if (!(tmp & ME4000_AO_STATUS_BIT_EF) && (tmp & ME4000_AO_STATUS_BIT_HF) | ||
5481 | && (tmp & ME4000_AO_STATUS_BIT_HF)) { | ||
5482 | c = ME4000_AO_FIFO_COUNT; | ||
5483 | ISR_PDEBUG("me4000_ao_isr():Fifo empty\n"); | ||
5484 | } else if ((tmp & ME4000_AO_STATUS_BIT_EF) | ||
5485 | && (tmp & ME4000_AO_STATUS_BIT_HF) | ||
5486 | && (tmp & ME4000_AO_STATUS_BIT_HF)) { | ||
5487 | c = ME4000_AO_FIFO_COUNT / 2; | ||
5488 | ISR_PDEBUG("me4000_ao_isr():Fifo under half full\n"); | ||
5489 | } else { | ||
5490 | c = 0; | ||
5491 | ISR_PDEBUG("me4000_ao_isr():Fifo full\n"); | ||
5492 | } | ||
5493 | |||
5494 | ISR_PDEBUG("me4000_ao_isr():Try to write 0x%04X values\n", c); | ||
5495 | |||
5496 | while (1) { | ||
5497 | c1 = me4000_values_to_end(ao_context->circ_buf, | ||
5498 | ME4000_AO_BUFFER_COUNT); | ||
5499 | ISR_PDEBUG("me4000_ao_isr():Values to end = %d\n", c1); | ||
5500 | if (c1 > c) | ||
5501 | c1 = c; | ||
5502 | |||
5503 | if (c1 <= 0) { | ||
5504 | ISR_PDEBUG | ||
5505 | ("me4000_ao_isr():Work done or buffer empty\n"); | ||
5506 | break; | ||
5507 | } | ||
5508 | if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG) || | ||
5509 | ((ao_context->fifo_reg & 0xFF) == ME4000_AO_03_FIFO_REG)) { | ||
5510 | for (i = 0; i < c1; i++) { | ||
5511 | value = | ||
5512 | ((u32) | ||
5513 | (* | ||
5514 | (ao_context->circ_buf.buf + | ||
5515 | ao_context->circ_buf.tail + i))) << 16; | ||
5516 | outl(value, ao_context->fifo_reg); | ||
5517 | } | ||
5518 | } else | ||
5519 | outsw(ao_context->fifo_reg, | ||
5520 | ao_context->circ_buf.buf + | ||
5521 | ao_context->circ_buf.tail, c1); | ||
5522 | |||
5523 | |||
5524 | ao_context->circ_buf.tail = | ||
5525 | (ao_context->circ_buf.tail + c1) & (ME4000_AO_BUFFER_COUNT - | ||
5526 | 1); | ||
5527 | ISR_PDEBUG("me4000_ao_isr():%d values wrote to port 0x%04X\n", | ||
5528 | c1, ao_context->fifo_reg); | ||
5529 | c -= c1; | ||
5530 | } | ||
5531 | |||
5532 | /* If there are no values left in the buffer, disable interrupts */ | ||
5533 | spin_lock(&ao_context->int_lock); | ||
5534 | if (!me4000_buf_count(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) { | ||
5535 | ISR_PDEBUG | ||
5536 | ("me4000_ao_isr():Disable Interrupt because no values left in buffer\n"); | ||
5537 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
5538 | tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ; | ||
5539 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
5540 | } | ||
5541 | spin_unlock(&ao_context->int_lock); | ||
5542 | |||
5543 | /* Reset the interrupt */ | ||
5544 | spin_lock(&ao_context->int_lock); | ||
5545 | tmp = me4000_inl(ao_context->ctrl_reg); | ||
5546 | tmp |= ME4000_AO_CTRL_BIT_RESET_IRQ; | ||
5547 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
5548 | tmp &= ~ME4000_AO_CTRL_BIT_RESET_IRQ; | ||
5549 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
5550 | |||
5551 | /* If state machine is stopped, flow was interrupted */ | ||
5552 | if (!(me4000_inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM)) { | ||
5553 | printk(KERN_ERR "ME4000:me4000_ao_isr():Broken pipe\n"); | ||
5554 | /* Set flag in order to inform write routine */ | ||
5555 | ao_context->pipe_flag = 1; | ||
5556 | /* Disable interrupt */ | ||
5557 | tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ; | ||
5558 | } | ||
5559 | me4000_outl(tmp, ao_context->ctrl_reg); | ||
5560 | spin_unlock(&ao_context->int_lock); | ||
5561 | |||
5562 | /* Wake up waiting process */ | ||
5563 | wake_up_interruptible(&(ao_context->wait_queue)); | ||
5564 | |||
5565 | /* Count the interrupt */ | ||
5566 | ao_context->board_info->irq_count++; | ||
5567 | |||
5568 | return IRQ_HANDLED; | ||
5569 | } | ||
5570 | |||
5571 | static irqreturn_t me4000_ai_isr(int irq, void *dev_id) | ||
5572 | { | ||
5573 | u32 tmp; | ||
5574 | struct me4000_ai_context *ai_context; | ||
5575 | int i; | ||
5576 | int c = 0; | ||
5577 | int c1 = 0; | ||
5578 | #ifdef ME4000_ISR_DEBUG | ||
5579 | unsigned long before; | ||
5580 | unsigned long after; | ||
5581 | #endif | ||
5582 | |||
5583 | ISR_PDEBUG("me4000_ai_isr() is executed\n"); | ||
5584 | |||
5585 | #ifdef ME4000_ISR_DEBUG | ||
5586 | rdtscl(before); | ||
5587 | #endif | ||
5588 | |||
5589 | ai_context = dev_id; | ||
5590 | |||
5591 | /* Check if irq number is right */ | ||
5592 | if (irq != ai_context->irq) { | ||
5593 | ISR_PDEBUG("me4000_ai_isr():incorrect interrupt num: %d\n", | ||
5594 | irq); | ||
5595 | return IRQ_NONE; | ||
5596 | } | ||
5597 | |||
5598 | if (me4000_inl(ai_context->irq_status_reg) & | ||
5599 | ME4000_IRQ_STATUS_BIT_AI_HF) { | ||
5600 | ISR_PDEBUG | ||
5601 | ("me4000_ai_isr():Fifo half full interrupt occured\n"); | ||
5602 | |||
5603 | /* Read status register to find out what happened */ | ||
5604 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5605 | |||
5606 | if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && | ||
5607 | !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) | ||
5608 | && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
5609 | ISR_PDEBUG("me4000_ai_isr():Fifo full\n"); | ||
5610 | c = ME4000_AI_FIFO_COUNT; | ||
5611 | |||
5612 | /* FIFO overflow, so stop conversion and disable all interrupts */ | ||
5613 | spin_lock(&ai_context->int_lock); | ||
5614 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5615 | tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
5616 | tmp &= | ||
5617 | ~(ME4000_AI_CTRL_BIT_HF_IRQ | | ||
5618 | ME4000_AI_CTRL_BIT_SC_IRQ); | ||
5619 | outl(tmp, ai_context->ctrl_reg); | ||
5620 | spin_unlock(&ai_context->int_lock); | ||
5621 | } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) && | ||
5622 | !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) | ||
5623 | && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
5624 | ISR_PDEBUG("me4000_ai_isr():Fifo half full\n"); | ||
5625 | c = ME4000_AI_FIFO_COUNT / 2; | ||
5626 | } else { | ||
5627 | c = 0; | ||
5628 | ISR_PDEBUG | ||
5629 | ("me4000_ai_isr():Can't determine state of fifo\n"); | ||
5630 | } | ||
5631 | |||
5632 | ISR_PDEBUG("me4000_ai_isr():Try to read %d values\n", c); | ||
5633 | |||
5634 | while (1) { | ||
5635 | c1 = me4000_space_to_end(ai_context->circ_buf, | ||
5636 | ME4000_AI_BUFFER_COUNT); | ||
5637 | ISR_PDEBUG("me4000_ai_isr():Space to end = %d\n", c1); | ||
5638 | if (c1 > c) | ||
5639 | c1 = c; | ||
5640 | |||
5641 | if (c1 <= 0) { | ||
5642 | ISR_PDEBUG | ||
5643 | ("me4000_ai_isr():Work done or buffer full\n"); | ||
5644 | break; | ||
5645 | } | ||
5646 | |||
5647 | insw(ai_context->data_reg, | ||
5648 | ai_context->circ_buf.buf + | ||
5649 | ai_context->circ_buf.head, c1); | ||
5650 | ai_context->circ_buf.head = | ||
5651 | (ai_context->circ_buf.head + | ||
5652 | c1) & (ME4000_AI_BUFFER_COUNT - 1); | ||
5653 | c -= c1; | ||
5654 | } | ||
5655 | |||
5656 | /* Work is done, so reset the interrupt */ | ||
5657 | ISR_PDEBUG | ||
5658 | ("me4000_ai_isr():reset interrupt fifo half full interrupt\n"); | ||
5659 | spin_lock(&ai_context->int_lock); | ||
5660 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5661 | tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET; | ||
5662 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
5663 | tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET; | ||
5664 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
5665 | spin_unlock(&ai_context->int_lock); | ||
5666 | } | ||
5667 | |||
5668 | if (me4000_inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) { | ||
5669 | ISR_PDEBUG | ||
5670 | ("me4000_ai_isr():Sample counter interrupt occured\n"); | ||
5671 | |||
5672 | if (!ai_context->sample_counter_reload) { | ||
5673 | ISR_PDEBUG | ||
5674 | ("me4000_ai_isr():Single data block available\n"); | ||
5675 | |||
5676 | /* Poll data until fifo empty */ | ||
5677 | for (i = 0; | ||
5678 | (i < ME4000_AI_FIFO_COUNT / 2) | ||
5679 | && (inl(ai_context->ctrl_reg) & | ||
5680 | ME4000_AI_STATUS_BIT_EF_DATA); i++) { | ||
5681 | if (me4000_space_to_end | ||
5682 | (ai_context->circ_buf, | ||
5683 | ME4000_AI_BUFFER_COUNT)) { | ||
5684 | *(ai_context->circ_buf.buf + | ||
5685 | ai_context->circ_buf.head) = | ||
5686 | inw(ai_context->data_reg); | ||
5687 | ai_context->circ_buf.head = | ||
5688 | (ai_context->circ_buf.head + | ||
5689 | 1) & (ME4000_AI_BUFFER_COUNT - 1); | ||
5690 | } else | ||
5691 | break; | ||
5692 | } | ||
5693 | ISR_PDEBUG("me4000_ai_isr():%d values read\n", i); | ||
5694 | } else { | ||
5695 | if (ai_context->sample_counter <= | ||
5696 | ME4000_AI_FIFO_COUNT / 2) { | ||
5697 | ISR_PDEBUG | ||
5698 | ("me4000_ai_isr():Interrupt from adjustable half full threshold\n"); | ||
5699 | |||
5700 | /* Read status register to find out what happened */ | ||
5701 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5702 | |||
5703 | if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && | ||
5704 | !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) | ||
5705 | && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
5706 | ISR_PDEBUG | ||
5707 | ("me4000_ai_isr():Fifo full\n"); | ||
5708 | c = ME4000_AI_FIFO_COUNT; | ||
5709 | |||
5710 | /* FIFO overflow, so stop conversion */ | ||
5711 | spin_lock(&ai_context->int_lock); | ||
5712 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5713 | tmp |= | ||
5714 | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
5715 | outl(tmp, ai_context->ctrl_reg); | ||
5716 | spin_unlock(&ai_context->int_lock); | ||
5717 | } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) | ||
5718 | && !(tmp & | ||
5719 | ME4000_AI_STATUS_BIT_HF_DATA) | ||
5720 | && (tmp & | ||
5721 | ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
5722 | ISR_PDEBUG | ||
5723 | ("me4000_ai_isr():Fifo half full\n"); | ||
5724 | c = ME4000_AI_FIFO_COUNT / 2; | ||
5725 | } else { | ||
5726 | c = ai_context->sample_counter; | ||
5727 | ISR_PDEBUG | ||
5728 | ("me4000_ai_isr():Sample count values\n"); | ||
5729 | } | ||
5730 | |||
5731 | ISR_PDEBUG | ||
5732 | ("me4000_ai_isr():Try to read %d values\n", | ||
5733 | c); | ||
5734 | |||
5735 | while (1) { | ||
5736 | c1 = me4000_space_to_end(ai_context-> | ||
5737 | circ_buf, | ||
5738 | ME4000_AI_BUFFER_COUNT); | ||
5739 | ISR_PDEBUG | ||
5740 | ("me4000_ai_isr():Space to end = %d\n", | ||
5741 | c1); | ||
5742 | if (c1 > c) | ||
5743 | c1 = c; | ||
5744 | |||
5745 | if (c1 <= 0) { | ||
5746 | ISR_PDEBUG | ||
5747 | ("me4000_ai_isr():Work done or buffer full\n"); | ||
5748 | break; | ||
5749 | } | ||
5750 | |||
5751 | insw(ai_context->data_reg, | ||
5752 | ai_context->circ_buf.buf + | ||
5753 | ai_context->circ_buf.head, c1); | ||
5754 | ai_context->circ_buf.head = | ||
5755 | (ai_context->circ_buf.head + | ||
5756 | c1) & (ME4000_AI_BUFFER_COUNT - 1); | ||
5757 | c -= c1; | ||
5758 | } | ||
5759 | } else { | ||
5760 | ISR_PDEBUG | ||
5761 | ("me4000_ai_isr():Multiple data block available\n"); | ||
5762 | |||
5763 | /* Read status register to find out what happened */ | ||
5764 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5765 | |||
5766 | if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && | ||
5767 | !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) | ||
5768 | && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
5769 | ISR_PDEBUG | ||
5770 | ("me4000_ai_isr():Fifo full\n"); | ||
5771 | c = ME4000_AI_FIFO_COUNT; | ||
5772 | |||
5773 | /* FIFO overflow, so stop conversion */ | ||
5774 | spin_lock(&ai_context->int_lock); | ||
5775 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5776 | tmp |= | ||
5777 | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
5778 | outl(tmp, ai_context->ctrl_reg); | ||
5779 | spin_unlock(&ai_context->int_lock); | ||
5780 | |||
5781 | while (1) { | ||
5782 | c1 = me4000_space_to_end | ||
5783 | (ai_context->circ_buf, | ||
5784 | ME4000_AI_BUFFER_COUNT); | ||
5785 | ISR_PDEBUG | ||
5786 | ("me4000_ai_isr():Space to end = %d\n", | ||
5787 | c1); | ||
5788 | if (c1 > c) | ||
5789 | c1 = c; | ||
5790 | |||
5791 | if (c1 <= 0) { | ||
5792 | ISR_PDEBUG | ||
5793 | ("me4000_ai_isr():Work done or buffer full\n"); | ||
5794 | break; | ||
5795 | } | ||
5796 | |||
5797 | insw(ai_context->data_reg, | ||
5798 | ai_context->circ_buf.buf + | ||
5799 | ai_context->circ_buf.head, | ||
5800 | c1); | ||
5801 | ai_context->circ_buf.head = | ||
5802 | (ai_context->circ_buf.head + | ||
5803 | c1) & | ||
5804 | (ME4000_AI_BUFFER_COUNT - | ||
5805 | 1); | ||
5806 | c -= c1; | ||
5807 | } | ||
5808 | } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) | ||
5809 | && !(tmp & | ||
5810 | ME4000_AI_STATUS_BIT_HF_DATA) | ||
5811 | && (tmp & | ||
5812 | ME4000_AI_STATUS_BIT_EF_DATA)) { | ||
5813 | ISR_PDEBUG | ||
5814 | ("me4000_ai_isr():Fifo half full\n"); | ||
5815 | c = ME4000_AI_FIFO_COUNT / 2; | ||
5816 | |||
5817 | while (1) { | ||
5818 | c1 = me4000_space_to_end | ||
5819 | (ai_context->circ_buf, | ||
5820 | ME4000_AI_BUFFER_COUNT); | ||
5821 | ISR_PDEBUG | ||
5822 | ("me4000_ai_isr():Space to end = %d\n", | ||
5823 | c1); | ||
5824 | if (c1 > c) | ||
5825 | c1 = c; | ||
5826 | |||
5827 | if (c1 <= 0) { | ||
5828 | ISR_PDEBUG | ||
5829 | ("me4000_ai_isr():Work done or buffer full\n"); | ||
5830 | break; | ||
5831 | } | ||
5832 | |||
5833 | insw(ai_context->data_reg, | ||
5834 | ai_context->circ_buf.buf + | ||
5835 | ai_context->circ_buf.head, | ||
5836 | c1); | ||
5837 | ai_context->circ_buf.head = | ||
5838 | (ai_context->circ_buf.head + | ||
5839 | c1) & | ||
5840 | (ME4000_AI_BUFFER_COUNT - | ||
5841 | 1); | ||
5842 | c -= c1; | ||
5843 | } | ||
5844 | } else { | ||
5845 | /* Poll data until fifo empty */ | ||
5846 | for (i = 0; | ||
5847 | (i < ME4000_AI_FIFO_COUNT / 2) | ||
5848 | && (inl(ai_context->ctrl_reg) & | ||
5849 | ME4000_AI_STATUS_BIT_EF_DATA); | ||
5850 | i++) { | ||
5851 | if (me4000_space_to_end | ||
5852 | (ai_context->circ_buf, | ||
5853 | ME4000_AI_BUFFER_COUNT)) { | ||
5854 | *(ai_context->circ_buf. | ||
5855 | buf + | ||
5856 | ai_context->circ_buf. | ||
5857 | head) = | ||
5858 | inw(ai_context->data_reg); | ||
5859 | ai_context->circ_buf. | ||
5860 | head = | ||
5861 | (ai_context-> | ||
5862 | circ_buf.head + | ||
5863 | 1) & | ||
5864 | (ME4000_AI_BUFFER_COUNT | ||
5865 | - 1); | ||
5866 | } else | ||
5867 | break; | ||
5868 | } | ||
5869 | ISR_PDEBUG | ||
5870 | ("me4000_ai_isr():%d values read\n", | ||
5871 | i); | ||
5872 | } | ||
5873 | } | ||
5874 | } | ||
5875 | |||
5876 | /* Work is done, so reset the interrupt */ | ||
5877 | ISR_PDEBUG | ||
5878 | ("me4000_ai_isr():reset interrupt from sample counter\n"); | ||
5879 | spin_lock(&ai_context->int_lock); | ||
5880 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5881 | tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET; | ||
5882 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
5883 | tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET; | ||
5884 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
5885 | spin_unlock(&ai_context->int_lock); | ||
5886 | } | ||
5887 | |||
5888 | /* Values are now available, so wake up waiting process */ | ||
5889 | if (me4000_buf_count(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) { | ||
5890 | ISR_PDEBUG("me4000_ai_isr():Wake up waiting process\n"); | ||
5891 | wake_up_interruptible(&(ai_context->wait_queue)); | ||
5892 | } | ||
5893 | |||
5894 | /* If there is no space left in the buffer, disable interrupts */ | ||
5895 | spin_lock(&ai_context->int_lock); | ||
5896 | if (!me4000_buf_space(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) { | ||
5897 | ISR_PDEBUG | ||
5898 | ("me4000_ai_isr():Disable Interrupt because no space left in buffer\n"); | ||
5899 | tmp = me4000_inl(ai_context->ctrl_reg); | ||
5900 | tmp &= | ||
5901 | ~(ME4000_AI_CTRL_BIT_SC_IRQ | ME4000_AI_CTRL_BIT_HF_IRQ | | ||
5902 | ME4000_AI_CTRL_BIT_LE_IRQ); | ||
5903 | me4000_outl(tmp, ai_context->ctrl_reg); | ||
5904 | } | ||
5905 | spin_unlock(&ai_context->int_lock); | ||
5906 | |||
5907 | #ifdef ME4000_ISR_DEBUG | ||
5908 | rdtscl(after); | ||
5909 | printk(KERN_ERR "ME4000:me4000_ai_isr():Time lapse = %lu\n", | ||
5910 | after - before); | ||
5911 | #endif | ||
5912 | |||
5913 | return IRQ_HANDLED; | ||
5914 | } | ||
5915 | |||
5916 | static irqreturn_t me4000_ext_int_isr(int irq, void *dev_id) | ||
5917 | { | ||
5918 | struct me4000_ext_int_context *ext_int_context; | ||
5919 | unsigned long tmp; | ||
5920 | |||
5921 | ISR_PDEBUG("me4000_ext_int_isr() is executed\n"); | ||
5922 | |||
5923 | ext_int_context = dev_id; | ||
5924 | |||
5925 | /* Check if irq number is right */ | ||
5926 | if (irq != ext_int_context->irq) { | ||
5927 | ISR_PDEBUG("me4000_ext_int_isr():incorrect interrupt num: %d\n", | ||
5928 | irq); | ||
5929 | return IRQ_NONE; | ||
5930 | } | ||
5931 | |||
5932 | if (me4000_inl(ext_int_context->irq_status_reg) & | ||
5933 | ME4000_IRQ_STATUS_BIT_EX) { | ||
5934 | ISR_PDEBUG("me4000_ext_int_isr():External interrupt occured\n"); | ||
5935 | tmp = me4000_inl(ext_int_context->ctrl_reg); | ||
5936 | tmp |= ME4000_AI_CTRL_BIT_EX_IRQ_RESET; | ||
5937 | me4000_outl(tmp, ext_int_context->ctrl_reg); | ||
5938 | tmp &= ~ME4000_AI_CTRL_BIT_EX_IRQ_RESET; | ||
5939 | me4000_outl(tmp, ext_int_context->ctrl_reg); | ||
5940 | |||
5941 | ext_int_context->int_count++; | ||
5942 | |||
5943 | if (ext_int_context->fasync_ptr) { | ||
5944 | ISR_PDEBUG | ||
5945 | ("me2600_ext_int_isr():Send signal to process\n"); | ||
5946 | kill_fasync(&ext_int_context->fasync_ptr, SIGIO, | ||
5947 | POLL_IN); | ||
5948 | } | ||
5949 | } | ||
5950 | |||
5951 | return IRQ_HANDLED; | ||
5952 | } | ||
5953 | |||
5954 | static void __exit me4000_module_exit(void) | ||
5955 | { | ||
5956 | struct me4000_info *board_info; | ||
5957 | |||
5958 | CALL_PDEBUG("cleanup_module() is executed\n"); | ||
5959 | |||
5960 | unregister_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME); | ||
5961 | |||
5962 | unregister_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME); | ||
5963 | |||
5964 | unregister_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME); | ||
5965 | |||
5966 | unregister_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME); | ||
5967 | |||
5968 | unregister_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME); | ||
5969 | |||
5970 | remove_proc_entry("me4000", NULL); | ||
5971 | |||
5972 | pci_unregister_driver(&me4000_driver); | ||
5973 | |||
5974 | /* Reset the boards */ | ||
5975 | list_for_each_entry(board_info, &me4000_board_info_list, list) { | ||
5976 | me4000_reset_board(board_info); | ||
5977 | } | ||
5978 | |||
5979 | clear_board_info_list(); | ||
5980 | } | ||
5981 | |||
5982 | module_exit(me4000_module_exit); | ||
5983 | |||
5984 | static int me4000_read_procmem(char *buf, char **start, off_t offset, int count, | ||
5985 | int *eof, void *data) | ||
5986 | { | ||
5987 | int len = 0; | ||
5988 | int limit = count - 1000; | ||
5989 | struct me4000_info *board_info; | ||
5990 | |||
5991 | len += sprintf(buf + len, "\nME4000 DRIVER VERSION %X.%X.%X\n\n", | ||
5992 | (ME4000_DRIVER_VERSION & 0xFF0000) >> 16, | ||
5993 | (ME4000_DRIVER_VERSION & 0xFF00) >> 8, | ||
5994 | (ME4000_DRIVER_VERSION & 0xFF)); | ||
5995 | |||
5996 | /* Search for the board context */ | ||
5997 | list_for_each_entry(board_info, &me4000_board_info_list, list) { | ||
5998 | len += | ||
5999 | sprintf(buf + len, "Board number %d:\n", | ||
6000 | board_info->board_count); | ||
6001 | len += sprintf(buf + len, "---------------\n"); | ||
6002 | len += | ||
6003 | sprintf(buf + len, "PLX base register = 0x%lX\n", | ||
6004 | board_info->plx_regbase); | ||
6005 | len += | ||
6006 | sprintf(buf + len, "PLX base register size = 0x%X\n", | ||
6007 | (unsigned int)board_info->plx_regbase_size); | ||
6008 | len += | ||
6009 | sprintf(buf + len, "ME4000 base register = 0x%X\n", | ||
6010 | (unsigned int)board_info->me4000_regbase); | ||
6011 | len += | ||
6012 | sprintf(buf + len, "ME4000 base register size = 0x%X\n", | ||
6013 | (unsigned int)board_info->me4000_regbase_size); | ||
6014 | len += | ||
6015 | sprintf(buf + len, "Serial number = 0x%X\n", | ||
6016 | board_info->serial_no); | ||
6017 | len += | ||
6018 | sprintf(buf + len, "Hardware revision = 0x%X\n", | ||
6019 | board_info->hw_revision); | ||
6020 | len += | ||
6021 | sprintf(buf + len, "Vendor id = 0x%X\n", | ||
6022 | board_info->vendor_id); | ||
6023 | len += | ||
6024 | sprintf(buf + len, "Device id = 0x%X\n", | ||
6025 | board_info->device_id); | ||
6026 | len += | ||
6027 | sprintf(buf + len, "PCI bus number = %d\n", | ||
6028 | board_info->pci_bus_no); | ||
6029 | len += | ||
6030 | sprintf(buf + len, "PCI device number = %d\n", | ||
6031 | board_info->pci_dev_no); | ||
6032 | len += | ||
6033 | sprintf(buf + len, "PCI function number = %d\n", | ||
6034 | board_info->pci_func_no); | ||
6035 | len += sprintf(buf + len, "IRQ = %u\n", board_info->irq); | ||
6036 | len += | ||
6037 | sprintf(buf + len, | ||
6038 | "Count of interrupts since module was loaded = %d\n", | ||
6039 | board_info->irq_count); | ||
6040 | |||
6041 | len += | ||
6042 | sprintf(buf + len, "Count of analog outputs = %d\n", | ||
6043 | board_info->board_p->ao.count); | ||
6044 | len += | ||
6045 | sprintf(buf + len, "Count of analog output fifos = %d\n", | ||
6046 | board_info->board_p->ao.fifo_count); | ||
6047 | |||
6048 | len += | ||
6049 | sprintf(buf + len, "Count of analog inputs = %d\n", | ||
6050 | board_info->board_p->ai.count); | ||
6051 | len += | ||
6052 | sprintf(buf + len, | ||
6053 | "Count of sample and hold devices for analog input = %d\n", | ||
6054 | board_info->board_p->ai.sh_count); | ||
6055 | len += | ||
6056 | sprintf(buf + len, | ||
6057 | "Analog external trigger available for analog input = %d\n", | ||
6058 | board_info->board_p->ai.ex_trig_analog); | ||
6059 | |||
6060 | len += | ||
6061 | sprintf(buf + len, "Count of digital ports = %d\n", | ||
6062 | board_info->board_p->dio.count); | ||
6063 | |||
6064 | len += | ||
6065 | sprintf(buf + len, "Count of counter devices = %d\n", | ||
6066 | board_info->board_p->cnt.count); | ||
6067 | len += | ||
6068 | sprintf(buf + len, "AI control register = 0x%08X\n", | ||
6069 | inl(board_info->me4000_regbase + | ||
6070 | ME4000_AI_CTRL_REG)); | ||
6071 | |||
6072 | len += sprintf(buf + len, "AO 0 control register = 0x%08X\n", | ||
6073 | inl(board_info->me4000_regbase + | ||
6074 | ME4000_AO_00_CTRL_REG)); | ||
6075 | len += | ||
6076 | sprintf(buf + len, "AO 0 status register = 0x%08X\n", | ||
6077 | inl(board_info->me4000_regbase + | ||
6078 | ME4000_AO_00_STATUS_REG)); | ||
6079 | len += | ||
6080 | sprintf(buf + len, "AO 1 control register = 0x%08X\n", | ||
6081 | inl(board_info->me4000_regbase + | ||
6082 | ME4000_AO_01_CTRL_REG)); | ||
6083 | len += | ||
6084 | sprintf(buf + len, "AO 1 status register = 0x%08X\n", | ||
6085 | inl(board_info->me4000_regbase + | ||
6086 | ME4000_AO_01_STATUS_REG)); | ||
6087 | len += | ||
6088 | sprintf(buf + len, "AO 2 control register = 0x%08X\n", | ||
6089 | inl(board_info->me4000_regbase + | ||
6090 | ME4000_AO_02_CTRL_REG)); | ||
6091 | len += | ||
6092 | sprintf(buf + len, "AO 2 status register = 0x%08X\n", | ||
6093 | inl(board_info->me4000_regbase + | ||
6094 | ME4000_AO_02_STATUS_REG)); | ||
6095 | len += | ||
6096 | sprintf(buf + len, "AO 3 control register = 0x%08X\n", | ||
6097 | inl(board_info->me4000_regbase + | ||
6098 | ME4000_AO_03_CTRL_REG)); | ||
6099 | len += | ||
6100 | sprintf(buf + len, "AO 3 status register = 0x%08X\n", | ||
6101 | inl(board_info->me4000_regbase + | ||
6102 | ME4000_AO_03_STATUS_REG)); | ||
6103 | if (len >= limit) | ||
6104 | break; | ||
6105 | } | ||
6106 | |||
6107 | *eof = 1; | ||
6108 | return len; | ||
6109 | } | ||