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