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