comedi_fops.c revision c5274ab09747d0ef829f9b8f040756758e5de55c
1ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 2ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi/comedi_fops.c 3ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi kernel module 4ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 5ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI - Linux Control and Measurement Device Interface 6ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> 7ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 8ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef This program is free software; you can redistribute it and/or modify 9ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef it under the terms of the GNU General Public License as published by 10ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef the Free Software Foundation; either version 2 of the License, or 11ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef (at your option) any later version. 12ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 13ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef This program is distributed in the hope that it will be useful, 14ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef but WITHOUT ANY WARRANTY; without even the implied warranty of 15ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef GNU General Public License for more details. 17ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 18ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef You should have received a copy of the GNU General Public License 19ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef along with this program; if not, write to the Free Software 20ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 22ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 23ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 24ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#undef DEBUG 25ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 26ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#define __NO_VERSION__ 27ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include "comedi_fops.h" 28ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include "comedi_compat32.h" 29ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 30ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/module.h> 31ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/errno.h> 32ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/kernel.h> 33ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/sched.h> 34ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/fcntl.h> 35ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/delay.h> 36ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/ioport.h> 37ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/mm.h> 38ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/slab.h> 39ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/kmod.h> 40ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/poll.h> 41ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/init.h> 42ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/device.h> 43ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/vmalloc.h> 44ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/fs.h> 45ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include "comedidev.h" 46ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#include <linux/cdev.h> 47883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess#include <linux/stat.h> 48ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 49476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman#include <linux/io.h> 50476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman#include <linux/uaccess.h> 51ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 52242e7ad91a067243d7ab63b6a25ed2e085733446Greg Kroah-Hartman#include "internal.h" 53ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 54ed9eccbe8970f6eedc1b978c157caf1251a896d4David SchleefMODULE_AUTHOR("http://www.comedi.org"); 55ed9eccbe8970f6eedc1b978c157caf1251a896d4David SchleefMODULE_DESCRIPTION("Comedi core module"); 56ed9eccbe8970f6eedc1b978c157caf1251a896d4David SchleefMODULE_LICENSE("GPL"); 57ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 58ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#ifdef CONFIG_COMEDI_DEBUG 59ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefint comedi_debug; 6018736438ae4ab3d96602b92446e07cc03c024b02Greg Kroah-HartmanEXPORT_SYMBOL(comedi_debug); 61ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefmodule_param(comedi_debug, int, 0644); 62ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#endif 63ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 646a9d7a21d710e544df20266b83b7829d9f7a1020Ian Abbottint comedi_autoconfig = 1; 656a9d7a21d710e544df20266b83b7829d9f7a1020Ian Abbottmodule_param(comedi_autoconfig, bool, 0444); 666a9d7a21d710e544df20266b83b7829d9f7a1020Ian Abbott 6792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int comedi_num_legacy_minors; 681dd33ab8a9397793d65b9fc090174ff7cdfaff95Bernd Porrmodule_param(comedi_num_legacy_minors, int, 0444); 691dd33ab8a9397793d65b9fc090174ff7cdfaff95Bernd Porr 70ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic DEFINE_SPINLOCK(comedi_file_info_table_lock); 71476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmanstatic struct comedi_device_file_info 720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral*comedi_file_info_table[COMEDI_NUM_MINORS]; 73476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman 740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_devconfig_ioctl(struct comedi_device *dev, 7592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_devconfig __user *arg); 7692d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_bufconfig_ioctl(struct comedi_device *dev, 7792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_bufconfig __user *arg); 780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_devinfo_ioctl(struct comedi_device *dev, 7992d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_devinfo __user *arg, 8092d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct file *file); 810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_subdinfo_ioctl(struct comedi_device *dev, 8292d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_subdinfo __user *arg, void *file); 830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_chaninfo_ioctl(struct comedi_device *dev, 8492d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_chaninfo __user *arg); 8592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_bufinfo_ioctl(struct comedi_device *dev, 8653fa827e295d8b09a2446b3126577244644d256dIan Abbott struct comedi_bufinfo __user *arg, void *file); 8792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_cmd_ioctl(struct comedi_device *dev, 8892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_cmd __user *arg, void *file); 890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, 900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file); 910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, 920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file); 930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, 940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file); 9592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_cmdtest_ioctl(struct comedi_device *dev, 9692d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_cmd __user *arg, void *file); 9792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_insnlist_ioctl(struct comedi_device *dev, 9892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_insnlist __user *arg, void *file); 9992d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_insn_ioctl(struct comedi_device *dev, 10092d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_insn __user *arg, void *file); 1010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, 1020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file); 10371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton 1040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralextern void do_become_nonbusy(struct comedi_device *dev, 1050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s); 10634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s); 107ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 108ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic int comedi_fasync(int fd, struct file *file, int on); 109ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 11071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int is_device_busy(struct comedi_device *dev); 111883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic int resize_async_buffer(struct comedi_device *dev, 112883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *s, 113883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_async *async, unsigned new_size); 114883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 115883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess/* declarations for sysfs attribute files */ 116883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_max_read_buffer_kb; 117883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_read_buffer_kb; 118883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_max_write_buffer_kb; 119883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_write_buffer_kb; 120ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 121ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, 122476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman unsigned long arg) 123ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 124ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(file->f_dentry->d_inode); 125476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 126476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 12771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev; 128ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int rc; 129ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 13053b670a75bef4bf6484bbf6ca6a896c365676fd4Frank Mori Hess if (dev_file_info == NULL || dev_file_info->device == NULL) 13153b670a75bef4bf6484bbf6ca6a896c365676fd4Frank Mori Hess return -ENODEV; 13253b670a75bef4bf6484bbf6ca6a896c365676fd4Frank Mori Hess dev = dev_file_info->device; 13353b670a75bef4bf6484bbf6ca6a896c365676fd4Frank Mori Hess 134ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 135ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 136ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* Device config is special, because it must work on 137ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * an unconfigured device. */ 138ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (cmd == COMEDI_DEVCONFIG) { 13992d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_devconfig_ioctl(dev, 14092d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman (struct comedi_devconfig __user *)arg); 141ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 142ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 143ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 144ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!dev->attached) { 145ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor); 146ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef rc = -ENODEV; 147ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 148ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 149ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 150ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef switch (cmd) { 151ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_BUFCONFIG: 15292d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_bufconfig_ioctl(dev, 15392d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman (struct comedi_bufconfig __user *)arg); 154ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 155ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_DEVINFO: 15692d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg, 15792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman file); 158ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 159ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_SUBDINFO: 16092d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_subdinfo_ioctl(dev, 16192d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman (struct comedi_subdinfo __user *)arg, 16292d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman file); 163ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 164ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_CHANINFO: 16592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_chaninfo_ioctl(dev, (void __user *)arg); 166ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 167ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_RANGEINFO: 16892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_rangeinfo_ioctl(dev, (void __user *)arg); 169ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 170ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_BUFINFO: 17192d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_bufinfo_ioctl(dev, 17253fa827e295d8b09a2446b3126577244644d256dIan Abbott (struct comedi_bufinfo __user *)arg, 17353fa827e295d8b09a2446b3126577244644d256dIan Abbott file); 174ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 175ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_LOCK: 176ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef rc = do_lock_ioctl(dev, arg, file); 177ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 178ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_UNLOCK: 179ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef rc = do_unlock_ioctl(dev, arg, file); 180ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 181ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_CANCEL: 182ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef rc = do_cancel_ioctl(dev, arg, file); 183ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 184ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_CMD: 18592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file); 186ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 187ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_CMDTEST: 18892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg, 18992d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman file); 190ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 191ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_INSNLIST: 19292d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_insnlist_ioctl(dev, 19392d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman (struct comedi_insnlist __user *)arg, 19492d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman file); 195ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 196ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_INSN: 19792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg, 19892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman file); 199ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 200ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case COMEDI_POLL: 201ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef rc = do_poll_ioctl(dev, arg, file); 202ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 203ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef default: 204ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef rc = -ENOTTY; 205ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 206ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 207ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 208476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmandone: 209ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 210ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return rc; 211ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 212ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 213ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 214ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_DEVCONFIG 215ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef device config ioctl 216ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 217ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 218ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef pointer to devconfig structure 219ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 220ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 221ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devconfig structure at arg 222ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 223ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 224ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef none 225ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 2260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_devconfig_ioctl(struct comedi_device *dev, 22792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_devconfig __user *arg) 228ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2290707bb04be89b18ee83b5a997e36cc585f0b988dBill Pemberton struct comedi_devconfig it; 230ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret; 231ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned char *aux_data = NULL; 232ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int aux_len; 233ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 234ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!capable(CAP_SYS_ADMIN)) 235ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EPERM; 236ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 237ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (arg == NULL) { 238ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (is_device_busy(dev)) 239ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EBUSY; 240476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (dev->attached) { 241ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef struct module *driver_module = dev->driver->module; 242ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_device_detach(dev); 243ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef module_put(driver_module); 244ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 245ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 246ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 247ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2480707bb04be89b18ee83b5a997e36cc585f0b988dBill Pemberton if (copy_from_user(&it, arg, sizeof(struct comedi_devconfig))) 249ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 250ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 251ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef it.board_name[COMEDI_NAMELEN - 1] = 0; 252ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 253ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (comedi_aux_data(it.options, 0) && 254476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { 255ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int bit_shift; 256ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef aux_len = it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; 257ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (aux_len < 0) 258ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 259ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 260ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef aux_data = vmalloc(aux_len); 261ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!aux_data) 262ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENOMEM; 263ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 264ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_from_user(aux_data, 265476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_aux_data(it.options, 0), aux_len)) { 266ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef vfree(aux_data); 267ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 268ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 269ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef it.options[COMEDI_DEVCONF_AUX_DATA_LO] = 270476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman (unsigned long)aux_data; 271ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (sizeof(void *) > sizeof(int)) { 272ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bit_shift = sizeof(int) * 8; 273ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef it.options[COMEDI_DEVCONF_AUX_DATA_HI] = 274476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman ((unsigned long)aux_data) >> bit_shift; 275ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } else 276ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef it.options[COMEDI_DEVCONF_AUX_DATA_HI] = 0; 277ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 278ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 279ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = comedi_device_attach(dev, &it); 280476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (ret == 0) { 281476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (!try_module_get(dev->driver->module)) { 282ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_device_detach(dev); 283ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENOSYS; 284ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 285ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 286ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 287ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (aux_data) 288ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef vfree(aux_data); 289ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 290ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 291ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 292ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 293ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 294ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_BUFCONFIG 295ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef buffer configuration ioctl 296ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 297ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 298ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef pointer to bufconfig structure 299ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 300ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 301ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bufconfig at arg 302ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 303ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 304ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef modified bufconfig at arg 305ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 306ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 30792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_bufconfig_ioctl(struct comedi_device *dev, 30892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_bufconfig __user *arg) 309ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 310be6aba4a423629126f318d351b2d0eb00abb9dd5Bill Pemberton struct comedi_bufconfig bc; 311d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 31234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 313883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess int retval = 0; 314ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 315be6aba4a423629126f318d351b2d0eb00abb9dd5Bill Pemberton if (copy_from_user(&bc, arg, sizeof(struct comedi_bufconfig))) 316ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 317ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 318ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0) 319ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 320ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 321ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + bc.subdevice; 322ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async = s->async; 323ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 324ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!async) { 325ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("subdevice does not have async capability\n"); 326ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bc.size = 0; 327ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bc.maximum_size = 0; 328ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto copyback; 329ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 330ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 331ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (bc.maximum_size) { 332ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!capable(CAP_SYS_ADMIN)) 333ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EPERM; 334ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 335ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->max_bufsize = bc.maximum_size; 336ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 337ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 338ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (bc.size) { 339883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = resize_async_buffer(dev, s, async, bc.size); 340883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval < 0) 341883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 342ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 343ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 344ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bc.size = async->prealloc_bufsz; 345ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bc.maximum_size = async->max_bufsize; 346ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 347476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmancopyback: 348be6aba4a423629126f318d351b2d0eb00abb9dd5Bill Pemberton if (copy_to_user(arg, &bc, sizeof(struct comedi_bufconfig))) 349ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 350ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 351ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 352ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 353ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 354ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 355ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_DEVINFO 356ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef device info ioctl 357ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 358ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 359ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef pointer to devinfo structure 360ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 361ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 362ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef none 363ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 364ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 365ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devinfo structure 366ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 367ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 3680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_devinfo_ioctl(struct comedi_device *dev, 36992d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_devinfo __user *arg, 37092d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct file *file) 371ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 372063db04b8901c5cf84c552a5053748d183d34e61Bill Pemberton struct comedi_devinfo devinfo; 373ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(file->f_dentry->d_inode); 374476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 375476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 37634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *read_subdev = 377476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_read_subdevice(dev_file_info); 37834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *write_subdev = 379476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_write_subdevice(dev_file_info); 380ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 381ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef memset(&devinfo, 0, sizeof(devinfo)); 382ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 383ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* fill devinfo structure */ 384ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devinfo.version_code = COMEDI_VERSION_CODE; 385ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devinfo.n_subdevs = dev->n_subdevices; 386ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef memcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN); 387ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef memcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN); 388ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 389476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (read_subdev) 390ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devinfo.read_subdevice = read_subdev - dev->subdevices; 391476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman else 392ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devinfo.read_subdevice = -1; 393476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman 394476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (write_subdev) 395ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devinfo.write_subdevice = write_subdev - dev->subdevices; 396476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman else 397ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef devinfo.write_subdevice = -1; 398ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 399063db04b8901c5cf84c552a5053748d183d34e61Bill Pemberton if (copy_to_user(arg, &devinfo, sizeof(struct comedi_devinfo))) 400ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 401ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 402ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 403ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 404ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 405ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 406ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_SUBDINFO 407ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef subdevice info ioctl 408ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 409ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 410ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef pointer to array of subdevice info structures 411ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 412ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 413ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef none 414ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 415ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 416ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef array of subdevice info structures at arg 417ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 418ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 4190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_subdinfo_ioctl(struct comedi_device *dev, 42092d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_subdinfo __user *arg, void *file) 421ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 422ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret, i; 423bd52efbbcc9f5d70c736b9b73c82aee149da1fe5Bill Pemberton struct comedi_subdinfo *tmp, *us; 42434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 425ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 4260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral tmp = 4270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kcalloc(dev->n_subdevices, sizeof(struct comedi_subdinfo), 4280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral GFP_KERNEL); 429ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!tmp) 430ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENOMEM; 431ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 432ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* fill subdinfo structs */ 433ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef for (i = 0; i < dev->n_subdevices; i++) { 434ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + i; 435ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us = tmp + i; 436ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 437ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->type = s->type; 438ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->n_chan = s->n_chan; 439ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags = s->subdev_flags; 440ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (comedi_get_subdevice_runflags(s) & SRF_RUNNING) 441ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_RUNNING; 442ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#define TIMER_nanosec 5 /* backwards compatibility */ 443ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->timer_type = TIMER_nanosec; 444ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->len_chanlist = s->len_chanlist; 445ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->maxdata = s->maxdata; 446ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->range_table) { 447ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->range_type = 448476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman (i << 24) | (0 << 16) | (s->range_table->length); 449ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } else { 450ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->range_type = 0; /* XXX */ 451ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 452ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->flags = s->flags; 453ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 454ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy) 455ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_BUSY; 456ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy == file) 457ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_BUSY_OWNER; 458ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock) 459ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_LOCKED; 460ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock == file) 461ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_LOCK_OWNER; 462ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->maxdata && s->maxdata_list) 463ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_MAXDATA; 464ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->flaglist) 465ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_FLAGS; 466ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->range_table_list) 467ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_RANGETYPE; 468ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->do_cmd) 469ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->subd_flags |= SDF_CMD; 470ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 471ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->insn_bits != &insn_inval) 472ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->insn_bits_support = COMEDI_SUPPORTED; 473ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef else 474ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->insn_bits_support = COMEDI_UNSUPPORTED; 475ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 476ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef us->settling_time_0 = s->settling_time_0; 477ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 478ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 479ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = copy_to_user(arg, tmp, 480bd52efbbcc9f5d70c736b9b73c82aee149da1fe5Bill Pemberton dev->n_subdevices * sizeof(struct comedi_subdinfo)); 481ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 482ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(tmp); 483ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 484ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret ? -EFAULT : 0; 485ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 486ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 487ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 488ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_CHANINFO 489ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef subdevice info ioctl 490ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 491ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 492ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef pointer to chaninfo structure 493ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 494ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 495ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef chaninfo structure at arg 496ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 497ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 498ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arrays at elements of chaninfo structure 499ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 500ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 5010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_chaninfo_ioctl(struct comedi_device *dev, 50292d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_chaninfo __user *arg) 503ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 50434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 505a18b416dc11ff9596ebf2012b1d15f485b951b28Bill Pemberton struct comedi_chaninfo it; 506ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 507a18b416dc11ff9596ebf2012b1d15f485b951b28Bill Pemberton if (copy_from_user(&it, arg, sizeof(struct comedi_chaninfo))) 508ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 509ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 510ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (it.subdev >= dev->n_subdevices) 511ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 512ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + it.subdev; 513ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 514ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (it.maxdata_list) { 515ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->maxdata || !s->maxdata_list) 516ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 517ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_to_user(it.maxdata_list, s->maxdata_list, 518790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton s->n_chan * sizeof(unsigned int))) 519ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 520ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 521ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 522ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (it.flaglist) { 523ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->flaglist) 524ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 525ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_to_user(it.flaglist, s->flaglist, 526476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman s->n_chan * sizeof(unsigned int))) 527ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 528ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 529ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 530ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (it.rangelist) { 531ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i; 532ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 533ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->range_table_list) 534ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 535ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef for (i = 0; i < s->n_chan; i++) { 536ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int x; 537ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 538ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) | 539476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman (s->range_table_list[i]->length); 54081604d43ade6abd316444f99ddb633f2e5a3f3ebVasiliy Kulikov if (put_user(x, it.rangelist + i)) 54181604d43ade6abd316444f99ddb633f2e5a3f3ebVasiliy Kulikov return -EFAULT; 542ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 543476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman#if 0 544476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (copy_to_user(it.rangelist, s->range_type_list, 5450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s->n_chan * sizeof(unsigned int))) 546476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return -EFAULT; 547476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman#endif 548ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 549ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 550ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 551ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 552ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 553ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* 554ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_BUFINFO 555ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef buffer information ioctl 556ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 557ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 558ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef pointer to bufinfo structure 559ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 560ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 561ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bufinfo at arg 562ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 563ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 564ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef modified bufinfo at arg 565ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 566ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef */ 56792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_bufinfo_ioctl(struct comedi_device *dev, 56853fa827e295d8b09a2446b3126577244644d256dIan Abbott struct comedi_bufinfo __user *arg, void *file) 569ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 5709aa5339ac1eba5268df69bbcdf1abb9fae5afecaBill Pemberton struct comedi_bufinfo bi; 57134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 572d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 573ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 5749aa5339ac1eba5268df69bbcdf1abb9fae5afecaBill Pemberton if (copy_from_user(&bi, arg, sizeof(struct comedi_bufinfo))) 575ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 576ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 577ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0) 578ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 579ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 580ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + bi.subdevice; 58153fa827e295d8b09a2446b3126577244644d256dIan Abbott 58253fa827e295d8b09a2446b3126577244644d256dIan Abbott if (s->lock && s->lock != file) 58353fa827e295d8b09a2446b3126577244644d256dIan Abbott return -EACCES; 58453fa827e295d8b09a2446b3126577244644d256dIan Abbott 585ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async = s->async; 586ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 587ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!async) { 588ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("subdevice does not have async capability\n"); 589ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_write_ptr = 0; 590ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_read_ptr = 0; 591ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_write_count = 0; 592ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_read_count = 0; 5934772c018e35b6a21e8a8bde54568b59998540a16Ian Abbott bi.bytes_read = 0; 5944772c018e35b6a21e8a8bde54568b59998540a16Ian Abbott bi.bytes_written = 0; 595ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto copyback; 596ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 59753fa827e295d8b09a2446b3126577244644d256dIan Abbott if (!s->busy) { 59853fa827e295d8b09a2446b3126577244644d256dIan Abbott bi.bytes_read = 0; 59953fa827e295d8b09a2446b3126577244644d256dIan Abbott bi.bytes_written = 0; 60053fa827e295d8b09a2446b3126577244644d256dIan Abbott goto copyback_position; 60153fa827e295d8b09a2446b3126577244644d256dIan Abbott } 60253fa827e295d8b09a2446b3126577244644d256dIan Abbott if (s->busy != file) 60353fa827e295d8b09a2446b3126577244644d256dIan Abbott return -EACCES; 604ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 605ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) { 606ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read); 607ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_buf_read_free(async, bi.bytes_read); 608ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 609ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | 610476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman SRF_RUNNING)) 611476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman && async->buf_write_count == async->buf_read_count) { 612ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef do_become_nonbusy(dev, s); 613ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 614ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 615ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 616ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)) { 617ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.bytes_written = 618476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_buf_write_alloc(async, bi.bytes_written); 619ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_buf_write_free(async, bi.bytes_written); 620ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 621ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 62253fa827e295d8b09a2446b3126577244644d256dIan Abbottcopyback_position: 623ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_write_count = async->buf_write_count; 624ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_write_ptr = async->buf_write_ptr; 625ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_read_count = async->buf_read_count; 626ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef bi.buf_read_ptr = async->buf_read_ptr; 627ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 628476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmancopyback: 6299aa5339ac1eba5268df69bbcdf1abb9fae5afecaBill Pemberton if (copy_to_user(arg, &bi, sizeof(struct comedi_bufinfo))) 630ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 631ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 632ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 633ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 634ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 6350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, 6360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data, void *file); 637ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 63820617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * COMEDI_INSNLIST 63920617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * synchronous instructions 640ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * 64120617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * arg: 64220617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * pointer to sync cmd structure 643ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * 64420617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * reads: 64520617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * sync cmd struct at arg 64620617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * instruction list 64720617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * data (for writes) 648ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * 64920617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * writes: 65020617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * data (for reads) 651ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef */ 652ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* arbitrary limits */ 653ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#define MAX_SAMPLES 256 65492d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_insnlist_ioctl(struct comedi_device *dev, 65592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_insnlist __user *arg, void *file) 656ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 657da613f4fabb43b8bc551bb874792e1f22a698696Bill Pemberton struct comedi_insnlist insnlist; 65890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton struct comedi_insn *insns = NULL; 659790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int *data = NULL; 660ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i = 0; 661ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret = 0; 662ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 663da613f4fabb43b8bc551bb874792e1f22a698696Bill Pemberton if (copy_from_user(&insnlist, arg, sizeof(struct comedi_insnlist))) 664ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 665ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 666790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL); 667ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!data) { 668ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("kmalloc failed\n"); 669ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -ENOMEM; 670ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 671ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 672ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 6730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral insns = 6740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); 675ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!insns) { 676ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("kmalloc failed\n"); 677ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -ENOMEM; 678ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 679ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 680ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 681ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_from_user(insns, insnlist.insns, 68290035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton sizeof(struct comedi_insn) * insnlist.n_insns)) { 683ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("copy_from_user failed\n"); 684ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 685ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 686ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 687ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 688ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef for (i = 0; i < insnlist.n_insns; i++) { 689ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insns[i].n > MAX_SAMPLES) { 690ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("number of samples too large\n"); 691ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 692ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 693ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 694ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insns[i].insn & INSN_MASK_WRITE) { 695ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_from_user(data, insns[i].data, 696790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton insns[i].n * sizeof(unsigned int))) { 697ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("copy_from_user failed\n"); 698ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 699ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 700ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 701ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 702ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = parse_insn(dev, insns + i, data, file); 703ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret < 0) 704ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 705ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insns[i].insn & INSN_MASK_READ) { 706ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_to_user(insns[i].data, data, 707790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton insns[i].n * sizeof(unsigned int))) { 708ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("copy_to_user failed\n"); 709ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 710ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 711ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 712ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 713ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (need_resched()) 714ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef schedule(); 715ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 716ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 717476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmanerror: 718476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman kfree(insns); 719476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman kfree(data); 720ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 721ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret < 0) 722ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 723ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return i; 724ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 725ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 7260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int check_insn_config_length(struct comedi_insn *insn, 7270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data) 728ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 729476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (insn->n < 1) 730476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return -EINVAL; 731ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 732ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef switch (data[0]) { 733ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_DIO_OUTPUT: 734ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_DIO_INPUT: 735ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_DISARM: 736ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_RESET: 737ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n == 1) 738ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 739ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 740ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_ARM: 741ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_DIO_QUERY: 742ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_BLOCK_SIZE: 743ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_FILTER: 744ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_SERIAL_CLOCK: 745ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_BIDIRECTIONAL_DATA: 746ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_ALT_SOURCE: 747ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_SET_COUNTER_MODE: 748ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_8254_READ_STATUS: 749ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_SET_ROUTING: 750ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_GET_ROUTING: 751ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_GET_PWM_STATUS: 752ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_PWM_SET_PERIOD: 753ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_PWM_GET_PERIOD: 754ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n == 2) 755ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 756ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 757ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_SET_GATE_SRC: 758ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_GET_GATE_SRC: 759ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_SET_CLOCK_SRC: 760ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_GET_CLOCK_SRC: 761ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_SET_OTHER_SRC: 762ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_GET_COUNTER_STATUS: 763ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_PWM_SET_H_BRIDGE: 764ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_PWM_GET_H_BRIDGE: 765ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: 766ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n == 3) 767ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 768ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 769ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_PWM_OUTPUT: 770ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG_ANALOG_TRIG: 771ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n == 5) 772ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 773ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 7740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* by default we allow the insn since we don't have checks for 7750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * all possible cases yet */ 776ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef default: 7773fffdf2045d0dbca3833f8f54ae41ce5f2c0b8faMark Rankilor printk(KERN_WARNING 7783fffdf2045d0dbca3833f8f54ae41ce5f2c0b8faMark Rankilor "comedi: no check for data length of config insn id " 7790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "%i is implemented.\n" 7800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral " Add a check to %s in %s.\n" 7810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral " Assuming n=%i is correct.\n", data[0], __func__, 7820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral __FILE__, insn->n); 783ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 784ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 785ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 786ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 787ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 788ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 7890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, 7900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data, void *file) 791ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 79234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 793ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret = 0; 794ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i; 795ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 796ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->insn & INSN_MASK_SPECIAL) { 797ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* a non-subdevice instruction */ 798ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 799ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef switch (insn->insn) { 800ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_GTOD: 801ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef { 802ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef struct timeval tv; 803ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 804ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n != 2) { 805ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 806ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 807ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 808ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 809ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef do_gettimeofday(&tv); 810ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef data[0] = tv.tv_sec; 811ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef data[1] = tv.tv_usec; 812ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = 2; 813ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 814ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 815ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 816ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_WAIT: 817ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n != 1 || data[0] >= 100000) { 818ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 819ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 820ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 821ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef udelay(data[0] / 1000); 822ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = 1; 823ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 824ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_INTTRIG: 825ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n != 1) { 826ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 827ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 828ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 829ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->subdev >= dev->n_subdevices) { 830ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("%d not usable subdevice\n", 831ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef insn->subdev); 832ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 833ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 834ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 835ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + insn->subdev; 836ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->async) { 837ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no async\n"); 838ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 839ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 840ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 841ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->async->inttrig) { 842ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no inttrig\n"); 843ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EAGAIN; 844ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 845ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 846ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->async->inttrig(dev, s, insn->data[0]); 847ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret >= 0) 848ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = 1; 849ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 850ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef default: 851ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("invalid insn\n"); 852ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 853ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 854ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 855ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } else { 856ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* a subdevice instruction */ 857790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int maxdata; 858ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 859ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->subdev >= dev->n_subdevices) { 860ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("subdevice %d out of range\n", insn->subdev); 861ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 862ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto out; 863ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 864ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + insn->subdev; 865ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 866ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->type == COMEDI_SUBD_UNUSED) { 867ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("%d not usable subdevice\n", insn->subdev); 868ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EIO; 869ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto out; 870ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 871ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 872ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* are we locked? (ioctl lock) */ 873ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock && s->lock != file) { 874ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("device locked\n"); 875ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EACCES; 876ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto out; 877ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 878ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 8790fd0ca75fd9eb0e9cde49c28ad227c2d8d049366Greg Kroah-Hartman ret = comedi_check_chanlist(s, 1, &insn->chanspec); 880476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (ret < 0) { 881ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 882ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("bad chanspec\n"); 883ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto out; 884ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 885ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 886ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy) { 887ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EBUSY; 888ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto out; 889ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 890ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* This looks arbitrary. It is. */ 891ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->busy = &parse_insn; 892ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef switch (insn->insn) { 893ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_READ: 894ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->insn_read(dev, s, insn, data); 895ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 896ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_WRITE: 897ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef maxdata = s->maxdata_list 898476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman ? s->maxdata_list[CR_CHAN(insn->chanspec)] 899476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman : s->maxdata; 900ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef for (i = 0; i < insn->n; ++i) { 901ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (data[i] > maxdata) { 902ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 903ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("bad data value(s)\n"); 904ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 905ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 906ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 907ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret == 0) 908ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->insn_write(dev, s, insn, data); 909ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 910ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_BITS: 911ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn->n != 2) { 912ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 9132f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott } else { 9142f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott /* Most drivers ignore the base channel in 9152f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott * insn->chanspec. Fix this here if 9162f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott * the subdevice has <= 32 channels. */ 9172f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott unsigned int shift; 9182f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott unsigned int orig_mask; 9192f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott 9202f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott orig_mask = data[0]; 9212f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott if (s->n_chan <= 32) { 9222f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott shift = CR_CHAN(insn->chanspec); 9232f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott if (shift > 0) { 9242f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott insn->chanspec = 0; 9252f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott data[0] <<= shift; 9262f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott data[1] <<= shift; 9272f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott } 9282f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott } else 9292f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott shift = 0; 9302f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott ret = s->insn_bits(dev, s, insn, data); 9312f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott data[0] = orig_mask; 9322f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott if (shift > 0) 9332f644ccfc5a3195290d12b8eedf18a37bba27d98Ian Abbott data[1] >>= shift; 934ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 935ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 936ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef case INSN_CONFIG: 937ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = check_insn_config_length(insn, data); 938ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret) 939ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 940ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->insn_config(dev, s, insn, data); 941ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 942ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef default: 943ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 944ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 945ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 946ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 947ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->busy = NULL; 948ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 949ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 950476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmanout: 951ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 952ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 953ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 954ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 95520617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * COMEDI_INSN 95620617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * synchronous instructions 957ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * 95820617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * arg: 95920617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * pointer to insn 960ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * 96120617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * reads: 96220617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * struct comedi_insn struct at arg 96320617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * data (for writes) 964ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * 96520617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * writes: 96620617f22b006e12b81602d80d85f8f3f7efdef45Pieter De Praetere * data (for reads) 967ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef */ 96892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_insn_ioctl(struct comedi_device *dev, 96992d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_insn __user *arg, void *file) 970ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 97190035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton struct comedi_insn insn; 972790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int *data = NULL; 973ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret = 0; 974ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 975790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton data = kmalloc(sizeof(unsigned int) * MAX_SAMPLES, GFP_KERNEL); 976ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!data) { 977ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -ENOMEM; 978ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 979ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 980ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 98190035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton if (copy_from_user(&insn, arg, sizeof(struct comedi_insn))) { 982ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 983ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 984ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 985ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 986ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* This is where the behavior of insn and insnlist deviate. */ 987ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn.n > MAX_SAMPLES) 988ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef insn.n = MAX_SAMPLES; 989ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn.insn & INSN_MASK_WRITE) { 99021fe2eea6381845956322e63e441f351774de7f9Mark if (copy_from_user(data, 99121fe2eea6381845956322e63e441f351774de7f9Mark insn.data, 99221fe2eea6381845956322e63e441f351774de7f9Mark insn.n * sizeof(unsigned int))) { 993ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 994ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 995ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 996ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 997ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = parse_insn(dev, &insn, data, file); 998ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret < 0) 999ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 1000ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (insn.insn & INSN_MASK_READ) { 100121fe2eea6381845956322e63e441f351774de7f9Mark if (copy_to_user(insn.data, 100221fe2eea6381845956322e63e441f351774de7f9Mark data, 100321fe2eea6381845956322e63e441f351774de7f9Mark insn.n * sizeof(unsigned int))) { 1004ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 1005ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto error; 1006ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1007ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1008ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = insn.n; 1009ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1010476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmanerror: 1011476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman kfree(data); 1012ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1013ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 1014ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1015ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1016181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartmanstatic void comedi_set_subdevice_runflags(struct comedi_subdevice *s, 1017181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman unsigned mask, unsigned bits) 1018181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman{ 1019181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman unsigned long flags; 1020181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman 1021181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman spin_lock_irqsave(&s->spin_lock, flags); 1022181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman s->runflags &= ~mask; 1023181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman s->runflags |= (bits & mask); 1024181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman spin_unlock_irqrestore(&s->spin_lock, flags); 1025181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman} 1026181bd67bf5780b941f2cba6247ed1c0cdfce468aGreg Kroah-Hartman 102792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_cmd_ioctl(struct comedi_device *dev, 102892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_cmd __user *cmd, void *file) 1029ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1030ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd user_cmd; 103134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1032d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 1033ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret = 0; 103492d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman unsigned int __user *chanlist_saver = NULL; 1035ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 103692d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman if (copy_from_user(&user_cmd, cmd, sizeof(struct comedi_cmd))) { 1037ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("bad cmd address\n"); 1038ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 1039ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1040476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* save user's chanlist pointer so it can be restored later */ 1041ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef chanlist_saver = user_cmd.chanlist; 1042ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1043ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (user_cmd.subdev >= dev->n_subdevices) { 1044ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("%d no such subdevice\n", user_cmd.subdev); 1045ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENODEV; 1046ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1047ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1048ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + user_cmd.subdev; 1049ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async = s->async; 1050ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1051ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->type == COMEDI_SUBD_UNUSED) { 1052ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("%d not valid subdevice\n", user_cmd.subdev); 1053ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EIO; 1054ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1055ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1056ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->do_cmd || !s->do_cmdtest || !s->async) { 1057ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("subdevice %i does not support commands\n", 1058ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.subdev); 1059ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EIO; 1060ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1061ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1062ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* are we locked? (ioctl lock) */ 1063ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock && s->lock != file) { 1064ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("subdevice locked\n"); 1065ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EACCES; 1066ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1067ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1068ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* are we busy? */ 1069ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy) { 1070ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("subdevice busy\n"); 1071ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EBUSY; 1072ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1073ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->busy = file; 1074ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1075ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* make sure channel/gain list isn't too long */ 1076ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (user_cmd.chanlist_len > s->len_chanlist) { 1077ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("channel/gain list too long %u > %d\n", 1078ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.chanlist_len, s->len_chanlist); 1079ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 1080ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1081ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1082ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1083ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* make sure channel/gain list isn't too short */ 1084ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (user_cmd.chanlist_len < 1) { 1085ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("channel/gain list too short %u < 1\n", 1086ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.chanlist_len); 1087ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 1088ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1089ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1090ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1091476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman kfree(async->cmd.chanlist); 1092ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->cmd = user_cmd; 1093ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->cmd.data = NULL; 1094ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* load channel/gain list */ 1095ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->cmd.chanlist = 1096476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL); 1097ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!async->cmd.chanlist) { 1098ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("allocation failed\n"); 1099ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -ENOMEM; 1100ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1101ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1102ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1103ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_from_user(async->cmd.chanlist, user_cmd.chanlist, 1104476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman async->cmd.chanlist_len * sizeof(int))) { 1105ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("fault reading chanlist\n"); 1106ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 1107ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1108ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1109ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1110ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* make sure each element in channel/gain list is valid */ 111121fe2eea6381845956322e63e441f351774de7f9Mark ret = comedi_check_chanlist(s, 111221fe2eea6381845956322e63e441f351774de7f9Mark async->cmd.chanlist_len, 111321fe2eea6381845956322e63e441f351774de7f9Mark async->cmd.chanlist); 1114476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (ret < 0) { 1115ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("bad chanlist\n"); 1116ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1117ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1118ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1119ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->do_cmdtest(dev, s, &async->cmd); 1120ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1121ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (async->cmd.flags & TRIG_BOGUS || ret) { 1122ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("test returned %d\n", ret); 1123ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd = async->cmd; 1124476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* restore chanlist pointer before copying back */ 1125ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.chanlist = chanlist_saver; 1126ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.data = NULL; 112792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman if (copy_to_user(cmd, &user_cmd, sizeof(struct comedi_cmd))) { 1128ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("fault writing cmd\n"); 1129ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 1130ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1131ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1132ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EAGAIN; 1133ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1134ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1135ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1136ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!async->prealloc_bufsz) { 1137ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -ENOMEM; 1138ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no buffer (?)\n"); 1139ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1140ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1141ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1142ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_reset_async_buf(async); 1143ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1144ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->cb_mask = 1145476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR | 1146476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman COMEDI_CB_OVERFLOW; 1147476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (async->cmd.flags & TRIG_WAKE_EOS) 1148ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->cb_mask |= COMEDI_CB_EOS; 1149ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1150ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING); 1151ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1152ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->do_cmd(dev, s); 1153ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret == 0) 1154ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 1155ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1156476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmancleanup: 1157ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef do_become_nonbusy(dev, s); 1158ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1159ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 1160ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1161ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1162ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 1163ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_CMDTEST 1164ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef command testing ioctl 1165ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1166ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 1167ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef pointer to cmd structure 1168ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1169ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 1170ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef cmd structure at arg 1171ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef channel/range list 1172ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1173ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 1174ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef modified cmd structure at arg 1175ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1176ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 117792d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic int do_cmdtest_ioctl(struct comedi_device *dev, 117892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman struct comedi_cmd __user *arg, void *file) 1179ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1180ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton struct comedi_cmd user_cmd; 118134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1182ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret = 0; 1183ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned int *chanlist = NULL; 118492d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman unsigned int __user *chanlist_saver = NULL; 1185ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1186ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) { 1187ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("bad cmd address\n"); 1188ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EFAULT; 1189ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1190476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* save user's chanlist pointer so it can be restored later */ 1191ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef chanlist_saver = user_cmd.chanlist; 1192ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1193ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (user_cmd.subdev >= dev->n_subdevices) { 1194ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("%d no such subdevice\n", user_cmd.subdev); 1195ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENODEV; 1196ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1197ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1198ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + user_cmd.subdev; 1199ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->type == COMEDI_SUBD_UNUSED) { 1200ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("%d not valid subdevice\n", user_cmd.subdev); 1201ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EIO; 1202ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1203ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1204ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->do_cmd || !s->do_cmdtest) { 1205ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("subdevice %i does not support commands\n", 1206ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.subdev); 1207ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EIO; 1208ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1209ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1210ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* make sure channel/gain list isn't too long */ 1211ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (user_cmd.chanlist_len > s->len_chanlist) { 1212ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("channel/gain list too long %d > %d\n", 1213ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.chanlist_len, s->len_chanlist); 1214ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EINVAL; 1215ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1216ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1217ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1218ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* load channel/gain list */ 1219ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (user_cmd.chanlist) { 1220ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef chanlist = 1221476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman kmalloc(user_cmd.chanlist_len * sizeof(int), GFP_KERNEL); 1222ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!chanlist) { 1223ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("allocation failed\n"); 1224ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -ENOMEM; 1225ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1226ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1227ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1228ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (copy_from_user(chanlist, user_cmd.chanlist, 1229476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman user_cmd.chanlist_len * sizeof(int))) { 1230ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("fault reading chanlist\n"); 1231ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 1232ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1233ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1234ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1235ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* make sure each element in channel/gain list is valid */ 12360fd0ca75fd9eb0e9cde49c28ad227c2d8d049366Greg Kroah-Hartman ret = comedi_check_chanlist(s, user_cmd.chanlist_len, chanlist); 1237476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (ret < 0) { 1238ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("bad chanlist\n"); 1239ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1240ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1241ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1242ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.chanlist = chanlist; 1243ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1244ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1245ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->do_cmdtest(dev, s, &user_cmd); 1246ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1247476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* restore chanlist pointer before copying back */ 1248ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef user_cmd.chanlist = chanlist_saver; 1249ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1250ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) { 1251ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("bad cmd address\n"); 1252ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EFAULT; 1253ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto cleanup; 1254ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1255476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmancleanup: 1256476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman kfree(chanlist); 1257ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1258ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 1259ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1260ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1261ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 1262ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_LOCK 1263ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef lock subdevice 1264ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1265ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 1266ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef subdevice number 1267ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1268ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 1269ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef none 1270ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1271ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 1272ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef none 1273ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1274ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 1275ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 12760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, 12770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file) 1278ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1279ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret = 0; 1280ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long flags; 128134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1282ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1283ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (arg >= dev->n_subdevices) 1284ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 1285ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + arg; 1286ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 12875f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&s->spin_lock, flags); 1288476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (s->busy || s->lock) 1289ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = -EBUSY; 1290476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman else 1291ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->lock = file; 12925f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&s->spin_lock, flags); 1293ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1294c5274ab09747d0ef829f9b8f040756758e5de55cGreg Dietsche#if 0 1295ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (ret < 0) 1296ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 1297ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1298ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock_f) 1299ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->lock_f(dev, s); 1300ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#endif 1301ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1302ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 1303ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1304ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1305ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 1306ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_UNLOCK 1307ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unlock subdevice 1308ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1309ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 1310ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef subdevice number 1311ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1312ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 1313ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef none 1314ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1315ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 1316ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef none 1317ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1318ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef This function isn't protected by the semaphore, since 1319ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef we already own the lock. 1320ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 13210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, 13220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file) 1323ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 132434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1325ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1326ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (arg >= dev->n_subdevices) 1327ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 1328ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + arg; 1329ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1330ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy) 1331ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EBUSY; 1332ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1333ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock && s->lock != file) 1334ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EACCES; 1335ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1336ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock == file) { 1337ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#if 0 1338ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->unlock) 1339ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->unlock(dev, s); 1340ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#endif 1341ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1342ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->lock = NULL; 1343ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1344ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1345ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 1346ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1347ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1348ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 1349ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_CANCEL 1350ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef cancel acquisition ioctl 1351ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1352ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 1353ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef subdevice number 1354ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1355ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 1356ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef nothing 1357ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1358ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 1359ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef nothing 1360ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1361ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 13620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, 13630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file) 1364ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 136534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1366ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1367ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (arg >= dev->n_subdevices) 1368ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 1369ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + arg; 1370ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->async == NULL) 1371ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 1372ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1373ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock && s->lock != file) 1374ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EACCES; 1375ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1376ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->busy) 1377ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 1378ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1379ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy != file) 1380ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EBUSY; 1381ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1382ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return do_cancel(dev, s); 1383ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1384ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1385ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 1386ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef COMEDI_POLL ioctl 1387ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef instructs driver to synchronize buffers 1388ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1389ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef arg: 1390ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef subdevice number 1391ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1392ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef reads: 1393ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef nothing 1394ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1395ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef writes: 1396ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef nothing 1397ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1398ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef*/ 13990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int do_poll_ioctl(struct comedi_device *dev, unsigned int arg, 14000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral void *file) 1401ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 140234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1403ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1404ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (arg >= dev->n_subdevices) 1405ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 1406ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + arg; 1407ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1408ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->lock && s->lock != file) 1409ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EACCES; 1410ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1411ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->busy) 1412ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 1413ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1414ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy != file) 1415ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EBUSY; 1416ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1417ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->poll) 1418ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return s->poll(dev, s); 1419ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1420ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EINVAL; 1421ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1422ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 142334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 1424ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1425ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int ret = 0; 1426ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1427ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) && s->cancel) 1428ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef ret = s->cancel(dev, s); 1429ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1430ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef do_become_nonbusy(dev, s); 1431ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1432ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return ret; 1433ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1434ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 143592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic void comedi_unmap(struct vm_area_struct *area) 1436ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1437d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 143871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev; 1439ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1440ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async = area->vm_private_data; 1441ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef dev = async->subdevice->device; 1442ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1443ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 1444ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->mmap_count--; 1445ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1446ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1447ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1448ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic struct vm_operations_struct comedi_vm_ops = { 14490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .close = comedi_unmap, 1450ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef}; 1451ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1452ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic int comedi_mmap(struct file *file, struct vm_area_struct *vma) 1453ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1454ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(file->f_dentry->d_inode); 1455476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 1456476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 145771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = dev_file_info->device; 1458d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = NULL; 1459ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long start = vma->vm_start; 1460ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long size; 1461ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int n_pages; 1462ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i; 1463ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int retval; 146434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1465ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1466ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 1467ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!dev->attached) { 1468ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no driver configured on comedi%i\n", dev->minor); 1469ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -ENODEV; 1470ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1471ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1472476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (vma->vm_flags & VM_WRITE) 1473ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = comedi_get_write_subdevice(dev_file_info); 1474476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman else 1475ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = comedi_get_read_subdevice(dev_file_info); 1476476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman 1477ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s == NULL) { 1478ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EINVAL; 1479ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1480ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1481ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async = s->async; 1482ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (async == NULL) { 1483ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EINVAL; 1484ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1485ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1486ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1487ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (vma->vm_pgoff != 0) { 1488ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("comedi: mmap() offset must be 0.\n"); 1489ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EINVAL; 1490ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1491ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1492ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1493ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef size = vma->vm_end - vma->vm_start; 1494ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (size > async->prealloc_bufsz) { 1495ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EFAULT; 1496ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1497ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1498ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (size & (~PAGE_MASK)) { 1499ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EFAULT; 1500ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1501ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1502ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1503ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef n_pages = size >> PAGE_SHIFT; 1504ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef for (i = 0; i < n_pages; ++i) { 1505ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (remap_pfn_range(vma, start, 15060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral page_to_pfn(virt_to_page 15070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (async->buf_page_list 15080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral [i].virt_addr)), PAGE_SIZE, 15090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral PAGE_SHARED)) { 1510ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EAGAIN; 1511ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1512ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1513ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef start += PAGE_SIZE; 1514ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1515ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1516ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef vma->vm_ops = &comedi_vm_ops; 1517ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef vma->vm_private_data = async; 1518ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1519ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->mmap_count++; 1520ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1521ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = 0; 1522476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmandone: 1523ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1524ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return retval; 1525ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1526ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 15270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic unsigned int comedi_poll(struct file *file, poll_table * wait) 1528ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1529ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned int mask = 0; 1530ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(file->f_dentry->d_inode); 1531476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 1532476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 153371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = dev_file_info->device; 153434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *read_subdev; 153534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *write_subdev; 1536ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1537ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 1538ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!dev->attached) { 1539ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no driver configured on comedi%i\n", dev->minor); 1540ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1541ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 1542ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1543ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1544ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mask = 0; 1545ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef read_subdev = comedi_get_read_subdevice(dev_file_info); 1546ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (read_subdev) { 1547ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef poll_wait(file, &read_subdev->async->wait_head, wait); 1548ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!read_subdev->busy 1549476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman || comedi_buf_read_n_available(read_subdev->async) > 0 1550476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman || !(comedi_get_subdevice_runflags(read_subdev) & 1551476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman SRF_RUNNING)) { 1552ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mask |= POLLIN | POLLRDNORM; 1553ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1554ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1555ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef write_subdev = comedi_get_write_subdevice(dev_file_info); 1556ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (write_subdev) { 1557ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef poll_wait(file, &write_subdev->async->wait_head, wait); 1558476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_buf_write_alloc(write_subdev->async, 1559476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman write_subdev->async->prealloc_bufsz); 1560ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!write_subdev->busy 1561476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman || !(comedi_get_subdevice_runflags(write_subdev) & 1562476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman SRF_RUNNING) 1563476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman || comedi_buf_write_n_allocated(write_subdev->async) >= 1564476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman bytes_per_sample(write_subdev->async->subdevice)) { 1565ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mask |= POLLOUT | POLLWRNORM; 1566ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1567ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1568ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1569ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1570ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return mask; 1571ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1572ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 157392d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic ssize_t comedi_write(struct file *file, const char __user *buf, 157492d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartman size_t nbytes, loff_t *offset) 1575ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 157634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1577d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 1578ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int n, m, count = 0, retval = 0; 1579ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DECLARE_WAITQUEUE(wait, current); 1580ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(file->f_dentry->d_inode); 1581476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 1582476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 158371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = dev_file_info->device; 1584ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1585ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!dev->attached) { 1586ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no driver configured on comedi%i\n", dev->minor); 1587ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -ENODEV; 1588ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1589ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1590ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1591ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = comedi_get_write_subdevice(dev_file_info); 1592ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s == NULL) { 1593ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EIO; 1594ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1595ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1596ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async = s->async; 1597ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1598ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!nbytes) { 1599ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = 0; 1600ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1601ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1602ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->busy) { 1603ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = 0; 1604ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1605ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1606ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy != file) { 1607ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EACCES; 1608ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1609ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1610ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef add_wait_queue(&async->wait_head, &wait); 1611ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef while (nbytes > 0 && !retval) { 1612ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef set_current_state(TASK_INTERRUPTIBLE); 1613ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1614d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) { 1615d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott if (count == 0) { 1616d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott if (comedi_get_subdevice_runflags(s) & 1617d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott SRF_ERROR) { 1618d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott retval = -EPIPE; 1619d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott } else { 1620d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott retval = 0; 1621d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott } 1622d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott do_become_nonbusy(dev, s); 1623d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott } 1624d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott break; 1625d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott } 1626d261154057c27f6c1d256b6198b0ad08733f1758Ian Abbott 1627ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef n = nbytes; 1628ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1629ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef m = n; 1630476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (async->buf_write_ptr + m > async->prealloc_bufsz) 1631ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef m = async->prealloc_bufsz - async->buf_write_ptr; 1632ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_buf_write_alloc(async, async->prealloc_bufsz); 1633476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (m > comedi_buf_write_n_allocated(async)) 1634ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef m = comedi_buf_write_n_allocated(async); 1635ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (m < n) 1636ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef n = m; 1637ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1638ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (n == 0) { 1639ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (file->f_flags & O_NONBLOCK) { 1640ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EAGAIN; 1641ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1642ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1643ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (signal_pending(current)) { 1644ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -ERESTARTSYS; 1645ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1646ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1647ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef schedule(); 1648476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (!s->busy) 1649ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1650ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy != file) { 1651ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EACCES; 1652ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1653ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1654ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef continue; 1655ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1656ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1657ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef m = copy_from_user(async->prealloc_buf + async->buf_write_ptr, 1658476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman buf, n); 1659ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (m) { 1660ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef n -= m; 1661ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EFAULT; 1662ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1663ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_buf_write_free(async, n); 1664ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1665ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef count += n; 1666ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef nbytes -= n; 1667ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1668ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef buf += n; 1669ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; /* makes device work like a pipe */ 1670ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1671ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef set_current_state(TASK_RUNNING); 1672ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef remove_wait_queue(&async->wait_head, &wait); 1673ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1674ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefdone: 1675476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return count ? count : retval; 1676ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1677ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 167892d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, 16796705b68d0be284e2f9949f3657ea65d426d0f988Andrea Gelmini loff_t *offset) 1680ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 168134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 1682d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async; 1683ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int n, m, count = 0, retval = 0; 1684ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DECLARE_WAITQUEUE(wait, current); 1685ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(file->f_dentry->d_inode); 1686476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 1687476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 168871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = dev_file_info->device; 1689ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1690ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!dev->attached) { 1691ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("no driver configured on comedi%i\n", dev->minor); 1692ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -ENODEV; 1693ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1694ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1695ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1696ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = comedi_get_read_subdevice(dev_file_info); 1697ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s == NULL) { 1698ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EIO; 1699ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1700ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1701ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async = s->async; 1702ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!nbytes) { 1703ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = 0; 1704ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1705ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1706ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->busy) { 1707ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = 0; 1708ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1709ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1710ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy != file) { 1711ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EACCES; 1712ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto done; 1713ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1714ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1715ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef add_wait_queue(&async->wait_head, &wait); 1716ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef while (nbytes > 0 && !retval) { 1717ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef set_current_state(TASK_INTERRUPTIBLE); 1718ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1719ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef n = nbytes; 1720ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1721ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef m = comedi_buf_read_n_available(async); 1722476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* printk("%d available\n",m); */ 1723476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (async->buf_read_ptr + m > async->prealloc_bufsz) 1724ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef m = async->prealloc_bufsz - async->buf_read_ptr; 1725476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* printk("%d contiguous\n",m); */ 1726ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (m < n) 1727ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef n = m; 1728ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1729ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (n == 0) { 1730ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) { 1731ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef do_become_nonbusy(dev, s); 1732ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (comedi_get_subdevice_runflags(s) & 1733476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman SRF_ERROR) { 1734ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EPIPE; 1735ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } else { 1736ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = 0; 1737ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1738ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1739ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1740ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (file->f_flags & O_NONBLOCK) { 1741ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EAGAIN; 1742ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1743ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1744ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (signal_pending(current)) { 1745ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -ERESTARTSYS; 1746ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1747ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1748ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef schedule(); 1749ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!s->busy) { 1750ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = 0; 1751ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1752ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1753ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy != file) { 1754ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EACCES; 1755ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 1756ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1757ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef continue; 1758ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1759ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef m = copy_to_user(buf, async->prealloc_buf + 1760476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman async->buf_read_ptr, n); 1761ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (m) { 1762ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef n -= m; 1763ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = -EFAULT; 1764ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1765ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1766ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_buf_read_alloc(async, n); 1767ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_buf_read_free(async, n); 1768ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1769ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef count += n; 1770ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef nbytes -= n; 1771ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1772ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef buf += n; 1773ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; /* makes device work like a pipe */ 1774ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1775ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING)) && 1776476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman async->buf_read_count - async->buf_write_count == 0) { 1777ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef do_become_nonbusy(dev, s); 1778ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1779ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef set_current_state(TASK_RUNNING); 1780ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef remove_wait_queue(&async->wait_head, &wait); 1781ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1782ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefdone: 1783476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return count ? count : retval; 1784ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1785ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1786ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef/* 1787ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef This function restores a subdevice to an idle state. 1788ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef */ 178934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonvoid do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) 1790ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1791d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 1792ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1793ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_set_subdevice_runflags(s, SRF_RUNNING, 0); 1794ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (async) { 1795ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_reset_async_buf(async); 1796ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->inttrig = NULL; 1797ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } else { 1798476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman printk(KERN_ERR 1799476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman "BUG: (?) do_become_nonbusy called with async=0\n"); 1800ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1801ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1802ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->busy = NULL; 1803ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1804ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1805ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic int comedi_open(struct inode *inode, struct file *file) 1806ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1807ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(inode); 1808476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 1809476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 18100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_device *dev = 18110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_file_info ? dev_file_info->device : NULL; 1812979200719d35934367bbf97d9b7d22d5b5281ddaIan Abbott 1813ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (dev == NULL) { 1814ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("invalid minor number\n"); 1815ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENODEV; 1816ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1817ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1818ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* This is slightly hacky, but we want module autoloading 1819ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * to work for root. 1820ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * case: user opens device, attached -> ok 1821ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * case: user opens device, unattached, in_request_module=0 -> autoload 1822ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * case: user opens device, unattached, in_request_module=1 -> fail 1823ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * case: root opens device, attached -> ok 1824ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * case: root opens device, unattached, in_request_module=1 -> ok 1825ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * (typically called from modprobe) 1826ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * case: root opens device, unattached, in_request_module=0 -> autoload 1827ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * 1828ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * The last could be changed to "-> ok", which would deny root 1829ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * autoloading. 1830ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef */ 1831ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 1832ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (dev->attached) 1833ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto ok; 1834a8f80e8ff94ecba629542d9b4b5f5a8ee3eb565cEric Paris if (!capable(CAP_NET_ADMIN) && dev->in_request_module) { 1835ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef DPRINTK("in request module\n"); 1836ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1837ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENODEV; 1838ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1839a8f80e8ff94ecba629542d9b4b5f5a8ee3eb565cEric Paris if (capable(CAP_NET_ADMIN) && dev->in_request_module) 1840ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef goto ok; 1841ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1842ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef dev->in_request_module = 1; 1843ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1844ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#ifdef CONFIG_KMOD 1845ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 184656d92c60e6dc708541711e9de4993e7d527d08e8Ian Abbott request_module("char-major-%i-%i", COMEDI_MAJOR, dev->minor); 1847ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 1848ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef#endif 1849ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1850ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef dev->in_request_module = 0; 1851ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1852a8f80e8ff94ecba629542d9b4b5f5a8ee3eb565cEric Paris if (!dev->attached && !capable(CAP_NET_ADMIN)) { 1853a8f80e8ff94ecba629542d9b4b5f5a8ee3eb565cEric Paris DPRINTK("not attached and not CAP_NET_ADMIN\n"); 1854ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1855ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENODEV; 1856ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1857ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefok: 1858ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef __module_get(THIS_MODULE); 1859ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1860ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (dev->attached) { 1861ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!try_module_get(dev->driver->module)) { 1862ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef module_put(THIS_MODULE); 1863ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1864ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENOSYS; 1865ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1866ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1867ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 18683c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott if (dev->attached && dev->use_count == 0 && dev->open) { 18693c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott int rc = dev->open(dev); 18703c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott if (rc < 0) { 18713c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott module_put(dev->driver->module); 18723c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott module_put(THIS_MODULE); 18733c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott mutex_unlock(&dev->mutex); 18743c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott return rc; 18753c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott } 18763c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott } 1877ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1878ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef dev->use_count++; 1879ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1880ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1881ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1882ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 1883ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1884ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1885ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic int comedi_close(struct inode *inode, struct file *file) 1886ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1887ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(inode); 1888476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 1889476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 189071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = dev_file_info->device; 189134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s = NULL; 1892ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i; 1893ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1894ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 1895ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1896ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (dev->subdevices) { 1897ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef for (i = 0; i < dev->n_subdevices; i++) { 1898ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + i; 1899ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1900476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (s->busy == file) 1901ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef do_cancel(dev, s); 1902476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (s->lock == file) 1903ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->lock = NULL; 1904ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1905ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1906476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (dev->attached && dev->use_count == 1 && dev->close) 1907ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef dev->close(dev); 1908ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1909ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef module_put(THIS_MODULE); 1910476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (dev->attached) 1911ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef module_put(dev->driver->module); 1912ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1913ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef dev->use_count--; 1914ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1915ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 1916ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1917476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (file->f_flags & FASYNC) 1918ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_fasync(-1, file, 0); 1919ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1920ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 1921ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1922ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1923ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic int comedi_fasync(int fd, struct file *file, int on) 1924ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1925ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef const unsigned minor = iminor(file->f_dentry->d_inode); 1926476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman struct comedi_device_file_info *dev_file_info = 1927476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman comedi_get_device_file_info(minor); 1928476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman 192971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = dev_file_info->device; 1930ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1931ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return fasync_helper(fd, file, on, &dev->async_queue); 1932ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1933ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1934ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefconst struct file_operations comedi_fops = { 19350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .owner = THIS_MODULE, 19360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .unlocked_ioctl = comedi_unlocked_ioctl, 19370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .compat_ioctl = comedi_compat_ioctl, 19380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .open = comedi_open, 19390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .release = comedi_close, 19400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .read = comedi_read, 19410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .write = comedi_write, 19420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .mmap = comedi_mmap, 19430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .poll = comedi_poll, 19440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .fasync = comedi_fasync, 19456038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = noop_llseek, 1946ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef}; 1947ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1948476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartmanstruct class *comedi_class; 1949ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic struct cdev comedi_cdev; 1950ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1951ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic void comedi_cleanup_legacy_minors(void) 1952ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1953ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned i; 1954476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman 19551dd33ab8a9397793d65b9fc090174ff7cdfaff95Bernd Porr for (i = 0; i < comedi_num_legacy_minors; i++) 1956ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_free_board_minor(i); 1957ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 1958ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1959ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic int __init comedi_init(void) 1960ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 1961ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i; 1962ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int retval; 1963ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1964476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman printk(KERN_INFO "comedi: version " COMEDI_RELEASE 1965476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman " - http://www.comedi.org\n"); 1966ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1967a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess if (comedi_num_legacy_minors < 0 || 1968a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) { 1969a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess printk(KERN_ERR "comedi: error: invalid value for module " 1970a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess "parameter \"comedi_num_legacy_minors\". Valid values " 1971a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess "are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS); 1972a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess return -EINVAL; 1973a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess } 1974a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess 1975a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess /* 1976a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess * comedi is unusable if both comedi_autoconfig and 1977a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess * comedi_num_legacy_minors are zero, so we might as well adjust the 1978a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess * defaults in that case 1979a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess */ 1980a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess if (comedi_autoconfig == 0 && comedi_num_legacy_minors == 0) 1981a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess comedi_num_legacy_minors = 16; 1982a3cb729ef4a192f04179f780122df78ef1ffe779Frank Mori Hess 1983476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman memset(comedi_file_info_table, 0, 1984476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS); 1985ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 1986ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 1987476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman COMEDI_NUM_MINORS, "comedi"); 1988ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (retval) 1989ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EIO; 1990ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef cdev_init(&comedi_cdev, &comedi_fops); 1991ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_cdev.owner = THIS_MODULE; 1992ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kobject_set_name(&comedi_cdev.kobj, "comedi"); 1993ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) { 1994ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 1995476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman COMEDI_NUM_MINORS); 1996ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EIO; 1997ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 1998ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_class = class_create(THIS_MODULE, "comedi"); 1999ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (IS_ERR(comedi_class)) { 20003fffdf2045d0dbca3833f8f54ae41ce5f2c0b8faMark Rankilor printk(KERN_ERR "comedi: failed to create class"); 2001ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef cdev_del(&comedi_cdev); 2002ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 2003476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman COMEDI_NUM_MINORS); 2004ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return PTR_ERR(comedi_class); 2005ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2006ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2007ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /* XXX requires /proc interface */ 2008ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_proc_init(); 2009ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2010476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* create devices files for legacy/manual use */ 20111dd33ab8a9397793d65b9fc090174ff7cdfaff95Bernd Porr for (i = 0; i < comedi_num_legacy_minors; i++) { 2012ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int minor; 2013ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef minor = comedi_alloc_board_minor(NULL); 2014476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (minor < 0) { 2015ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_cleanup_legacy_minors(); 2016ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef cdev_del(&comedi_cdev); 2017ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 2018476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman COMEDI_NUM_MINORS); 2019ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return minor; 2020ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2021ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2022ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2023ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 2024ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2025ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2026ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstatic void __exit comedi_cleanup(void) 2027ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2028ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i; 2029ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2030ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_cleanup_legacy_minors(); 2031476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman for (i = 0; i < COMEDI_NUM_MINORS; ++i) 2032ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef BUG_ON(comedi_file_info_table[i]); 2033476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman 2034ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef class_destroy(comedi_class); 2035ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef cdev_del(&comedi_cdev); 2036ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); 2037ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2038ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_proc_cleanup(); 2039ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2040ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2041ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefmodule_init(comedi_init); 2042ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefmodule_exit(comedi_cleanup); 2043ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 204471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonvoid comedi_error(const struct comedi_device *dev, const char *s) 2045ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 20463fffdf2045d0dbca3833f8f54ae41ce5f2c0b8faMark Rankilor printk(KERN_ERR "comedi%d: %s: %s\n", dev->minor, 20473fffdf2045d0dbca3833f8f54ae41ce5f2c0b8faMark Rankilor dev->driver->driver_name, s); 2048ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 204918736438ae4ab3d96602b92446e07cc03c024b02Greg Kroah-HartmanEXPORT_SYMBOL(comedi_error); 2050ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 205134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonvoid comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) 2052ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2053d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton struct comedi_async *async = s->async; 2054ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned runflags = 0; 2055ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned runflags_mask = 0; 2056ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2057476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman /* DPRINTK("comedi_event 0x%x\n",mask); */ 2058ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2059ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) == 0) 2060ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return; 2061ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 20620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (s-> 20630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | 20640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral COMEDI_CB_OVERFLOW)) { 2065ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef runflags_mask |= SRF_RUNNING; 2066ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 206725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* remember if an error event has occurred, so an error 2068ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef * can be returned the next time the user does a read() */ 2069ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->async->events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) { 2070ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef runflags_mask |= SRF_ERROR; 2071ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef runflags |= SRF_ERROR; 2072ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2073ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (runflags_mask) { 2074ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef /*sets SRF_ERROR and SRF_RUNNING together atomically */ 2075ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_set_subdevice_runflags(s, runflags_mask, runflags); 2076ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2077ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2078ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (async->cb_mask & s->async->events) { 2079ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (comedi_get_subdevice_runflags(s) & SRF_USER) { 2080fcea115462c690ba09f9df7471d60dda0d86a4eaGreg Kroah-Hartman wake_up_interruptible(&async->wait_head); 20816705b68d0be284e2f9949f3657ea65d426d0f988Andrea Gelmini if (s->subdev_flags & SDF_CMD_READ) 20820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kill_fasync(&dev->async_queue, SIGIO, POLL_IN); 20836705b68d0be284e2f9949f3657ea65d426d0f988Andrea Gelmini if (s->subdev_flags & SDF_CMD_WRITE) 20840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kill_fasync(&dev->async_queue, SIGIO, POLL_OUT); 2085ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } else { 2086ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (async->cb_func) 2087ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef async->cb_func(s->async->events, async->cb_arg); 2088ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2089ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2090ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->async->events = 0; 2091ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 209218736438ae4ab3d96602b92446e07cc03c024b02Greg Kroah-HartmanEXPORT_SYMBOL(comedi_event); 2093ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 209434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonunsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) 2095ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2096ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long flags; 2097ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned runflags; 2098ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 20995f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&s->spin_lock, flags); 2100ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef runflags = s->runflags; 21015f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&s->spin_lock, flags); 2102ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return runflags; 2103ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 210418736438ae4ab3d96602b92446e07cc03c024b02Greg Kroah-HartmanEXPORT_SYMBOL(comedi_get_subdevice_runflags); 2105ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 210671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int is_device_busy(struct comedi_device *dev) 2107ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 210834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 2109ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef int i; 2110ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2111ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (!dev->attached) 2112ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 2113ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2114ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef for (i = 0; i < dev->n_subdevices; i++) { 2115ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s = dev->subdevices + i; 2116ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->busy) 2117ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 1; 2118ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef if (s->async && s->async->mmap_count) 2119ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 1; 2120ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2121ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2122ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return 0; 2123ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2124ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 212592d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic void comedi_device_init(struct comedi_device *dev) 2126ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 212771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton memset(dev, 0, sizeof(struct comedi_device)); 2128ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef spin_lock_init(&dev->spinlock); 2129ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_init(&dev->mutex); 2130ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef dev->minor = -1; 2131ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2132ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 213392d0127c9d249c078b0939050f25041ed37be7cdGreg Kroah-Hartmanstatic void comedi_device_cleanup(struct comedi_device *dev) 2134ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2135476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (dev == NULL) 2136476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return; 2137ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_lock(&dev->mutex); 2138ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_device_detach(dev); 2139ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_unlock(&dev->mutex); 2140ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef mutex_destroy(&dev->mutex); 2141ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2142ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2143ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefint comedi_alloc_board_minor(struct device *hardware_device) 2144ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2145ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long flags; 2146ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef struct comedi_device_file_info *info; 21470bfbbe8f09617247c87d3b626cbf007c423afff1Bill Pemberton struct device *csdev; 2148ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned i; 2149883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess int retval; 2150ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2151ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL); 2152476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (info == NULL) 2153476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return -ENOMEM; 215471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton info->device = kzalloc(sizeof(struct comedi_device), GFP_KERNEL); 2155476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (info->device == NULL) { 2156ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(info); 2157ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -ENOMEM; 2158ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2159ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_device_init(info->device); 21605f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&comedi_file_info_table_lock, flags); 2161476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) { 2162476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (comedi_file_info_table[i] == NULL) { 2163ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_file_info_table[i] = info; 2164ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 2165ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2166ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 21675f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&comedi_file_info_table_lock, flags); 2168476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (i == COMEDI_NUM_BOARD_MINORS) { 2169ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_device_cleanup(info->device); 2170ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(info->device); 2171ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(info); 21720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 217321fe2eea6381845956322e63e441f351774de7f9Mark "comedi: error: " 217421fe2eea6381845956322e63e441f351774de7f9Mark "ran out of minor numbers for board device files.\n"); 2175ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EBUSY; 2176ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2177ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info->device->minor = i; 2178ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef csdev = COMEDI_DEVICE_CREATE(comedi_class, NULL, 2179476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman MKDEV(COMEDI_MAJOR, i), NULL, 2180476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman hardware_device, "comedi%i", i); 2181476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (!IS_ERR(csdev)) 2182ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info->device->class_dev = csdev; 2183883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess dev_set_drvdata(csdev, info); 2184883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb); 2185883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 21860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 218721fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 218821fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 21890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_max_read_buffer_kb.attr.name); 2190883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_board_minor(i); 2191883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2192883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2193883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_read_buffer_kb); 2194883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 21950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 219621fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 219721fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 21980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_read_buffer_kb.attr.name); 2199883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_board_minor(i); 2200883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2201883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2202883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb); 2203883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 22040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 220521fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 220621fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 22070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_max_write_buffer_kb.attr.name); 2208883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_board_minor(i); 2209883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2210883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2211883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_write_buffer_kb); 2212883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 22130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 221421fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 221521fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 22160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_write_buffer_kb.attr.name); 2217883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_board_minor(i); 2218883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2219883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2220ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return i; 2221ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2222ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2223ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefvoid comedi_free_board_minor(unsigned minor) 2224ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2225ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long flags; 2226ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef struct comedi_device_file_info *info; 2227ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2228ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); 22295f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&comedi_file_info_table_lock, flags); 2230ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info = comedi_file_info_table[minor]; 2231ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_file_info_table[minor] = NULL; 22325f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&comedi_file_info_table_lock, flags); 2233ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2234476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (info) { 223571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = info->device; 2236476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (dev) { 2237476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (dev->class_dev) { 2238476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman device_destroy(comedi_class, 2239476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman MKDEV(COMEDI_MAJOR, dev->minor)); 2240ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2241ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_device_cleanup(dev); 2242ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(dev); 2243ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2244ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(info); 2245ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2246ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2247ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2248883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessint comedi_alloc_subdevice_minor(struct comedi_device *dev, 2249883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *s) 2250ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2251ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long flags; 2252ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef struct comedi_device_file_info *info; 22530bfbbe8f09617247c87d3b626cbf007c423afff1Bill Pemberton struct device *csdev; 2254ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned i; 2255883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess int retval; 2256ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2257ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL); 2258476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (info == NULL) 2259476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return -ENOMEM; 2260ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info->device = dev; 2261ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info->read_subdevice = s; 2262ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info->write_subdevice = s; 22635f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&comedi_file_info_table_lock, flags); 22644c41f3ae3bf0bcc53f259b657c2fbc3961ff2b8aFrank Mori Hess for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) { 2265476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (comedi_file_info_table[i] == NULL) { 2266ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_file_info_table[i] = info; 2267ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef break; 2268ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2269ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 22705f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&comedi_file_info_table_lock, flags); 2271476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (i == COMEDI_NUM_MINORS) { 2272ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(info); 22730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 227421fe2eea6381845956322e63e441f351774de7f9Mark "comedi: error: " 227521fe2eea6381845956322e63e441f351774de7f9Mark "ran out of minor numbers for board device files.\n"); 2276ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return -EBUSY; 2277ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2278ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->minor = i; 2279ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef csdev = COMEDI_DEVICE_CREATE(comedi_class, dev->class_dev, 2280476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman MKDEV(COMEDI_MAJOR, i), NULL, NULL, 2281476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman "comedi%i_subd%i", dev->minor, 2282476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman (int)(s - dev->subdevices)); 2283476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (!IS_ERR(csdev)) 2284ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->class_dev = csdev; 2285883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess dev_set_drvdata(csdev, info); 2286883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb); 2287883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 22880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 228921fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 229021fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 22910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_max_read_buffer_kb.attr.name); 2292883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_subdevice_minor(s); 2293883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2294883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2295883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_read_buffer_kb); 2296883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 22970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 229821fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 229921fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 23000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_read_buffer_kb.attr.name); 2301883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_subdevice_minor(s); 2302883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2303883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2304883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb); 2305883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 23060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 230721fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 230821fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 23090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_max_write_buffer_kb.attr.name); 2310883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_subdevice_minor(s); 2311883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2312883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2313883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = device_create_file(csdev, &dev_attr_write_buffer_kb); 2314883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval) { 23150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk(KERN_ERR 231621fe2eea6381845956322e63e441f351774de7f9Mark "comedi: " 231721fe2eea6381845956322e63e441f351774de7f9Mark "failed to create sysfs attribute file \"%s\".\n", 23180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev_attr_write_buffer_kb.attr.name); 2319883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess comedi_free_subdevice_minor(s); 2320883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2321883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2322ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return i; 2323ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2324ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 232534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonvoid comedi_free_subdevice_minor(struct comedi_subdevice *s) 2326ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2327ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long flags; 2328ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef struct comedi_device_file_info *info; 2329ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2330476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (s == NULL) 2331476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return; 2332476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (s->minor < 0) 2333476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman return; 2334ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2335ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef BUG_ON(s->minor >= COMEDI_NUM_MINORS); 2336ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef BUG_ON(s->minor < COMEDI_FIRST_SUBDEVICE_MINOR); 2337ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 23385f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&comedi_file_info_table_lock, flags); 2339ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info = comedi_file_info_table[s->minor]; 2340ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef comedi_file_info_table[s->minor] = NULL; 23415f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&comedi_file_info_table_lock, flags); 2342ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2343476b847733636ce5765093f5d1a369cc470e78e6Greg Kroah-Hartman if (s->class_dev) { 2344ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor)); 2345ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef s->class_dev = NULL; 2346ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef } 2347ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef kfree(info); 2348ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 2349ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2350ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleefstruct comedi_device_file_info *comedi_get_device_file_info(unsigned minor) 2351ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef{ 2352ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef unsigned long flags; 2353ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef struct comedi_device_file_info *info; 2354ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef 2355ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef BUG_ON(minor >= COMEDI_NUM_MINORS); 23565f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_lock_irqsave(&comedi_file_info_table_lock, flags); 2357ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef info = comedi_file_info_table[minor]; 23585f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman spin_unlock_irqrestore(&comedi_file_info_table_lock, flags); 2359ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef return info; 2360ed9eccbe8970f6eedc1b978c157caf1251a896d4David Schleef} 236118736438ae4ab3d96602b92446e07cc03c024b02Greg Kroah-HartmanEXPORT_SYMBOL_GPL(comedi_get_device_file_info); 2362883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2363883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic int resize_async_buffer(struct comedi_device *dev, 2364883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *s, 2365883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_async *async, unsigned new_size) 2366883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2367883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess int retval; 2368883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2369883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (new_size > async->max_bufsize) 2370883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EPERM; 2371883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2372883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (s->busy) { 2373883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess DPRINTK("subdevice is busy, cannot resize buffer\n"); 2374883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EBUSY; 2375883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2376883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (async->mmap_count) { 2377883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess DPRINTK("subdevice is mmapped, cannot resize buffer\n"); 2378883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EBUSY; 2379883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2380883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2381883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (!async->prealloc_buf) 2382883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2383883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2384883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess /* make sure buffer is an integral number of pages 23850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * (we round up) */ 2386883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; 2387883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2388883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = comedi_buf_alloc(dev, s, new_size); 2389883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval < 0) 2390883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2391883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2392883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (s->buf_change) { 2393883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = s->buf_change(dev, s, new_size); 2394883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval < 0) 2395883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2396883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2397883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2398883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess DPRINTK("comedi%i subd %d buffer resized to %i bytes\n", 2399b8b5cd9f87e08f72c78d9197bf199821fda4ba36Ian Abbott dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz); 2400883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return 0; 2401883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2402883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2403883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess/* sysfs attribute files */ 2404883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2405883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic const unsigned bytes_per_kibi = 1024; 2406883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2407883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t show_max_read_buffer_kb(struct device *dev, 2408883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, char *buf) 2409883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2410883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess ssize_t retval; 2411883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2412883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned max_buffer_size_kb = 0; 2413883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const read_subdevice = 24140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_read_subdevice(info); 2415883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2416883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2417883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (read_subdevice && 2418883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess (read_subdevice->subdev_flags & SDF_CMD_READ) && 2419883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess read_subdevice->async) { 2420883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess max_buffer_size_kb = read_subdevice->async->max_bufsize / 24210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral bytes_per_kibi; 2422883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 24230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb); 2424883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2425883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2426883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2427883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2428883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2429883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t store_max_read_buffer_kb(struct device *dev, 2430883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, 2431883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess const char *buf, size_t count) 2432883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2433883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2434883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned long new_max_size_kb; 2435883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess uint64_t new_max_size; 2436883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const read_subdevice = 24370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_read_subdevice(info); 2438883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2439883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (strict_strtoul(buf, 10, &new_max_size_kb)) 2440883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 24410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_max_size_kb != (uint32_t) new_max_size_kb) 2442883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 24430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral new_max_size = ((uint64_t) new_max_size_kb) * bytes_per_kibi; 24440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_max_size != (uint32_t) new_max_size) 2445883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2446883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2447883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2448883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (read_subdevice == NULL || 2449883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 || 2450883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess read_subdevice->async == NULL) { 2451883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2452883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2453883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2454883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess read_subdevice->async->max_bufsize = new_max_size; 2455883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2456883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2457883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return count; 2458883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2459883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2460883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_max_read_buffer_kb = { 2461883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .attr = { 24620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "max_read_buffer_kb", 24630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .mode = S_IRUGO | S_IWUSR}, 2464883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .show = &show_max_read_buffer_kb, 2465883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .store = &store_max_read_buffer_kb 2466883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess}; 2467883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2468883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t show_read_buffer_kb(struct device *dev, 2469883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, char *buf) 2470883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2471883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess ssize_t retval; 2472883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2473883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned buffer_size_kb = 0; 2474883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const read_subdevice = 24750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_read_subdevice(info); 2476883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2477883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2478883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (read_subdevice && 24790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (read_subdevice->subdev_flags & SDF_CMD_READ) && 24800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral read_subdevice->async) { 2481883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess buffer_size_kb = read_subdevice->async->prealloc_bufsz / 24820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral bytes_per_kibi; 2483883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 24840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb); 2485883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2486883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2487883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2488883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2489883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2490883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t store_read_buffer_kb(struct device *dev, 2491883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, 2492883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess const char *buf, size_t count) 2493883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2494883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2495883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned long new_size_kb; 2496883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess uint64_t new_size; 2497883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess int retval; 2498883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const read_subdevice = 24990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_read_subdevice(info); 2500883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2501883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (strict_strtoul(buf, 10, &new_size_kb)) 2502883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 25030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_size_kb != (uint32_t) new_size_kb) 2504883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 25050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral new_size = ((uint64_t) new_size_kb) * bytes_per_kibi; 25060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_size != (uint32_t) new_size) 2507883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2508883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2509883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2510883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (read_subdevice == NULL || 2511883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 || 2512883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess read_subdevice->async == NULL) { 2513883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2514883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2515883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2516883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = resize_async_buffer(info->device, read_subdevice, 2517883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess read_subdevice->async, new_size); 2518883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2519883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2520883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval < 0) 2521883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2522883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return count; 2523883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2524883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2525883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_read_buffer_kb = { 2526883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .attr = { 25270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "read_buffer_kb", 25280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .mode = S_IRUGO | S_IWUSR | S_IWGRP}, 2529883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .show = &show_read_buffer_kb, 2530883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .store = &store_read_buffer_kb 2531883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess}; 2532883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2533883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t show_max_write_buffer_kb(struct device *dev, 2534883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, 2535883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess char *buf) 2536883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2537883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess ssize_t retval; 2538883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2539883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned max_buffer_size_kb = 0; 2540883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const write_subdevice = 25410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_write_subdevice(info); 2542883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2543883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2544883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (write_subdevice && 2545883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess (write_subdevice->subdev_flags & SDF_CMD_WRITE) && 2546883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess write_subdevice->async) { 2547883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess max_buffer_size_kb = write_subdevice->async->max_bufsize / 25480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral bytes_per_kibi; 2549883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 25500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb); 2551883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2552883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2553883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2554883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2555883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2556883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t store_max_write_buffer_kb(struct device *dev, 2557883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, 2558883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess const char *buf, size_t count) 2559883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2560883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2561883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned long new_max_size_kb; 2562883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess uint64_t new_max_size; 2563883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const write_subdevice = 25640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_write_subdevice(info); 2565883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2566883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (strict_strtoul(buf, 10, &new_max_size_kb)) 2567883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 25680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_max_size_kb != (uint32_t) new_max_size_kb) 2569883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 25700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral new_max_size = ((uint64_t) new_max_size_kb) * bytes_per_kibi; 25710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_max_size != (uint32_t) new_max_size) 2572883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2573883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2574883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2575883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (write_subdevice == NULL || 2576883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 || 2577883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess write_subdevice->async == NULL) { 2578883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2579883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2580883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2581883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess write_subdevice->async->max_bufsize = new_max_size; 2582883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2583883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2584883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return count; 2585883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2586883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2587883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_max_write_buffer_kb = { 2588883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .attr = { 25890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "max_write_buffer_kb", 25900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .mode = S_IRUGO | S_IWUSR}, 2591883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .show = &show_max_write_buffer_kb, 2592883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .store = &store_max_write_buffer_kb 2593883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess}; 2594883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2595883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t show_write_buffer_kb(struct device *dev, 2596883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, char *buf) 2597883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2598883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess ssize_t retval; 2599883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2600883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned buffer_size_kb = 0; 2601883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const write_subdevice = 26020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_write_subdevice(info); 2603883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2604883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2605883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (write_subdevice && 2606883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess (write_subdevice->subdev_flags & SDF_CMD_WRITE) && 2607883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess write_subdevice->async) { 2608883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess buffer_size_kb = write_subdevice->async->prealloc_bufsz / 26090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral bytes_per_kibi; 2610883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 26110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb); 2612883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2613883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2614883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2615883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2616883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2617883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic ssize_t store_write_buffer_kb(struct device *dev, 2618883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct device_attribute *attr, 2619883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess const char *buf, size_t count) 2620883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess{ 2621883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_device_file_info *info = dev_get_drvdata(dev); 2622883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess unsigned long new_size_kb; 2623883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess uint64_t new_size; 2624883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess int retval; 2625883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess struct comedi_subdevice *const write_subdevice = 26260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_get_write_subdevice(info); 2627883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2628883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (strict_strtoul(buf, 10, &new_size_kb)) 2629883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 26300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_size_kb != (uint32_t) new_size_kb) 2631883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 26320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral new_size = ((uint64_t) new_size_kb) * bytes_per_kibi; 26330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral if (new_size != (uint32_t) new_size) 2634883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2635883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2636883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_lock(&info->device->mutex); 2637883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (write_subdevice == NULL || 2638883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 || 2639883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess write_subdevice->async == NULL) { 2640883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2641883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return -EINVAL; 2642883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess } 2643883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess retval = resize_async_buffer(info->device, write_subdevice, 26440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral write_subdevice->async, new_size); 2645883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess mutex_unlock(&info->device->mutex); 2646883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2647883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess if (retval < 0) 2648883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return retval; 2649883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess return count; 2650883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess} 2651883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess 2652883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hessstatic struct device_attribute dev_attr_write_buffer_kb = { 2653883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .attr = { 26540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "write_buffer_kb", 26550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .mode = S_IRUGO | S_IWUSR | S_IWGRP}, 2656883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .show = &show_write_buffer_kb, 2657883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess .store = &store_write_buffer_kb 2658883db3d9bb4d50f05cbb8b5197f6aef10c1231a9Frank Mori Hess}; 2659