Staging: add cowloop driver
[safe/jmp/linux-2.6] / drivers / staging / comedi / comedi_fops.c
1 /*
2     comedi/comedi_fops.c
3     comedi kernel module
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23
24 #undef DEBUG
25
26 #define __NO_VERSION__
27 #include "comedi_fops.h"
28 #include "comedi_compat32.h"
29
30 #include <linux/module.h>
31 #include <linux/errno.h>
32 #include <linux/kernel.h>
33 #include <linux/sched.h>
34 #include <linux/fcntl.h>
35 #include <linux/delay.h>
36 #include <linux/ioport.h>
37 #include <linux/mm.h>
38 #include <linux/slab.h>
39 #include <linux/kmod.h>
40 #include <linux/poll.h>
41 #include <linux/init.h>
42 #include <linux/device.h>
43 #include <linux/vmalloc.h>
44 #include <linux/fs.h>
45 #include "comedidev.h"
46 #include <linux/cdev.h>
47 #include <linux/stat.h>
48
49 #include <linux/io.h>
50 #include <linux/uaccess.h>
51
52 /* #include "kvmem.h" */
53
54 MODULE_AUTHOR("http://www.comedi.org");
55 MODULE_DESCRIPTION("Comedi core module");
56 MODULE_LICENSE("GPL");
57
58 #ifdef CONFIG_COMEDI_DEBUG
59 int comedi_debug;
60 module_param(comedi_debug, int, 0644);
61 #endif
62
63 int comedi_autoconfig = 1;
64 module_param(comedi_autoconfig, bool, 0444);
65
66 int comedi_num_legacy_minors = 0;
67 module_param(comedi_num_legacy_minors, int, 0444);
68
69 static DEFINE_SPINLOCK(comedi_file_info_table_lock);
70 static struct comedi_device_file_info
71 *comedi_file_info_table[COMEDI_NUM_MINORS];
72
73 static int do_devconfig_ioctl(struct comedi_device *dev,
74                               struct comedi_devconfig *arg);
75 static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
76 static int do_devinfo_ioctl(struct comedi_device *dev,
77                             struct comedi_devinfo *arg, struct file *file);
78 static int do_subdinfo_ioctl(struct comedi_device *dev,
79                              struct comedi_subdinfo *arg, void *file);
80 static int do_chaninfo_ioctl(struct comedi_device *dev,
81                              struct comedi_chaninfo *arg);
82 static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg);
83 static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file);
84 static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
85                          void *file);
86 static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg,
87                            void *file);
88 static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
89                            void *file);
90 static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file);
91 static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file);
92 static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file);
93 static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd,
94                          void *file);
95
96 extern void do_become_nonbusy(struct comedi_device *dev,
97                               struct comedi_subdevice *s);
98 static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
99
100 static int comedi_fasync(int fd, struct file *file, int on);
101
102 static int is_device_busy(struct comedi_device *dev);
103 static int resize_async_buffer(struct comedi_device *dev,
104                                struct comedi_subdevice *s,
105                                struct comedi_async *async, unsigned new_size);
106
107 /* declarations for sysfs attribute files */
108 static struct device_attribute dev_attr_max_read_buffer_kb;
109 static struct device_attribute dev_attr_read_buffer_kb;
110 static struct device_attribute dev_attr_max_write_buffer_kb;
111 static struct device_attribute dev_attr_write_buffer_kb;
112
113 #ifdef HAVE_UNLOCKED_IOCTL
114 static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
115                                   unsigned long arg)
116 #else
117 static int comedi_ioctl(struct inode *inode, struct file *file,
118                         unsigned int cmd, unsigned long arg)
119 #endif
120 {
121         const unsigned minor = iminor(file->f_dentry->d_inode);
122         struct comedi_device_file_info *dev_file_info =
123             comedi_get_device_file_info(minor);
124         struct comedi_device *dev;
125         int rc;
126
127         if (dev_file_info == NULL || dev_file_info->device == NULL)
128                 return -ENODEV;
129         dev = dev_file_info->device;
130
131         mutex_lock(&dev->mutex);
132
133         /* Device config is special, because it must work on
134          * an unconfigured device. */
135         if (cmd == COMEDI_DEVCONFIG) {
136                 rc = do_devconfig_ioctl(dev, (void *)arg);
137                 goto done;
138         }
139
140         if (!dev->attached) {
141                 DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor);
142                 rc = -ENODEV;
143                 goto done;
144         }
145
146         switch (cmd) {
147         case COMEDI_BUFCONFIG:
148                 rc = do_bufconfig_ioctl(dev, (void *)arg);
149                 break;
150         case COMEDI_DEVINFO:
151                 rc = do_devinfo_ioctl(dev, (void *)arg, file);
152                 break;
153         case COMEDI_SUBDINFO:
154                 rc = do_subdinfo_ioctl(dev, (void *)arg, file);
155                 break;
156         case COMEDI_CHANINFO:
157                 rc = do_chaninfo_ioctl(dev, (void *)arg);
158                 break;
159         case COMEDI_RANGEINFO:
160                 rc = do_rangeinfo_ioctl(dev, (void *)arg);
161                 break;
162         case COMEDI_BUFINFO:
163                 rc = do_bufinfo_ioctl(dev, (void *)arg);
164                 break;
165         case COMEDI_LOCK:
166                 rc = do_lock_ioctl(dev, arg, file);
167                 break;
168         case COMEDI_UNLOCK:
169                 rc = do_unlock_ioctl(dev, arg, file);
170                 break;
171         case COMEDI_CANCEL:
172                 rc = do_cancel_ioctl(dev, arg, file);
173                 break;
174         case COMEDI_CMD:
175                 rc = do_cmd_ioctl(dev, (void *)arg, file);
176                 break;
177         case COMEDI_CMDTEST:
178                 rc = do_cmdtest_ioctl(dev, (void *)arg, file);
179                 break;
180         case COMEDI_INSNLIST:
181                 rc = do_insnlist_ioctl(dev, (void *)arg, file);
182                 break;
183         case COMEDI_INSN:
184                 rc = do_insn_ioctl(dev, (void *)arg, file);
185                 break;
186         case COMEDI_POLL:
187                 rc = do_poll_ioctl(dev, arg, file);
188                 break;
189         default:
190                 rc = -ENOTTY;
191                 break;
192         }
193
194 done:
195         mutex_unlock(&dev->mutex);
196         return rc;
197 }
198
199 /*
200         COMEDI_DEVCONFIG
201         device config ioctl
202
203         arg:
204                 pointer to devconfig structure
205
206         reads:
207                 devconfig structure at arg
208
209         writes:
210                 none
211 */
212 static int do_devconfig_ioctl(struct comedi_device *dev,
213                               struct comedi_devconfig *arg)
214 {
215         struct comedi_devconfig it;
216         int ret;
217         unsigned char *aux_data = NULL;
218         int aux_len;
219
220         if (!capable(CAP_SYS_ADMIN))
221                 return -EPERM;
222
223         if (arg == NULL) {
224                 if (is_device_busy(dev))
225                         return -EBUSY;
226                 if (dev->attached) {
227                         struct module *driver_module = dev->driver->module;
228                         comedi_device_detach(dev);
229                         module_put(driver_module);
230                 }
231                 return 0;
232         }
233
234         if (copy_from_user(&it, arg, sizeof(struct comedi_devconfig)))
235                 return -EFAULT;
236
237         it.board_name[COMEDI_NAMELEN - 1] = 0;
238
239         if (comedi_aux_data(it.options, 0) &&
240             it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
241                 int bit_shift;
242                 aux_len = it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
243                 if (aux_len < 0)
244                         return -EFAULT;
245
246                 aux_data = vmalloc(aux_len);
247                 if (!aux_data)
248                         return -ENOMEM;
249
250                 if (copy_from_user(aux_data,
251                                    comedi_aux_data(it.options, 0), aux_len)) {
252                         vfree(aux_data);
253                         return -EFAULT;
254                 }
255                 it.options[COMEDI_DEVCONF_AUX_DATA_LO] =
256                     (unsigned long)aux_data;
257                 if (sizeof(void *) > sizeof(int)) {
258                         bit_shift = sizeof(int) * 8;
259                         it.options[COMEDI_DEVCONF_AUX_DATA_HI] =
260                             ((unsigned long)aux_data) >> bit_shift;
261                 } else
262                         it.options[COMEDI_DEVCONF_AUX_DATA_HI] = 0;
263         }
264
265         ret = comedi_device_attach(dev, &it);
266         if (ret == 0) {
267                 if (!try_module_get(dev->driver->module)) {
268                         comedi_device_detach(dev);
269                         return -ENOSYS;
270                 }
271         }
272
273         if (aux_data)
274                 vfree(aux_data);
275
276         return ret;
277 }
278
279 /*
280         COMEDI_BUFCONFIG
281         buffer configuration ioctl
282
283         arg:
284                 pointer to bufconfig structure
285
286         reads:
287                 bufconfig at arg
288
289         writes:
290                 modified bufconfig at arg
291
292 */
293 static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
294 {
295         struct comedi_bufconfig bc;
296         struct comedi_async *async;
297         struct comedi_subdevice *s;
298         int retval = 0;
299
300         if (copy_from_user(&bc, arg, sizeof(struct comedi_bufconfig)))
301                 return -EFAULT;
302
303         if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0)
304                 return -EINVAL;
305
306         s = dev->subdevices + bc.subdevice;
307         async = s->async;
308
309         if (!async) {
310                 DPRINTK("subdevice does not have async capability\n");
311                 bc.size = 0;
312                 bc.maximum_size = 0;
313                 goto copyback;
314         }
315
316         if (bc.maximum_size) {
317                 if (!capable(CAP_SYS_ADMIN))
318                         return -EPERM;
319
320                 async->max_bufsize = bc.maximum_size;
321         }
322
323         if (bc.size) {
324                 retval = resize_async_buffer(dev, s, async, bc.size);
325                 if (retval < 0)
326                         return retval;
327         }
328
329         bc.size = async->prealloc_bufsz;
330         bc.maximum_size = async->max_bufsize;
331
332 copyback:
333         if (copy_to_user(arg, &bc, sizeof(struct comedi_bufconfig)))
334                 return -EFAULT;
335
336         return 0;
337 }
338
339 /*
340         COMEDI_DEVINFO
341         device info ioctl
342
343         arg:
344                 pointer to devinfo structure
345
346         reads:
347                 none
348
349         writes:
350                 devinfo structure
351
352 */
353 static int do_devinfo_ioctl(struct comedi_device *dev,
354                             struct comedi_devinfo *arg, struct file *file)
355 {
356         struct comedi_devinfo devinfo;
357         const unsigned minor = iminor(file->f_dentry->d_inode);
358         struct comedi_device_file_info *dev_file_info =
359             comedi_get_device_file_info(minor);
360         struct comedi_subdevice *read_subdev =
361             comedi_get_read_subdevice(dev_file_info);
362         struct comedi_subdevice *write_subdev =
363             comedi_get_write_subdevice(dev_file_info);
364
365         memset(&devinfo, 0, sizeof(devinfo));
366
367         /* fill devinfo structure */
368         devinfo.version_code = COMEDI_VERSION_CODE;
369         devinfo.n_subdevs = dev->n_subdevices;
370         memcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
371         memcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
372
373         if (read_subdev)
374                 devinfo.read_subdevice = read_subdev - dev->subdevices;
375         else
376                 devinfo.read_subdevice = -1;
377
378         if (write_subdev)
379                 devinfo.write_subdevice = write_subdev - dev->subdevices;
380         else
381                 devinfo.write_subdevice = -1;
382
383         if (copy_to_user(arg, &devinfo, sizeof(struct comedi_devinfo)))
384                 return -EFAULT;
385
386         return 0;
387 }
388
389 /*
390         COMEDI_SUBDINFO
391         subdevice info ioctl
392
393         arg:
394                 pointer to array of subdevice info structures
395
396         reads:
397                 none
398
399         writes:
400                 array of subdevice info structures at arg
401
402 */
403 static int do_subdinfo_ioctl(struct comedi_device *dev,
404                              struct comedi_subdinfo *arg, void *file)
405 {
406         int ret, i;
407         struct comedi_subdinfo *tmp, *us;
408         struct comedi_subdevice *s;
409
410         tmp =
411             kcalloc(dev->n_subdevices, sizeof(struct comedi_subdinfo),
412                     GFP_KERNEL);
413         if (!tmp)
414                 return -ENOMEM;
415
416         /* fill subdinfo structs */
417         for (i = 0; i < dev->n_subdevices; i++) {
418                 s = dev->subdevices + i;
419                 us = tmp + i;
420
421                 us->type = s->type;
422                 us->n_chan = s->n_chan;
423                 us->subd_flags = s->subdev_flags;
424                 if (comedi_get_subdevice_runflags(s) & SRF_RUNNING)
425                         us->subd_flags |= SDF_RUNNING;
426 #define TIMER_nanosec 5         /* backwards compatibility */
427                 us->timer_type = TIMER_nanosec;
428                 us->len_chanlist = s->len_chanlist;
429                 us->maxdata = s->maxdata;
430                 if (s->range_table) {
431                         us->range_type =
432                             (i << 24) | (0 << 16) | (s->range_table->length);
433                 } else {
434                         us->range_type = 0;     /* XXX */
435                 }
436                 us->flags = s->flags;
437
438                 if (s->busy)
439                         us->subd_flags |= SDF_BUSY;
440                 if (s->busy == file)
441                         us->subd_flags |= SDF_BUSY_OWNER;
442                 if (s->lock)
443                         us->subd_flags |= SDF_LOCKED;
444                 if (s->lock == file)
445                         us->subd_flags |= SDF_LOCK_OWNER;
446                 if (!s->maxdata && s->maxdata_list)
447                         us->subd_flags |= SDF_MAXDATA;
448                 if (s->flaglist)
449                         us->subd_flags |= SDF_FLAGS;
450                 if (s->range_table_list)
451                         us->subd_flags |= SDF_RANGETYPE;
452                 if (s->do_cmd)
453                         us->subd_flags |= SDF_CMD;
454
455                 if (s->insn_bits != &insn_inval)
456                         us->insn_bits_support = COMEDI_SUPPORTED;
457                 else
458                         us->insn_bits_support = COMEDI_UNSUPPORTED;
459
460                 us->settling_time_0 = s->settling_time_0;
461         }
462
463         ret = copy_to_user(arg, tmp,
464                            dev->n_subdevices * sizeof(struct comedi_subdinfo));
465
466         kfree(tmp);
467
468         return ret ? -EFAULT : 0;
469 }
470
471 /*
472         COMEDI_CHANINFO
473         subdevice info ioctl
474
475         arg:
476                 pointer to chaninfo structure
477
478         reads:
479                 chaninfo structure at arg
480
481         writes:
482                 arrays at elements of chaninfo structure
483
484 */
485 static int do_chaninfo_ioctl(struct comedi_device *dev,
486                              struct comedi_chaninfo *arg)
487 {
488         struct comedi_subdevice *s;
489         struct comedi_chaninfo it;
490
491         if (copy_from_user(&it, arg, sizeof(struct comedi_chaninfo)))
492                 return -EFAULT;
493
494         if (it.subdev >= dev->n_subdevices)
495                 return -EINVAL;
496         s = dev->subdevices + it.subdev;
497
498         if (it.maxdata_list) {
499                 if (s->maxdata || !s->maxdata_list)
500                         return -EINVAL;
501                 if (copy_to_user(it.maxdata_list, s->maxdata_list,
502                                  s->n_chan * sizeof(unsigned int)))
503                         return -EFAULT;
504         }
505
506         if (it.flaglist) {
507                 if (!s->flaglist)
508                         return -EINVAL;
509                 if (copy_to_user(it.flaglist, s->flaglist,
510                                  s->n_chan * sizeof(unsigned int)))
511                         return -EFAULT;
512         }
513
514         if (it.rangelist) {
515                 int i;
516
517                 if (!s->range_table_list)
518                         return -EINVAL;
519                 for (i = 0; i < s->n_chan; i++) {
520                         int x;
521
522                         x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) |
523                             (s->range_table_list[i]->length);
524                         put_user(x, it.rangelist + i);
525                 }
526 #if 0
527                 if (copy_to_user(it.rangelist, s->range_type_list,
528                                  s->n_chan * sizeof(unsigned int)))
529                         return -EFAULT;
530 #endif
531         }
532
533         return 0;
534 }
535
536  /*
537     COMEDI_BUFINFO
538     buffer information ioctl
539
540     arg:
541     pointer to bufinfo structure
542
543     reads:
544     bufinfo at arg
545
546     writes:
547     modified bufinfo at arg
548
549   */
550 static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
551 {
552         struct comedi_bufinfo bi;
553         struct comedi_subdevice *s;
554         struct comedi_async *async;
555
556         if (copy_from_user(&bi, arg, sizeof(struct comedi_bufinfo)))
557                 return -EFAULT;
558
559         if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
560                 return -EINVAL;
561
562         s = dev->subdevices + bi.subdevice;
563         async = s->async;
564
565         if (!async) {
566                 DPRINTK("subdevice does not have async capability\n");
567                 bi.buf_write_ptr = 0;
568                 bi.buf_read_ptr = 0;
569                 bi.buf_write_count = 0;
570                 bi.buf_read_count = 0;
571                 goto copyback;
572         }
573
574         if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
575                 bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
576                 comedi_buf_read_free(async, bi.bytes_read);
577
578                 if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR |
579                                                           SRF_RUNNING))
580                     && async->buf_write_count == async->buf_read_count) {
581                         do_become_nonbusy(dev, s);
582                 }
583         }
584
585         if (bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)) {
586                 bi.bytes_written =
587                     comedi_buf_write_alloc(async, bi.bytes_written);
588                 comedi_buf_write_free(async, bi.bytes_written);
589         }
590
591         bi.buf_write_count = async->buf_write_count;
592         bi.buf_write_ptr = async->buf_write_ptr;
593         bi.buf_read_count = async->buf_read_count;
594         bi.buf_read_ptr = async->buf_read_ptr;
595
596 copyback:
597         if (copy_to_user(arg, &bi, sizeof(struct comedi_bufinfo)))
598                 return -EFAULT;
599
600         return 0;
601 }
602
603 static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
604                       unsigned int *data, void *file);
605 /*
606  *      COMEDI_INSNLIST
607  *      synchronous instructions
608  *
609  *      arg:
610  *              pointer to sync cmd structure
611  *
612  *      reads:
613  *              sync cmd struct at arg
614  *              instruction list
615  *              data (for writes)
616  *
617  *      writes:
618  *              data (for reads)
619  */
620 /* arbitrary limits */
621 #define MAX_SAMPLES 256
622 static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
623 {
624         struct comedi_insnlist insnlist;
625         struct comedi_insn *insns = NULL;
626         unsigned int *data = NULL;
627         int i = 0;
628         int ret = 0;
629
630         if (copy_from_user(&insnlist, arg, sizeof(struct comedi_insnlist)))
631                 return -EFAULT;
632
633         data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
634         if (!data) {
635                 DPRINTK("kmalloc failed\n");
636                 ret = -ENOMEM;
637                 goto error;
638         }
639
640         insns =
641             kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL);
642         if (!insns) {
643                 DPRINTK("kmalloc failed\n");
644                 ret = -ENOMEM;
645                 goto error;
646         }
647
648         if (copy_from_user(insns, insnlist.insns,
649                            sizeof(struct comedi_insn) * insnlist.n_insns)) {
650                 DPRINTK("copy_from_user failed\n");
651                 ret = -EFAULT;
652                 goto error;
653         }
654
655         for (i = 0; i < insnlist.n_insns; i++) {
656                 if (insns[i].n > MAX_SAMPLES) {
657                         DPRINTK("number of samples too large\n");
658                         ret = -EINVAL;
659                         goto error;
660                 }
661                 if (insns[i].insn & INSN_MASK_WRITE) {
662                         if (copy_from_user(data, insns[i].data,
663                                            insns[i].n * sizeof(unsigned int))) {
664                                 DPRINTK("copy_from_user failed\n");
665                                 ret = -EFAULT;
666                                 goto error;
667                         }
668                 }
669                 ret = parse_insn(dev, insns + i, data, file);
670                 if (ret < 0)
671                         goto error;
672                 if (insns[i].insn & INSN_MASK_READ) {
673                         if (copy_to_user(insns[i].data, data,
674                                          insns[i].n * sizeof(unsigned int))) {
675                                 DPRINTK("copy_to_user failed\n");
676                                 ret = -EFAULT;
677                                 goto error;
678                         }
679                 }
680                 if (need_resched())
681                         schedule();
682         }
683
684 error:
685         kfree(insns);
686         kfree(data);
687
688         if (ret < 0)
689                 return ret;
690         return i;
691 }
692
693 static int check_insn_config_length(struct comedi_insn *insn,
694                                     unsigned int *data)
695 {
696         if (insn->n < 1)
697                 return -EINVAL;
698
699         switch (data[0]) {
700         case INSN_CONFIG_DIO_OUTPUT:
701         case INSN_CONFIG_DIO_INPUT:
702         case INSN_CONFIG_DISARM:
703         case INSN_CONFIG_RESET:
704                 if (insn->n == 1)
705                         return 0;
706                 break;
707         case INSN_CONFIG_ARM:
708         case INSN_CONFIG_DIO_QUERY:
709         case INSN_CONFIG_BLOCK_SIZE:
710         case INSN_CONFIG_FILTER:
711         case INSN_CONFIG_SERIAL_CLOCK:
712         case INSN_CONFIG_BIDIRECTIONAL_DATA:
713         case INSN_CONFIG_ALT_SOURCE:
714         case INSN_CONFIG_SET_COUNTER_MODE:
715         case INSN_CONFIG_8254_READ_STATUS:
716         case INSN_CONFIG_SET_ROUTING:
717         case INSN_CONFIG_GET_ROUTING:
718         case INSN_CONFIG_GET_PWM_STATUS:
719         case INSN_CONFIG_PWM_SET_PERIOD:
720         case INSN_CONFIG_PWM_GET_PERIOD:
721                 if (insn->n == 2)
722                         return 0;
723                 break;
724         case INSN_CONFIG_SET_GATE_SRC:
725         case INSN_CONFIG_GET_GATE_SRC:
726         case INSN_CONFIG_SET_CLOCK_SRC:
727         case INSN_CONFIG_GET_CLOCK_SRC:
728         case INSN_CONFIG_SET_OTHER_SRC:
729         case INSN_CONFIG_GET_COUNTER_STATUS:
730         case INSN_CONFIG_PWM_SET_H_BRIDGE:
731         case INSN_CONFIG_PWM_GET_H_BRIDGE:
732         case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
733                 if (insn->n == 3)
734                         return 0;
735                 break;
736         case INSN_CONFIG_PWM_OUTPUT:
737         case INSN_CONFIG_ANALOG_TRIG:
738                 if (insn->n == 5)
739                         return 0;
740                 break;
741                 /* by default we allow the insn since we don't have checks for
742                  * all possible cases yet */
743         default:
744                 printk("comedi: no check for data length of config insn id "
745                        "%i is implemented.\n"
746                        " Add a check to %s in %s.\n"
747                        " Assuming n=%i is correct.\n", data[0], __func__,
748                        __FILE__, insn->n);
749                 return 0;
750                 break;
751         }
752         return -EINVAL;
753 }
754
755 static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
756                       unsigned int *data, void *file)
757 {
758         struct comedi_subdevice *s;
759         int ret = 0;
760         int i;
761
762         if (insn->insn & INSN_MASK_SPECIAL) {
763                 /* a non-subdevice instruction */
764
765                 switch (insn->insn) {
766                 case INSN_GTOD:
767                         {
768                                 struct timeval tv;
769
770                                 if (insn->n != 2) {
771                                         ret = -EINVAL;
772                                         break;
773                                 }
774
775                                 do_gettimeofday(&tv);
776                                 data[0] = tv.tv_sec;
777                                 data[1] = tv.tv_usec;
778                                 ret = 2;
779
780                                 break;
781                         }
782                 case INSN_WAIT:
783                         if (insn->n != 1 || data[0] >= 100000) {
784                                 ret = -EINVAL;
785                                 break;
786                         }
787                         udelay(data[0] / 1000);
788                         ret = 1;
789                         break;
790                 case INSN_INTTRIG:
791                         if (insn->n != 1) {
792                                 ret = -EINVAL;
793                                 break;
794                         }
795                         if (insn->subdev >= dev->n_subdevices) {
796                                 DPRINTK("%d not usable subdevice\n",
797                                         insn->subdev);
798                                 ret = -EINVAL;
799                                 break;
800                         }
801                         s = dev->subdevices + insn->subdev;
802                         if (!s->async) {
803                                 DPRINTK("no async\n");
804                                 ret = -EINVAL;
805                                 break;
806                         }
807                         if (!s->async->inttrig) {
808                                 DPRINTK("no inttrig\n");
809                                 ret = -EAGAIN;
810                                 break;
811                         }
812                         ret = s->async->inttrig(dev, s, insn->data[0]);
813                         if (ret >= 0)
814                                 ret = 1;
815                         break;
816                 default:
817                         DPRINTK("invalid insn\n");
818                         ret = -EINVAL;
819                         break;
820                 }
821         } else {
822                 /* a subdevice instruction */
823                 unsigned int maxdata;
824
825                 if (insn->subdev >= dev->n_subdevices) {
826                         DPRINTK("subdevice %d out of range\n", insn->subdev);
827                         ret = -EINVAL;
828                         goto out;
829                 }
830                 s = dev->subdevices + insn->subdev;
831
832                 if (s->type == COMEDI_SUBD_UNUSED) {
833                         DPRINTK("%d not usable subdevice\n", insn->subdev);
834                         ret = -EIO;
835                         goto out;
836                 }
837
838                 /* are we locked? (ioctl lock) */
839                 if (s->lock && s->lock != file) {
840                         DPRINTK("device locked\n");
841                         ret = -EACCES;
842                         goto out;
843                 }
844
845                 ret = check_chanlist(s, 1, &insn->chanspec);
846                 if (ret < 0) {
847                         ret = -EINVAL;
848                         DPRINTK("bad chanspec\n");
849                         goto out;
850                 }
851
852                 if (s->busy) {
853                         ret = -EBUSY;
854                         goto out;
855                 }
856                 /* This looks arbitrary.  It is. */
857                 s->busy = &parse_insn;
858                 switch (insn->insn) {
859                 case INSN_READ:
860                         ret = s->insn_read(dev, s, insn, data);
861                         break;
862                 case INSN_WRITE:
863                         maxdata = s->maxdata_list
864                             ? s->maxdata_list[CR_CHAN(insn->chanspec)]
865                             : s->maxdata;
866                         for (i = 0; i < insn->n; ++i) {
867                                 if (data[i] > maxdata) {
868                                         ret = -EINVAL;
869                                         DPRINTK("bad data value(s)\n");
870                                         break;
871                                 }
872                         }
873                         if (ret == 0)
874                                 ret = s->insn_write(dev, s, insn, data);
875                         break;
876                 case INSN_BITS:
877                         if (insn->n != 2) {
878                                 ret = -EINVAL;
879                                 break;
880                         }
881                         ret = s->insn_bits(dev, s, insn, data);
882                         break;
883                 case INSN_CONFIG:
884                         ret = check_insn_config_length(insn, data);
885                         if (ret)
886                                 break;
887                         ret = s->insn_config(dev, s, insn, data);
888                         break;
889                 default:
890                         ret = -EINVAL;
891                         break;
892                 }
893
894                 s->busy = NULL;
895         }
896
897 out:
898         return ret;
899 }
900
901 /*
902  *      COMEDI_INSN
903  *      synchronous instructions
904  *
905  *      arg:
906  *              pointer to insn
907  *
908  *      reads:
909  *              struct comedi_insn struct at arg
910  *              data (for writes)
911  *
912  *      writes:
913  *              data (for reads)
914  */
915 static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
916 {
917         struct comedi_insn insn;
918         unsigned int *data = NULL;
919         int ret = 0;
920
921         data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL);
922         if (!data) {
923                 ret = -ENOMEM;
924                 goto error;
925         }
926
927         if (copy_from_user(&insn, arg, sizeof(struct comedi_insn))) {
928                 ret = -EFAULT;
929                 goto error;
930         }
931
932         /* This is where the behavior of insn and insnlist deviate. */
933         if (insn.n > MAX_SAMPLES)
934                 insn.n = MAX_SAMPLES;
935         if (insn.insn & INSN_MASK_WRITE) {
936                 if (copy_from_user
937                     (data, insn.data, insn.n * sizeof(unsigned int))) {
938                         ret = -EFAULT;
939                         goto error;
940                 }
941         }
942         ret = parse_insn(dev, &insn, data, file);
943         if (ret < 0)
944                 goto error;
945         if (insn.insn & INSN_MASK_READ) {
946                 if (copy_to_user
947                     (insn.data, data, insn.n * sizeof(unsigned int))) {
948                         ret = -EFAULT;
949                         goto error;
950                 }
951         }
952         ret = insn.n;
953
954 error:
955         kfree(data);
956
957         return ret;
958 }
959
960 /*
961         COMEDI_CMD
962         command ioctl
963
964         arg:
965                 pointer to cmd structure
966
967         reads:
968                 cmd structure at arg
969                 channel/range list
970
971         writes:
972                 modified cmd structure at arg
973
974 */
975 static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
976 {
977         struct comedi_cmd user_cmd;
978         struct comedi_subdevice *s;
979         struct comedi_async *async;
980         int ret = 0;
981         unsigned int *chanlist_saver = NULL;
982
983         if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
984                 DPRINTK("bad cmd address\n");
985                 return -EFAULT;
986         }
987         /* save user's chanlist pointer so it can be restored later */
988         chanlist_saver = user_cmd.chanlist;
989
990         if (user_cmd.subdev >= dev->n_subdevices) {
991                 DPRINTK("%d no such subdevice\n", user_cmd.subdev);
992                 return -ENODEV;
993         }
994
995         s = dev->subdevices + user_cmd.subdev;
996         async = s->async;
997
998         if (s->type == COMEDI_SUBD_UNUSED) {
999                 DPRINTK("%d not valid subdevice\n", user_cmd.subdev);
1000                 return -EIO;
1001         }
1002
1003         if (!s->do_cmd || !s->do_cmdtest || !s->async) {
1004                 DPRINTK("subdevice %i does not support commands\n",
1005                         user_cmd.subdev);
1006                 return -EIO;
1007         }
1008
1009         /* are we locked? (ioctl lock) */
1010         if (s->lock && s->lock != file) {
1011                 DPRINTK("subdevice locked\n");
1012                 return -EACCES;
1013         }
1014
1015         /* are we busy? */
1016         if (s->busy) {
1017                 DPRINTK("subdevice busy\n");
1018                 return -EBUSY;
1019         }
1020         s->busy = file;
1021
1022         /* make sure channel/gain list isn't too long */
1023         if (user_cmd.chanlist_len > s->len_chanlist) {
1024                 DPRINTK("channel/gain list too long %u > %d\n",
1025                         user_cmd.chanlist_len, s->len_chanlist);
1026                 ret = -EINVAL;
1027                 goto cleanup;
1028         }
1029
1030         /* make sure channel/gain list isn't too short */
1031         if (user_cmd.chanlist_len < 1) {
1032                 DPRINTK("channel/gain list too short %u < 1\n",
1033                         user_cmd.chanlist_len);
1034                 ret = -EINVAL;
1035                 goto cleanup;
1036         }
1037
1038         kfree(async->cmd.chanlist);
1039         async->cmd = user_cmd;
1040         async->cmd.data = NULL;
1041         /* load channel/gain list */
1042         async->cmd.chanlist =
1043             kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
1044         if (!async->cmd.chanlist) {
1045                 DPRINTK("allocation failed\n");
1046                 ret = -ENOMEM;
1047                 goto cleanup;
1048         }
1049
1050         if (copy_from_user(async->cmd.chanlist, user_cmd.chanlist,
1051                            async->cmd.chanlist_len * sizeof(int))) {
1052                 DPRINTK("fault reading chanlist\n");
1053                 ret = -EFAULT;
1054                 goto cleanup;
1055         }
1056
1057         /* make sure each element in channel/gain list is valid */
1058         ret = check_chanlist(s, async->cmd.chanlist_len, async->cmd.chanlist);
1059         if (ret < 0) {
1060                 DPRINTK("bad chanlist\n");
1061                 goto cleanup;
1062         }
1063
1064         ret = s->do_cmdtest(dev, s, &async->cmd);
1065
1066         if (async->cmd.flags & TRIG_BOGUS || ret) {
1067                 DPRINTK("test returned %d\n", ret);
1068                 user_cmd = async->cmd;
1069                 /* restore chanlist pointer before copying back */
1070                 user_cmd.chanlist = chanlist_saver;
1071                 user_cmd.data = NULL;
1072                 if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
1073                         DPRINTK("fault writing cmd\n");
1074                         ret = -EFAULT;
1075                         goto cleanup;
1076                 }
1077                 ret = -EAGAIN;
1078                 goto cleanup;
1079         }
1080
1081         if (!async->prealloc_bufsz) {
1082                 ret = -ENOMEM;
1083                 DPRINTK("no buffer (?)\n");
1084                 goto cleanup;
1085         }
1086
1087         comedi_reset_async_buf(async);
1088
1089         async->cb_mask =
1090             COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR |
1091             COMEDI_CB_OVERFLOW;
1092         if (async->cmd.flags & TRIG_WAKE_EOS)
1093                 async->cb_mask |= COMEDI_CB_EOS;
1094
1095         comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
1096
1097         ret = s->do_cmd(dev, s);
1098         if (ret == 0)
1099                 return 0;
1100
1101 cleanup:
1102         do_become_nonbusy(dev, s);
1103
1104         return ret;
1105 }
1106
1107 /*
1108         COMEDI_CMDTEST
1109         command testing ioctl
1110
1111         arg:
1112                 pointer to cmd structure
1113
1114         reads:
1115                 cmd structure at arg
1116                 channel/range list
1117
1118         writes:
1119                 modified cmd structure at arg
1120
1121 */
1122 static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
1123 {
1124         struct comedi_cmd user_cmd;
1125         struct comedi_subdevice *s;
1126         int ret = 0;
1127         unsigned int *chanlist = NULL;
1128         unsigned int *chanlist_saver = NULL;
1129
1130         if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
1131                 DPRINTK("bad cmd address\n");
1132                 return -EFAULT;
1133         }
1134         /* save user's chanlist pointer so it can be restored later */
1135         chanlist_saver = user_cmd.chanlist;
1136
1137         if (user_cmd.subdev >= dev->n_subdevices) {
1138                 DPRINTK("%d no such subdevice\n", user_cmd.subdev);
1139                 return -ENODEV;
1140         }
1141
1142         s = dev->subdevices + user_cmd.subdev;
1143         if (s->type == COMEDI_SUBD_UNUSED) {
1144                 DPRINTK("%d not valid subdevice\n", user_cmd.subdev);
1145                 return -EIO;
1146         }
1147
1148         if (!s->do_cmd || !s->do_cmdtest) {
1149                 DPRINTK("subdevice %i does not support commands\n",
1150                         user_cmd.subdev);
1151                 return -EIO;
1152         }
1153
1154         /* make sure channel/gain list isn't too long */
1155         if (user_cmd.chanlist_len > s->len_chanlist) {
1156                 DPRINTK("channel/gain list too long %d > %d\n",
1157                         user_cmd.chanlist_len, s->len_chanlist);
1158                 ret = -EINVAL;
1159                 goto cleanup;
1160         }
1161
1162         /* load channel/gain list */
1163         if (user_cmd.chanlist) {
1164                 chanlist =
1165                     kmalloc(user_cmd.chanlist_len * sizeof(int), GFP_KERNEL);
1166                 if (!chanlist) {
1167                         DPRINTK("allocation failed\n");
1168                         ret = -ENOMEM;
1169                         goto cleanup;
1170                 }
1171
1172                 if (copy_from_user(chanlist, user_cmd.chanlist,
1173                                    user_cmd.chanlist_len * sizeof(int))) {
1174                         DPRINTK("fault reading chanlist\n");
1175                         ret = -EFAULT;
1176                         goto cleanup;
1177                 }
1178
1179                 /* make sure each element in channel/gain list is valid */
1180                 ret = check_chanlist(s, user_cmd.chanlist_len, chanlist);
1181                 if (ret < 0) {
1182                         DPRINTK("bad chanlist\n");
1183                         goto cleanup;
1184                 }
1185
1186                 user_cmd.chanlist = chanlist;
1187         }
1188
1189         ret = s->do_cmdtest(dev, s, &user_cmd);
1190
1191         /* restore chanlist pointer before copying back */
1192         user_cmd.chanlist = chanlist_saver;
1193
1194         if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
1195                 DPRINTK("bad cmd address\n");
1196                 ret = -EFAULT;
1197                 goto cleanup;
1198         }
1199 cleanup:
1200         kfree(chanlist);
1201
1202         return ret;
1203 }
1204
1205 /*
1206         COMEDI_LOCK
1207         lock subdevice
1208
1209         arg:
1210                 subdevice number
1211
1212         reads:
1213                 none
1214
1215         writes:
1216                 none
1217
1218 */
1219
1220 static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
1221                          void *file)
1222 {
1223         int ret = 0;
1224         unsigned long flags;
1225         struct comedi_subdevice *s;
1226
1227         if (arg >= dev->n_subdevices)
1228                 return -EINVAL;
1229         s = dev->subdevices + arg;
1230
1231         spin_lock_irqsave(&s->spin_lock, flags);
1232         if (s->busy || s->lock)
1233                 ret = -EBUSY;
1234         else
1235                 s->lock = file;
1236         spin_unlock_irqrestore(&s->spin_lock, flags);
1237
1238         if (ret < 0)
1239                 return ret;
1240
1241 #if 0
1242         if (s->lock_f)
1243                 ret = s->lock_f(dev, s);
1244 #endif
1245
1246         return ret;
1247 }
1248
1249 /*
1250         COMEDI_UNLOCK
1251         unlock subdevice
1252
1253         arg:
1254                 subdevice number
1255
1256         reads:
1257                 none
1258
1259         writes:
1260                 none
1261
1262         This function isn't protected by the semaphore, since
1263         we already own the lock.
1264 */
1265 static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg,
1266                            void *file)
1267 {
1268         struct comedi_subdevice *s;
1269
1270         if (arg >= dev->n_subdevices)
1271                 return -EINVAL;
1272         s = dev->subdevices + arg;
1273
1274         if (s->busy)
1275                 return -EBUSY;
1276
1277         if (s->lock && s->lock != file)
1278                 return -EACCES;
1279
1280         if (s->lock == file) {
1281 #if 0
1282                 if (s->unlock)
1283                         s->unlock(dev, s);
1284 #endif
1285
1286                 s->lock = NULL;
1287         }
1288
1289         return 0;
1290 }
1291
1292 /*
1293         COMEDI_CANCEL
1294         cancel acquisition ioctl
1295
1296         arg:
1297                 subdevice number
1298
1299         reads:
1300                 nothing
1301
1302         writes:
1303                 nothing
1304
1305 */
1306 static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
1307                            void *file)
1308 {
1309         struct comedi_subdevice *s;
1310
1311         if (arg >= dev->n_subdevices)
1312                 return -EINVAL;
1313         s = dev->subdevices + arg;
1314         if (s->async == NULL)
1315                 return -EINVAL;
1316
1317         if (s->lock && s->lock != file)
1318                 return -EACCES;
1319
1320         if (!s->busy)
1321                 return 0;
1322
1323         if (s->busy != file)
1324                 return -EBUSY;
1325
1326         return do_cancel(dev, s);
1327 }
1328
1329 /*
1330         COMEDI_POLL ioctl
1331         instructs driver to synchronize buffers
1332
1333         arg:
1334                 subdevice number
1335
1336         reads:
1337                 nothing
1338
1339         writes:
1340                 nothing
1341
1342 */
1343 static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg,
1344                          void *file)
1345 {
1346         struct comedi_subdevice *s;
1347
1348         if (arg >= dev->n_subdevices)
1349                 return -EINVAL;
1350         s = dev->subdevices + arg;
1351
1352         if (s->lock && s->lock != file)
1353                 return -EACCES;
1354
1355         if (!s->busy)
1356                 return 0;
1357
1358         if (s->busy != file)
1359                 return -EBUSY;
1360
1361         if (s->poll)
1362                 return s->poll(dev, s);
1363
1364         return -EINVAL;
1365 }
1366
1367 static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1368 {
1369         int ret = 0;
1370
1371         if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) && s->cancel)
1372                 ret = s->cancel(dev, s);
1373
1374         do_become_nonbusy(dev, s);
1375
1376         return ret;
1377 }
1378
1379 void comedi_unmap(struct vm_area_struct *area)
1380 {
1381         struct comedi_async *async;
1382         struct comedi_device *dev;
1383
1384         async = area->vm_private_data;
1385         dev = async->subdevice->device;
1386
1387         mutex_lock(&dev->mutex);
1388         async->mmap_count--;
1389         mutex_unlock(&dev->mutex);
1390 }
1391
1392 static struct vm_operations_struct comedi_vm_ops = {
1393         .close = comedi_unmap,
1394 };
1395
1396 static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
1397 {
1398         const unsigned minor = iminor(file->f_dentry->d_inode);
1399         struct comedi_device_file_info *dev_file_info =
1400             comedi_get_device_file_info(minor);
1401         struct comedi_device *dev = dev_file_info->device;
1402         struct comedi_async *async = NULL;
1403         unsigned long start = vma->vm_start;
1404         unsigned long size;
1405         int n_pages;
1406         int i;
1407         int retval;
1408         struct comedi_subdevice *s;
1409
1410         mutex_lock(&dev->mutex);
1411         if (!dev->attached) {
1412                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1413                 retval = -ENODEV;
1414                 goto done;
1415         }
1416         if (vma->vm_flags & VM_WRITE)
1417                 s = comedi_get_write_subdevice(dev_file_info);
1418         else
1419                 s = comedi_get_read_subdevice(dev_file_info);
1420
1421         if (s == NULL) {
1422                 retval = -EINVAL;
1423                 goto done;
1424         }
1425         async = s->async;
1426         if (async == NULL) {
1427                 retval = -EINVAL;
1428                 goto done;
1429         }
1430
1431         if (vma->vm_pgoff != 0) {
1432                 DPRINTK("comedi: mmap() offset must be 0.\n");
1433                 retval = -EINVAL;
1434                 goto done;
1435         }
1436
1437         size = vma->vm_end - vma->vm_start;
1438         if (size > async->prealloc_bufsz) {
1439                 retval = -EFAULT;
1440                 goto done;
1441         }
1442         if (size & (~PAGE_MASK)) {
1443                 retval = -EFAULT;
1444                 goto done;
1445         }
1446
1447         n_pages = size >> PAGE_SHIFT;
1448         for (i = 0; i < n_pages; ++i) {
1449                 if (remap_pfn_range(vma, start,
1450                                     page_to_pfn(virt_to_page
1451                                                 (async->buf_page_list
1452                                                  [i].virt_addr)), PAGE_SIZE,
1453                                     PAGE_SHARED)) {
1454                         retval = -EAGAIN;
1455                         goto done;
1456                 }
1457                 start += PAGE_SIZE;
1458         }
1459
1460         vma->vm_ops = &comedi_vm_ops;
1461         vma->vm_private_data = async;
1462
1463         async->mmap_count++;
1464
1465         retval = 0;
1466 done:
1467         mutex_unlock(&dev->mutex);
1468         return retval;
1469 }
1470
1471 static unsigned int comedi_poll(struct file *file, poll_table * wait)
1472 {
1473         unsigned int mask = 0;
1474         const unsigned minor = iminor(file->f_dentry->d_inode);
1475         struct comedi_device_file_info *dev_file_info =
1476             comedi_get_device_file_info(minor);
1477         struct comedi_device *dev = dev_file_info->device;
1478         struct comedi_subdevice *read_subdev;
1479         struct comedi_subdevice *write_subdev;
1480
1481         mutex_lock(&dev->mutex);
1482         if (!dev->attached) {
1483                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1484                 mutex_unlock(&dev->mutex);
1485                 return 0;
1486         }
1487
1488         mask = 0;
1489         read_subdev = comedi_get_read_subdevice(dev_file_info);
1490         if (read_subdev) {
1491                 poll_wait(file, &read_subdev->async->wait_head, wait);
1492                 if (!read_subdev->busy
1493                     || comedi_buf_read_n_available(read_subdev->async) > 0
1494                     || !(comedi_get_subdevice_runflags(read_subdev) &
1495                          SRF_RUNNING)) {
1496                         mask |= POLLIN | POLLRDNORM;
1497                 }
1498         }
1499         write_subdev = comedi_get_write_subdevice(dev_file_info);
1500         if (write_subdev) {
1501                 poll_wait(file, &write_subdev->async->wait_head, wait);
1502                 comedi_buf_write_alloc(write_subdev->async,
1503                                        write_subdev->async->prealloc_bufsz);
1504                 if (!write_subdev->busy
1505                     || !(comedi_get_subdevice_runflags(write_subdev) &
1506                          SRF_RUNNING)
1507                     || comedi_buf_write_n_allocated(write_subdev->async) >=
1508                     bytes_per_sample(write_subdev->async->subdevice)) {
1509                         mask |= POLLOUT | POLLWRNORM;
1510                 }
1511         }
1512
1513         mutex_unlock(&dev->mutex);
1514         return mask;
1515 }
1516
1517 static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
1518                             loff_t * offset)
1519 {
1520         struct comedi_subdevice *s;
1521         struct comedi_async *async;
1522         int n, m, count = 0, retval = 0;
1523         DECLARE_WAITQUEUE(wait, current);
1524         const unsigned minor = iminor(file->f_dentry->d_inode);
1525         struct comedi_device_file_info *dev_file_info =
1526             comedi_get_device_file_info(minor);
1527         struct comedi_device *dev = dev_file_info->device;
1528
1529         if (!dev->attached) {
1530                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1531                 retval = -ENODEV;
1532                 goto done;
1533         }
1534
1535         s = comedi_get_write_subdevice(dev_file_info);
1536         if (s == NULL) {
1537                 retval = -EIO;
1538                 goto done;
1539         }
1540         async = s->async;
1541
1542         if (!nbytes) {
1543                 retval = 0;
1544                 goto done;
1545         }
1546         if (!s->busy) {
1547                 retval = 0;
1548                 goto done;
1549         }
1550         if (s->busy != file) {
1551                 retval = -EACCES;
1552                 goto done;
1553         }
1554         add_wait_queue(&async->wait_head, &wait);
1555         while (nbytes > 0 && !retval) {
1556                 set_current_state(TASK_INTERRUPTIBLE);
1557
1558                 n = nbytes;
1559
1560                 m = n;
1561                 if (async->buf_write_ptr + m > async->prealloc_bufsz)
1562                         m = async->prealloc_bufsz - async->buf_write_ptr;
1563                 comedi_buf_write_alloc(async, async->prealloc_bufsz);
1564                 if (m > comedi_buf_write_n_allocated(async))
1565                         m = comedi_buf_write_n_allocated(async);
1566                 if (m < n)
1567                         n = m;
1568
1569                 if (n == 0) {
1570                         if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
1571                                 if (comedi_get_subdevice_runflags(s) &
1572                                     SRF_ERROR) {
1573                                         retval = -EPIPE;
1574                                 } else {
1575                                         retval = 0;
1576                                 }
1577                                 do_become_nonbusy(dev, s);
1578                                 break;
1579                         }
1580                         if (file->f_flags & O_NONBLOCK) {
1581                                 retval = -EAGAIN;
1582                                 break;
1583                         }
1584                         if (signal_pending(current)) {
1585                                 retval = -ERESTARTSYS;
1586                                 break;
1587                         }
1588                         schedule();
1589                         if (!s->busy)
1590                                 break;
1591                         if (s->busy != file) {
1592                                 retval = -EACCES;
1593                                 break;
1594                         }
1595                         continue;
1596                 }
1597
1598                 m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
1599                                    buf, n);
1600                 if (m) {
1601                         n -= m;
1602                         retval = -EFAULT;
1603                 }
1604                 comedi_buf_write_free(async, n);
1605
1606                 count += n;
1607                 nbytes -= n;
1608
1609                 buf += n;
1610                 break;          /* makes device work like a pipe */
1611         }
1612         set_current_state(TASK_RUNNING);
1613         remove_wait_queue(&async->wait_head, &wait);
1614
1615 done:
1616         return count ? count : retval;
1617 }
1618
1619 static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
1620                            loff_t * offset)
1621 {
1622         struct comedi_subdevice *s;
1623         struct comedi_async *async;
1624         int n, m, count = 0, retval = 0;
1625         DECLARE_WAITQUEUE(wait, current);
1626         const unsigned minor = iminor(file->f_dentry->d_inode);
1627         struct comedi_device_file_info *dev_file_info =
1628             comedi_get_device_file_info(minor);
1629         struct comedi_device *dev = dev_file_info->device;
1630
1631         if (!dev->attached) {
1632                 DPRINTK("no driver configured on comedi%i\n", dev->minor);
1633                 retval = -ENODEV;
1634                 goto done;
1635         }
1636
1637         s = comedi_get_read_subdevice(dev_file_info);
1638         if (s == NULL) {
1639                 retval = -EIO;
1640                 goto done;
1641         }
1642         async = s->async;
1643         if (!nbytes) {
1644                 retval = 0;
1645                 goto done;
1646         }
1647         if (!s->busy) {
1648                 retval = 0;
1649                 goto done;
1650         }
1651         if (s->busy != file) {
1652                 retval = -EACCES;
1653                 goto done;
1654         }
1655
1656         add_wait_queue(&async->wait_head, &wait);
1657         while (nbytes > 0 && !retval) {
1658                 set_current_state(TASK_INTERRUPTIBLE);
1659
1660                 n = nbytes;
1661
1662                 m = comedi_buf_read_n_available(async);
1663                 /* printk("%d available\n",m); */
1664                 if (async->buf_read_ptr + m > async->prealloc_bufsz)
1665                         m = async->prealloc_bufsz - async->buf_read_ptr;
1666                 /* printk("%d contiguous\n",m); */
1667                 if (m < n)
1668                         n = m;
1669
1670                 if (n == 0) {
1671                         if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
1672                                 do_become_nonbusy(dev, s);
1673                                 if (comedi_get_subdevice_runflags(s) &
1674                                     SRF_ERROR) {
1675                                         retval = -EPIPE;
1676                                 } else {
1677                                         retval = 0;
1678                                 }
1679                                 break;
1680                         }
1681                         if (file->f_flags & O_NONBLOCK) {
1682                                 retval = -EAGAIN;
1683                                 break;
1684                         }
1685                         if (signal_pending(current)) {
1686                                 retval = -ERESTARTSYS;
1687                                 break;
1688                         }
1689                         schedule();
1690                         if (!s->busy) {
1691                                 retval = 0;
1692                                 break;
1693                         }
1694                         if (s->busy != file) {
1695                                 retval = -EACCES;
1696                                 break;
1697                         }
1698                         continue;
1699                 }
1700                 m = copy_to_user(buf, async->prealloc_buf +
1701                                  async->buf_read_ptr, n);
1702                 if (m) {
1703                         n -= m;
1704                         retval = -EFAULT;
1705                 }
1706
1707                 comedi_buf_read_alloc(async, n);
1708                 comedi_buf_read_free(async, n);
1709
1710                 count += n;
1711                 nbytes -= n;
1712
1713                 buf += n;
1714                 break;          /* makes device work like a pipe */
1715         }
1716         if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING)) &&
1717             async->buf_read_count - async->buf_write_count == 0) {
1718                 do_become_nonbusy(dev, s);
1719         }
1720         set_current_state(TASK_RUNNING);
1721         remove_wait_queue(&async->wait_head, &wait);
1722
1723 done:
1724         return count ? count : retval;
1725 }
1726
1727 /*
1728    This function restores a subdevice to an idle state.
1729  */
1730 void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s)
1731 {
1732         struct comedi_async *async = s->async;
1733
1734         comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
1735         if (async) {
1736                 comedi_reset_async_buf(async);
1737                 async->inttrig = NULL;
1738         } else {
1739                 printk(KERN_ERR
1740                        "BUG: (?) do_become_nonbusy called with async=0\n");
1741         }
1742
1743         s->busy = NULL;
1744 }
1745
1746 static int comedi_open(struct inode *inode, struct file *file)
1747 {
1748         const unsigned minor = iminor(inode);
1749         struct comedi_device_file_info *dev_file_info =
1750             comedi_get_device_file_info(minor);
1751         struct comedi_device *dev =
1752             dev_file_info ? dev_file_info->device : NULL;
1753
1754         if (dev == NULL) {
1755                 DPRINTK("invalid minor number\n");
1756                 return -ENODEV;
1757         }
1758
1759         /* This is slightly hacky, but we want module autoloading
1760          * to work for root.
1761          * case: user opens device, attached -> ok
1762          * case: user opens device, unattached, in_request_module=0 -> autoload
1763          * case: user opens device, unattached, in_request_module=1 -> fail
1764          * case: root opens device, attached -> ok
1765          * case: root opens device, unattached, in_request_module=1 -> ok
1766          *   (typically called from modprobe)
1767          * case: root opens device, unattached, in_request_module=0 -> autoload
1768          *
1769          * The last could be changed to "-> ok", which would deny root
1770          * autoloading.
1771          */
1772         mutex_lock(&dev->mutex);
1773         if (dev->attached)
1774                 goto ok;
1775         if (!capable(CAP_NET_ADMIN) && dev->in_request_module) {
1776                 DPRINTK("in request module\n");
1777                 mutex_unlock(&dev->mutex);
1778                 return -ENODEV;
1779         }
1780         if (capable(CAP_NET_ADMIN) && dev->in_request_module)
1781                 goto ok;
1782
1783         dev->in_request_module = 1;
1784
1785 #ifdef CONFIG_KMOD
1786         mutex_unlock(&dev->mutex);
1787         request_module("char-major-%i-%i", COMEDI_MAJOR, dev->minor);
1788         mutex_lock(&dev->mutex);
1789 #endif
1790
1791         dev->in_request_module = 0;
1792
1793         if (!dev->attached && !capable(CAP_NET_ADMIN)) {
1794                 DPRINTK("not attached and not CAP_NET_ADMIN\n");
1795                 mutex_unlock(&dev->mutex);
1796                 return -ENODEV;
1797         }
1798 ok:
1799         __module_get(THIS_MODULE);
1800
1801         if (dev->attached) {
1802                 if (!try_module_get(dev->driver->module)) {
1803                         module_put(THIS_MODULE);
1804                         mutex_unlock(&dev->mutex);
1805                         return -ENOSYS;
1806                 }
1807         }
1808
1809         if (dev->attached && dev->use_count == 0 && dev->open)
1810                 dev->open(dev);
1811
1812         dev->use_count++;
1813
1814         mutex_unlock(&dev->mutex);
1815
1816         return 0;
1817 }
1818
1819 static int comedi_close(struct inode *inode, struct file *file)
1820 {
1821         const unsigned minor = iminor(inode);
1822         struct comedi_device_file_info *dev_file_info =
1823             comedi_get_device_file_info(minor);
1824         struct comedi_device *dev = dev_file_info->device;
1825         struct comedi_subdevice *s = NULL;
1826         int i;
1827
1828         mutex_lock(&dev->mutex);
1829
1830         if (dev->subdevices) {
1831                 for (i = 0; i < dev->n_subdevices; i++) {
1832                         s = dev->subdevices + i;
1833
1834                         if (s->busy == file)
1835                                 do_cancel(dev, s);
1836                         if (s->lock == file)
1837                                 s->lock = NULL;
1838                 }
1839         }
1840         if (dev->attached && dev->use_count == 1 && dev->close)
1841                 dev->close(dev);
1842
1843         module_put(THIS_MODULE);
1844         if (dev->attached)
1845                 module_put(dev->driver->module);
1846
1847         dev->use_count--;
1848
1849         mutex_unlock(&dev->mutex);
1850
1851         if (file->f_flags & FASYNC)
1852                 comedi_fasync(-1, file, 0);
1853
1854         return 0;
1855 }
1856
1857 static int comedi_fasync(int fd, struct file *file, int on)
1858 {
1859         const unsigned minor = iminor(file->f_dentry->d_inode);
1860         struct comedi_device_file_info *dev_file_info =
1861             comedi_get_device_file_info(minor);
1862
1863         struct comedi_device *dev = dev_file_info->device;
1864
1865         return fasync_helper(fd, file, on, &dev->async_queue);
1866 }
1867
1868 const struct file_operations comedi_fops = {
1869         .owner = THIS_MODULE,
1870 #ifdef HAVE_UNLOCKED_IOCTL
1871         .unlocked_ioctl = comedi_unlocked_ioctl,
1872 #else
1873         .ioctl = comedi_ioctl,
1874 #endif
1875 #ifdef HAVE_COMPAT_IOCTL
1876         .compat_ioctl = comedi_compat_ioctl,
1877 #endif
1878         .open = comedi_open,
1879         .release = comedi_close,
1880         .read = comedi_read,
1881         .write = comedi_write,
1882         .mmap = comedi_mmap,
1883         .poll = comedi_poll,
1884         .fasync = comedi_fasync,
1885 };
1886
1887 struct class *comedi_class;
1888 static struct cdev comedi_cdev;
1889
1890 static void comedi_cleanup_legacy_minors(void)
1891 {
1892         unsigned i;
1893
1894         for (i = 0; i < comedi_num_legacy_minors; i++)
1895                 comedi_free_board_minor(i);
1896 }
1897
1898 static int __init comedi_init(void)
1899 {
1900         int i;
1901         int retval;
1902
1903         printk(KERN_INFO "comedi: version " COMEDI_RELEASE
1904                " - http://www.comedi.org\n");
1905
1906         if (comedi_num_legacy_minors < 0 ||
1907             comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
1908                 printk(KERN_ERR "comedi: error: invalid value for module "
1909                        "parameter \"comedi_num_legacy_minors\".  Valid values "
1910                        "are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS);
1911                 return -EINVAL;
1912         }
1913
1914         /*
1915          * comedi is unusable if both comedi_autoconfig and
1916          * comedi_num_legacy_minors are zero, so we might as well adjust the
1917          * defaults in that case
1918          */
1919         if (comedi_autoconfig == 0 && comedi_num_legacy_minors == 0)
1920                 comedi_num_legacy_minors = 16;
1921
1922         memset(comedi_file_info_table, 0,
1923                sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS);
1924
1925         retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
1926                                         COMEDI_NUM_MINORS, "comedi");
1927         if (retval)
1928                 return -EIO;
1929         cdev_init(&comedi_cdev, &comedi_fops);
1930         comedi_cdev.owner = THIS_MODULE;
1931         kobject_set_name(&comedi_cdev.kobj, "comedi");
1932         if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
1933                 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
1934                                          COMEDI_NUM_MINORS);
1935                 return -EIO;
1936         }
1937         comedi_class = class_create(THIS_MODULE, "comedi");
1938         if (IS_ERR(comedi_class)) {
1939                 printk("comedi: failed to create class");
1940                 cdev_del(&comedi_cdev);
1941                 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
1942                                          COMEDI_NUM_MINORS);
1943                 return PTR_ERR(comedi_class);
1944         }
1945
1946         /* XXX requires /proc interface */
1947         comedi_proc_init();
1948
1949         /* create devices files for legacy/manual use */
1950         for (i = 0; i < comedi_num_legacy_minors; i++) {
1951                 int minor;
1952                 minor = comedi_alloc_board_minor(NULL);
1953                 if (minor < 0) {
1954                         comedi_cleanup_legacy_minors();
1955                         cdev_del(&comedi_cdev);
1956                         unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
1957                                                  COMEDI_NUM_MINORS);
1958                         return minor;
1959                 }
1960         }
1961
1962         comedi_register_ioctl32();
1963
1964         return 0;
1965 }
1966
1967 static void __exit comedi_cleanup(void)
1968 {
1969         int i;
1970
1971         comedi_cleanup_legacy_minors();
1972         for (i = 0; i < COMEDI_NUM_MINORS; ++i)
1973                 BUG_ON(comedi_file_info_table[i]);
1974
1975         class_destroy(comedi_class);
1976         cdev_del(&comedi_cdev);
1977         unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
1978
1979         comedi_proc_cleanup();
1980
1981         comedi_unregister_ioctl32();
1982 }
1983
1984 module_init(comedi_init);
1985 module_exit(comedi_cleanup);
1986
1987 void comedi_error(const struct comedi_device *dev, const char *s)
1988 {
1989         printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name, s);
1990 }
1991
1992 void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
1993 {
1994         struct comedi_async *async = s->async;
1995         unsigned runflags = 0;
1996         unsigned runflags_mask = 0;
1997
1998         /* DPRINTK("comedi_event 0x%x\n",mask); */
1999
2000         if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) == 0)
2001                 return;
2002
2003         if (s->
2004             async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2005                              COMEDI_CB_OVERFLOW)) {
2006                 runflags_mask |= SRF_RUNNING;
2007         }
2008         /* remember if an error event has occured, so an error
2009          * can be returned the next time the user does a read() */
2010         if (s->async->events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
2011                 runflags_mask |= SRF_ERROR;
2012                 runflags |= SRF_ERROR;
2013         }
2014         if (runflags_mask) {
2015                 /*sets SRF_ERROR and SRF_RUNNING together atomically */
2016                 comedi_set_subdevice_runflags(s, runflags_mask, runflags);
2017         }
2018
2019         if (async->cb_mask & s->async->events) {
2020                 if (comedi_get_subdevice_runflags(s) & SRF_USER) {
2021                         wake_up_interruptible(&async->wait_head);
2022                         if (s->subdev_flags & SDF_CMD_READ) {
2023                                 kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
2024                         }
2025                         if (s->subdev_flags & SDF_CMD_WRITE) {
2026                                 kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
2027                         }
2028                 } else {
2029                         if (async->cb_func)
2030                                 async->cb_func(s->async->events, async->cb_arg);
2031                 }
2032         }
2033         s->async->events = 0;
2034 }
2035
2036 void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
2037                                    unsigned bits)
2038 {
2039         unsigned long flags;
2040
2041         spin_lock_irqsave(&s->spin_lock, flags);
2042         s->runflags &= ~mask;
2043         s->runflags |= (bits & mask);
2044         spin_unlock_irqrestore(&s->spin_lock, flags);
2045 }
2046
2047 unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
2048 {
2049         unsigned long flags;
2050         unsigned runflags;
2051
2052         spin_lock_irqsave(&s->spin_lock, flags);
2053         runflags = s->runflags;
2054         spin_unlock_irqrestore(&s->spin_lock, flags);
2055         return runflags;
2056 }
2057
2058 static int is_device_busy(struct comedi_device *dev)
2059 {
2060         struct comedi_subdevice *s;
2061         int i;
2062
2063         if (!dev->attached)
2064                 return 0;
2065
2066         for (i = 0; i < dev->n_subdevices; i++) {
2067                 s = dev->subdevices + i;
2068                 if (s->busy)
2069                         return 1;
2070                 if (s->async && s->async->mmap_count)
2071                         return 1;
2072         }
2073
2074         return 0;
2075 }
2076
2077 void comedi_device_init(struct comedi_device *dev)
2078 {
2079         memset(dev, 0, sizeof(struct comedi_device));
2080         spin_lock_init(&dev->spinlock);
2081         mutex_init(&dev->mutex);
2082         dev->minor = -1;
2083 }
2084
2085 void comedi_device_cleanup(struct comedi_device *dev)
2086 {
2087         if (dev == NULL)
2088                 return;
2089         mutex_lock(&dev->mutex);
2090         comedi_device_detach(dev);
2091         mutex_unlock(&dev->mutex);
2092         mutex_destroy(&dev->mutex);
2093 }
2094
2095 int comedi_alloc_board_minor(struct device *hardware_device)
2096 {
2097         unsigned long flags;
2098         struct comedi_device_file_info *info;
2099         struct device *csdev;
2100         unsigned i;
2101         int retval;
2102
2103         info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
2104         if (info == NULL)
2105                 return -ENOMEM;
2106         info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL);
2107         if (info->device == NULL) {
2108                 kfree(info);
2109                 return -ENOMEM;
2110         }
2111         comedi_device_init(info->device);
2112         spin_lock_irqsave(&comedi_file_info_table_lock, flags);
2113         for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) {
2114                 if (comedi_file_info_table[i] == NULL) {
2115                         comedi_file_info_table[i] = info;
2116                         break;
2117                 }
2118         }
2119         spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
2120         if (i == COMEDI_NUM_BOARD_MINORS) {
2121                 comedi_device_cleanup(info->device);
2122                 kfree(info->device);
2123                 kfree(info);
2124                 printk(KERN_ERR
2125                        "comedi: error: ran out of minor numbers for board device files.\n");
2126                 return -EBUSY;
2127         }
2128         info->device->minor = i;
2129         csdev = COMEDI_DEVICE_CREATE(comedi_class, NULL,
2130                                      MKDEV(COMEDI_MAJOR, i), NULL,
2131                                      hardware_device, "comedi%i", i);
2132         if (!IS_ERR(csdev))
2133                 info->device->class_dev = csdev;
2134         dev_set_drvdata(csdev, info);
2135         retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
2136         if (retval) {
2137                 printk(KERN_ERR
2138                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2139                        dev_attr_max_read_buffer_kb.attr.name);
2140                 comedi_free_board_minor(i);
2141                 return retval;
2142         }
2143         retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
2144         if (retval) {
2145                 printk(KERN_ERR
2146                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2147                        dev_attr_read_buffer_kb.attr.name);
2148                 comedi_free_board_minor(i);
2149                 return retval;
2150         }
2151         retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
2152         if (retval) {
2153                 printk(KERN_ERR
2154                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2155                        dev_attr_max_write_buffer_kb.attr.name);
2156                 comedi_free_board_minor(i);
2157                 return retval;
2158         }
2159         retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
2160         if (retval) {
2161                 printk(KERN_ERR
2162                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2163                        dev_attr_write_buffer_kb.attr.name);
2164                 comedi_free_board_minor(i);
2165                 return retval;
2166         }
2167         return i;
2168 }
2169
2170 void comedi_free_board_minor(unsigned minor)
2171 {
2172         unsigned long flags;
2173         struct comedi_device_file_info *info;
2174
2175         BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
2176         spin_lock_irqsave(&comedi_file_info_table_lock, flags);
2177         info = comedi_file_info_table[minor];
2178         comedi_file_info_table[minor] = NULL;
2179         spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
2180
2181         if (info) {
2182                 struct comedi_device *dev = info->device;
2183                 if (dev) {
2184                         if (dev->class_dev) {
2185                                 device_destroy(comedi_class,
2186                                                MKDEV(COMEDI_MAJOR, dev->minor));
2187                         }
2188                         comedi_device_cleanup(dev);
2189                         kfree(dev);
2190                 }
2191                 kfree(info);
2192         }
2193 }
2194
2195 int comedi_alloc_subdevice_minor(struct comedi_device *dev,
2196                                  struct comedi_subdevice *s)
2197 {
2198         unsigned long flags;
2199         struct comedi_device_file_info *info;
2200         struct device *csdev;
2201         unsigned i;
2202         int retval;
2203
2204         info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
2205         if (info == NULL)
2206                 return -ENOMEM;
2207         info->device = dev;
2208         info->read_subdevice = s;
2209         info->write_subdevice = s;
2210         spin_lock_irqsave(&comedi_file_info_table_lock, flags);
2211         for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) {
2212                 if (comedi_file_info_table[i] == NULL) {
2213                         comedi_file_info_table[i] = info;
2214                         break;
2215                 }
2216         }
2217         spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
2218         if (i == COMEDI_NUM_MINORS) {
2219                 kfree(info);
2220                 printk(KERN_ERR
2221                        "comedi: error: ran out of minor numbers for board device files.\n");
2222                 return -EBUSY;
2223         }
2224         s->minor = i;
2225         csdev = COMEDI_DEVICE_CREATE(comedi_class, dev->class_dev,
2226                                      MKDEV(COMEDI_MAJOR, i), NULL, NULL,
2227                                      "comedi%i_subd%i", dev->minor,
2228                                      (int)(s - dev->subdevices));
2229         if (!IS_ERR(csdev))
2230                 s->class_dev = csdev;
2231         dev_set_drvdata(csdev, info);
2232         retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
2233         if (retval) {
2234                 printk(KERN_ERR
2235                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2236                        dev_attr_max_read_buffer_kb.attr.name);
2237                 comedi_free_subdevice_minor(s);
2238                 return retval;
2239         }
2240         retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
2241         if (retval) {
2242                 printk(KERN_ERR
2243                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2244                        dev_attr_read_buffer_kb.attr.name);
2245                 comedi_free_subdevice_minor(s);
2246                 return retval;
2247         }
2248         retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
2249         if (retval) {
2250                 printk(KERN_ERR
2251                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2252                        dev_attr_max_write_buffer_kb.attr.name);
2253                 comedi_free_subdevice_minor(s);
2254                 return retval;
2255         }
2256         retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
2257         if (retval) {
2258                 printk(KERN_ERR
2259                        "comedi: failed to create sysfs attribute file \"%s\".\n",
2260                        dev_attr_write_buffer_kb.attr.name);
2261                 comedi_free_subdevice_minor(s);
2262                 return retval;
2263         }
2264         return i;
2265 }
2266
2267 void comedi_free_subdevice_minor(struct comedi_subdevice *s)
2268 {
2269         unsigned long flags;
2270         struct comedi_device_file_info *info;
2271
2272         if (s == NULL)
2273                 return;
2274         if (s->minor < 0)
2275                 return;
2276
2277         BUG_ON(s->minor >= COMEDI_NUM_MINORS);
2278         BUG_ON(s->minor < COMEDI_FIRST_SUBDEVICE_MINOR);
2279
2280         spin_lock_irqsave(&comedi_file_info_table_lock, flags);
2281         info = comedi_file_info_table[s->minor];
2282         comedi_file_info_table[s->minor] = NULL;
2283         spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
2284
2285         if (s->class_dev) {
2286                 device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
2287                 s->class_dev = NULL;
2288         }
2289         kfree(info);
2290 }
2291
2292 struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
2293 {
2294         unsigned long flags;
2295         struct comedi_device_file_info *info;
2296
2297         BUG_ON(minor >= COMEDI_NUM_MINORS);
2298         spin_lock_irqsave(&comedi_file_info_table_lock, flags);
2299         info = comedi_file_info_table[minor];
2300         spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
2301         return info;
2302 }
2303
2304 static int resize_async_buffer(struct comedi_device *dev,
2305                                struct comedi_subdevice *s,
2306                                struct comedi_async *async, unsigned new_size)
2307 {
2308         int retval;
2309
2310         if (new_size > async->max_bufsize)
2311                 return -EPERM;
2312
2313         if (s->busy) {
2314                 DPRINTK("subdevice is busy, cannot resize buffer\n");
2315                 return -EBUSY;
2316         }
2317         if (async->mmap_count) {
2318                 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
2319                 return -EBUSY;
2320         }
2321
2322         if (!async->prealloc_buf)
2323                 return -EINVAL;
2324
2325         /* make sure buffer is an integral number of pages
2326          * (we round up) */
2327         new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
2328
2329         retval = comedi_buf_alloc(dev, s, new_size);
2330         if (retval < 0)
2331                 return retval;
2332
2333         if (s->buf_change) {
2334                 retval = s->buf_change(dev, s, new_size);
2335                 if (retval < 0)
2336                         return retval;
2337         }
2338
2339         DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
2340                 dev->minor, s - dev->subdevices, async->prealloc_bufsz);
2341         return 0;
2342 }
2343
2344 /* sysfs attribute files */
2345
2346 static const unsigned bytes_per_kibi = 1024;
2347
2348 static ssize_t show_max_read_buffer_kb(struct device *dev,
2349                                        struct device_attribute *attr, char *buf)
2350 {
2351         ssize_t retval;
2352         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2353         unsigned max_buffer_size_kb = 0;
2354         struct comedi_subdevice *const read_subdevice =
2355             comedi_get_read_subdevice(info);
2356
2357         mutex_lock(&info->device->mutex);
2358         if (read_subdevice &&
2359             (read_subdevice->subdev_flags & SDF_CMD_READ) &&
2360             read_subdevice->async) {
2361                 max_buffer_size_kb = read_subdevice->async->max_bufsize /
2362                     bytes_per_kibi;
2363         }
2364         retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
2365         mutex_unlock(&info->device->mutex);
2366
2367         return retval;
2368 }
2369
2370 static ssize_t store_max_read_buffer_kb(struct device *dev,
2371                                         struct device_attribute *attr,
2372                                         const char *buf, size_t count)
2373 {
2374         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2375         unsigned long new_max_size_kb;
2376         uint64_t new_max_size;
2377         struct comedi_subdevice *const read_subdevice =
2378             comedi_get_read_subdevice(info);
2379
2380         if (strict_strtoul(buf, 10, &new_max_size_kb))
2381                 return -EINVAL;
2382         if (new_max_size_kb != (uint32_t) new_max_size_kb)
2383                 return -EINVAL;
2384         new_max_size = ((uint64_t) new_max_size_kb) * bytes_per_kibi;
2385         if (new_max_size != (uint32_t) new_max_size)
2386                 return -EINVAL;
2387
2388         mutex_lock(&info->device->mutex);
2389         if (read_subdevice == NULL ||
2390             (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
2391             read_subdevice->async == NULL) {
2392                 mutex_unlock(&info->device->mutex);
2393                 return -EINVAL;
2394         }
2395         read_subdevice->async->max_bufsize = new_max_size;
2396         mutex_unlock(&info->device->mutex);
2397
2398         return count;
2399 }
2400
2401 static struct device_attribute dev_attr_max_read_buffer_kb = {
2402         .attr = {
2403                  .name = "max_read_buffer_kb",
2404                  .mode = S_IRUGO | S_IWUSR},
2405         .show = &show_max_read_buffer_kb,
2406         .store = &store_max_read_buffer_kb
2407 };
2408
2409 static ssize_t show_read_buffer_kb(struct device *dev,
2410                                    struct device_attribute *attr, char *buf)
2411 {
2412         ssize_t retval;
2413         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2414         unsigned buffer_size_kb = 0;
2415         struct comedi_subdevice *const read_subdevice =
2416             comedi_get_read_subdevice(info);
2417
2418         mutex_lock(&info->device->mutex);
2419         if (read_subdevice &&
2420             (read_subdevice->subdev_flags & SDF_CMD_READ) &&
2421             read_subdevice->async) {
2422                 buffer_size_kb = read_subdevice->async->prealloc_bufsz /
2423                     bytes_per_kibi;
2424         }
2425         retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
2426         mutex_unlock(&info->device->mutex);
2427
2428         return retval;
2429 }
2430
2431 static ssize_t store_read_buffer_kb(struct device *dev,
2432                                     struct device_attribute *attr,
2433                                     const char *buf, size_t count)
2434 {
2435         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2436         unsigned long new_size_kb;
2437         uint64_t new_size;
2438         int retval;
2439         struct comedi_subdevice *const read_subdevice =
2440             comedi_get_read_subdevice(info);
2441
2442         if (strict_strtoul(buf, 10, &new_size_kb))
2443                 return -EINVAL;
2444         if (new_size_kb != (uint32_t) new_size_kb)
2445                 return -EINVAL;
2446         new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
2447         if (new_size != (uint32_t) new_size)
2448                 return -EINVAL;
2449
2450         mutex_lock(&info->device->mutex);
2451         if (read_subdevice == NULL ||
2452             (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
2453             read_subdevice->async == NULL) {
2454                 mutex_unlock(&info->device->mutex);
2455                 return -EINVAL;
2456         }
2457         retval = resize_async_buffer(info->device, read_subdevice,
2458                                      read_subdevice->async, new_size);
2459         mutex_unlock(&info->device->mutex);
2460
2461         if (retval < 0)
2462                 return retval;
2463         return count;
2464 }
2465
2466 static struct device_attribute dev_attr_read_buffer_kb = {
2467         .attr = {
2468                  .name = "read_buffer_kb",
2469                  .mode = S_IRUGO | S_IWUSR | S_IWGRP},
2470         .show = &show_read_buffer_kb,
2471         .store = &store_read_buffer_kb
2472 };
2473
2474 static ssize_t show_max_write_buffer_kb(struct device *dev,
2475                                         struct device_attribute *attr,
2476                                         char *buf)
2477 {
2478         ssize_t retval;
2479         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2480         unsigned max_buffer_size_kb = 0;
2481         struct comedi_subdevice *const write_subdevice =
2482             comedi_get_write_subdevice(info);
2483
2484         mutex_lock(&info->device->mutex);
2485         if (write_subdevice &&
2486             (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
2487             write_subdevice->async) {
2488                 max_buffer_size_kb = write_subdevice->async->max_bufsize /
2489                     bytes_per_kibi;
2490         }
2491         retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
2492         mutex_unlock(&info->device->mutex);
2493
2494         return retval;
2495 }
2496
2497 static ssize_t store_max_write_buffer_kb(struct device *dev,
2498                                          struct device_attribute *attr,
2499                                          const char *buf, size_t count)
2500 {
2501         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2502         unsigned long new_max_size_kb;
2503         uint64_t new_max_size;
2504         struct comedi_subdevice *const write_subdevice =
2505             comedi_get_write_subdevice(info);
2506
2507         if (strict_strtoul(buf, 10, &new_max_size_kb))
2508                 return -EINVAL;
2509         if (new_max_size_kb != (uint32_t) new_max_size_kb)
2510                 return -EINVAL;
2511         new_max_size = ((uint64_t) new_max_size_kb) * bytes_per_kibi;
2512         if (new_max_size != (uint32_t) new_max_size)
2513                 return -EINVAL;
2514
2515         mutex_lock(&info->device->mutex);
2516         if (write_subdevice == NULL ||
2517             (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
2518             write_subdevice->async == NULL) {
2519                 mutex_unlock(&info->device->mutex);
2520                 return -EINVAL;
2521         }
2522         write_subdevice->async->max_bufsize = new_max_size;
2523         mutex_unlock(&info->device->mutex);
2524
2525         return count;
2526 }
2527
2528 static struct device_attribute dev_attr_max_write_buffer_kb = {
2529         .attr = {
2530                  .name = "max_write_buffer_kb",
2531                  .mode = S_IRUGO | S_IWUSR},
2532         .show = &show_max_write_buffer_kb,
2533         .store = &store_max_write_buffer_kb
2534 };
2535
2536 static ssize_t show_write_buffer_kb(struct device *dev,
2537                                     struct device_attribute *attr, char *buf)
2538 {
2539         ssize_t retval;
2540         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2541         unsigned buffer_size_kb = 0;
2542         struct comedi_subdevice *const write_subdevice =
2543             comedi_get_write_subdevice(info);
2544
2545         mutex_lock(&info->device->mutex);
2546         if (write_subdevice &&
2547             (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
2548             write_subdevice->async) {
2549                 buffer_size_kb = write_subdevice->async->prealloc_bufsz /
2550                     bytes_per_kibi;
2551         }
2552         retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
2553         mutex_unlock(&info->device->mutex);
2554
2555         return retval;
2556 }
2557
2558 static ssize_t store_write_buffer_kb(struct device *dev,
2559                                      struct device_attribute *attr,
2560                                      const char *buf, size_t count)
2561 {
2562         struct comedi_device_file_info *info = dev_get_drvdata(dev);
2563         unsigned long new_size_kb;
2564         uint64_t new_size;
2565         int retval;
2566         struct comedi_subdevice *const write_subdevice =
2567             comedi_get_write_subdevice(info);
2568
2569         if (strict_strtoul(buf, 10, &new_size_kb))
2570                 return -EINVAL;
2571         if (new_size_kb != (uint32_t) new_size_kb)
2572                 return -EINVAL;
2573         new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
2574         if (new_size != (uint32_t) new_size)
2575                 return -EINVAL;
2576
2577         mutex_lock(&info->device->mutex);
2578         if (write_subdevice == NULL ||
2579             (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
2580             write_subdevice->async == NULL) {
2581                 mutex_unlock(&info->device->mutex);
2582                 return -EINVAL;
2583         }
2584         retval = resize_async_buffer(info->device, write_subdevice,
2585                                      write_subdevice->async, new_size);
2586         mutex_unlock(&info->device->mutex);
2587
2588         if (retval < 0)
2589                 return retval;
2590         return count;
2591 }
2592
2593 static struct device_attribute dev_attr_write_buffer_kb = {
2594         .attr = {
2595                  .name = "write_buffer_kb",
2596                  .mode = S_IRUGO | S_IWUSR | S_IWGRP},
2597         .show = &show_write_buffer_kb,
2598         .store = &store_write_buffer_kb
2599 };