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