diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/staging/comedi/drivers.c | 26 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/amplc_dio200.h | 6 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/amplc_dio200_common.c | 2 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/amplc_pci230.c | 12 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/cb_pcimdda.c | 4 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/daqboard2000.c | 2 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/ni_mio_common.c | 5 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/pcl816.c | 4 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/pcl818.c | 4 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/quatech_daqp_cs.c | 2 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/serial2002.c | 778 |
12 files changed, 33 insertions, 813 deletions
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 9d733471ca2e..57dd63d548b7 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -473,21 +473,21 @@ unsigned int comedi_nsamples_left(struct comedi_subdevice *s, { struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + unsigned long long scans_left; + unsigned long long samples_left; - if (cmd->stop_src == TRIG_COUNT) { - unsigned int scans_left = __comedi_nscans_left(s, cmd->stop_arg); - unsigned int scan_pos = - comedi_bytes_to_samples(s, async->scan_progress); - unsigned long long samples_left = 0; - - if (scans_left) { - samples_left = ((unsigned long long)scans_left * - cmd->scan_end_arg) - scan_pos; - } + if (cmd->stop_src != TRIG_COUNT) + return nsamples; - if (samples_left < nsamples) - nsamples = samples_left; - } + scans_left = __comedi_nscans_left(s, cmd->stop_arg); + if (!scans_left) + return 0; + + samples_left = scans_left * cmd->scan_end_arg - + comedi_bytes_to_samples(s, async->scan_progress); + + if (samples_left < nsamples) + return samples_left; return nsamples; } EXPORT_SYMBOL_GPL(comedi_nsamples_left); diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 736e7e55219d..98b42b47dfe1 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_COMEDI_ISADMA) += comedi_isadma.o obj-$(CONFIG_COMEDI_BOND) += comedi_bond.o obj-$(CONFIG_COMEDI_TEST) += comedi_test.o obj-$(CONFIG_COMEDI_PARPORT) += comedi_parport.o -obj-$(CONFIG_COMEDI_SERIAL2002) += serial2002.o # Comedi ISA drivers obj-$(CONFIG_COMEDI_AMPLC_DIO200_ISA) += amplc_dio200.o diff --git a/drivers/staging/comedi/drivers/amplc_dio200.h b/drivers/staging/comedi/drivers/amplc_dio200.h index 88c1d1063d5d..4c3e4c37c4c5 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.h +++ b/drivers/staging/comedi/drivers/amplc_dio200.h @@ -32,9 +32,9 @@ struct dio200_board { unsigned short n_subdevs; /* number of subdevices */ unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */ unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */ - bool has_int_sce:1; /* has interrupt enable/status reg */ - bool has_clk_gat_sce:1; /* has clock/gate selection registers */ - bool is_pcie:1; /* has enhanced features */ + unsigned int has_int_sce:1; /* has interrupt enable/status reg */ + unsigned int has_clk_gat_sce:1; /* has clock/gate selection registers */ + unsigned int is_pcie:1; /* has enhanced features */ }; int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq, diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 82bd41d92509..8697dc02ffb4 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -96,7 +96,7 @@ struct dio200_subdev_intr { unsigned int ofs; unsigned int valid_isns; unsigned int enabled_isns; - bool active:1; + unsigned int active:1; }; static unsigned char dio200_read8(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 15fc7f19051a..08ffe26c5d43 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -444,7 +444,7 @@ struct pci230_board { unsigned char ai_bits; unsigned char ao_bits; unsigned char min_hwver; /* Minimum hardware version supported. */ - bool have_dio:1; + unsigned int have_dio:1; }; static const struct pci230_board pci230_boards[] = { @@ -490,11 +490,11 @@ struct pci230_private { unsigned short adcg; /* ADCG register value */ unsigned char ier; /* Interrupt enable bits */ unsigned char res_owned[NUM_OWNERS]; /* Owned resources */ - bool intr_running:1; /* Flag set in interrupt routine */ - bool ai_bipolar:1; /* Flag AI range is bipolar */ - bool ao_bipolar:1; /* Flag AO range is bipolar */ - bool ai_cmd_started:1; /* Flag AI command started */ - bool ao_cmd_started:1; /* Flag AO command started */ + unsigned int intr_running:1; /* Flag set in interrupt routine */ + unsigned int ai_bipolar:1; /* Flag AI range is bipolar */ + unsigned int ao_bipolar:1; /* Flag AO range is bipolar */ + unsigned int ai_cmd_started:1; /* Flag AI command started */ + unsigned int ao_cmd_started:1; /* Flag AO command started */ }; /* PCI230 clock source periods in ns */ diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index b33203f6a990..21fc7b3c5f60 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -188,7 +188,5 @@ static struct pci_driver cb_pcimdda_driver_pci_driver = { module_comedi_pci_driver(cb_pcimdda_driver, cb_pcimdda_driver_pci_driver); MODULE_AUTHOR("Calin A. Culianu <calin@rtlab.org>"); -MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA " - "series. Currently only supports PCIM-DDA06-16 (which " - "also happens to be the only board in this series. :) ) "); +MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA series. Currently only supports PCIM-DDA06-16 (which also happens to be the only board in this series. :) ) "); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 03f98b0287c8..aabcda3f9fc8 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -240,7 +240,7 @@ enum db2k_boardid { struct db2k_boardtype { const char *name; - bool has_2_ao:1; /* false: 4 AO chans; true: 2 AO chans */ + unsigned int has_2_ao:1;/* false: 4 AO chans; true: 2 AO chans */ }; static const struct db2k_boardtype db2k_boardtypes[] = { diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index e40a2c0a9543..4dee2fc37aed 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -4294,7 +4294,7 @@ static int pack_ad8842(int addr, int val, int *bitstring) struct caldac_struct { int n_chans; int n_bits; - int (*packbits)(int, int, int *); + int (*packbits)(int address, int value, int *bitstring); }; static struct caldac_struct caldacs[] = { @@ -5446,11 +5446,11 @@ static int ni_E_init(struct comedi_device *dev, /* Digital I/O (PFI) subdevice */ s = &dev->subdevices[NI_PFI_DIO_SUBDEV]; s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->maxdata = 1; if (devpriv->is_m_series) { s->n_chan = 16; s->insn_bits = ni_pfi_insn_bits; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; ni_writew(dev, s->state, NI_M_PFI_DO_REG); for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) { @@ -5459,6 +5459,7 @@ static int ni_E_init(struct comedi_device *dev, } } else { s->n_chan = 10; + s->subdev_flags = SDF_INTERNAL; } s->insn_config = ni_pfi_insn_config; diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index d722079f3327..d87cf6d4a161 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -282,7 +282,7 @@ static int check_channel_list(struct comedi_device *dev, unsigned int chanlen) { unsigned int chansegment[16]; - unsigned int i, nowmustbechan, seglen, segpos; + unsigned int i, nowmustbechan, seglen; /* correct channel and range number check itself comedi/range.c */ if (chanlen < 1) { @@ -312,7 +312,7 @@ static int check_channel_list(struct comedi_device *dev, } /* check whole chanlist */ - for (i = 0, segpos = 0; i < chanlen; i++) { + for (i = 0; i < chanlen; i++) { if (chanlist[i] != chansegment[i % seglen]) { dev_dbg(dev->class_dev, "bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index eebb49751713..0af5315d4357 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -573,7 +573,7 @@ static int check_channel_list(struct comedi_device *dev, unsigned int *chanlist, unsigned int n_chan) { unsigned int chansegment[16]; - unsigned int i, nowmustbechan, seglen, segpos; + unsigned int i, nowmustbechan, seglen; /* correct channel and range number check itself comedi/range.c */ if (n_chan < 1) { @@ -605,7 +605,7 @@ static int check_channel_list(struct comedi_device *dev, } /* check whole chanlist */ - for (i = 0, segpos = 0; i < n_chan; i++) { + for (i = 0; i < n_chan; i++) { if (chanlist[i] != chansegment[i % seglen]) { dev_dbg(dev->class_dev, "bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index ea194aa01a64..257b0daff01f 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -642,7 +642,7 @@ static int daqp_ao_insn_write(struct comedi_device *dev, /* Make sure D/A update mode is direct update */ outb(0, dev->iobase + DAQP_AUX_REG); - for (i = 0; i > insn->n; i++) { + for (i = 0; i < insn->n; i++) { unsigned int val = data[i]; int ret; diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c deleted file mode 100644 index 5471b2212a62..000000000000 --- a/drivers/staging/comedi/drivers/serial2002.c +++ /dev/null @@ -1,778 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * serial2002.c - * Comedi driver for serial connected hardware - * - * COMEDI - Linux Control and Measurement Device Interface - * Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se> - */ - -/* - * Driver: serial2002 - * Description: Driver for serial connected hardware - * Devices: - * Author: Anders Blomdell - * Updated: Fri, 7 Jun 2002 12:56:45 -0700 - * Status: in development - */ - -#include <linux/module.h> -#include "../comedidev.h" - -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/ktime.h> - -#include <linux/termios.h> -#include <asm/ioctls.h> -#include <linux/serial.h> -#include <linux/poll.h> - -struct serial2002_range_table_t { - /* HACK... */ - int length; - struct comedi_krange range; -}; - -struct serial2002_private { - int port; /* /dev/ttyS<port> */ - int speed; /* baudrate */ - struct file *tty; - unsigned int ao_readback[32]; - unsigned char digital_in_mapping[32]; - unsigned char digital_out_mapping[32]; - unsigned char analog_in_mapping[32]; - unsigned char analog_out_mapping[32]; - unsigned char encoder_in_mapping[32]; - struct serial2002_range_table_t in_range[32], out_range[32]; -}; - -struct serial_data { - enum { is_invalid, is_digital, is_channel } kind; - int index; - unsigned long value; -}; - -/* - * The configuration serial_data.value read from the device is - * a bitmask that defines specific options of a channel: - * - * 4:0 - the channel to configure - * 7:5 - the kind of channel - * 9:8 - the command used to configure the channel - * - * The remaining bits vary in use depending on the command: - * - * BITS 15:10 - the channel bits (maxdata) - * MIN/MAX 12:10 - the units multiplier for the scale - * 13 - the sign of the scale - * 33:14 - the base value for the range - */ -#define S2002_CFG_CHAN(x) ((x) & 0x1f) -#define S2002_CFG_KIND(x) (((x) >> 5) & 0x7) -#define S2002_CFG_KIND_INVALID 0 -#define S2002_CFG_KIND_DIGITAL_IN 1 -#define S2002_CFG_KIND_DIGITAL_OUT 2 -#define S2002_CFG_KIND_ANALOG_IN 3 -#define S2002_CFG_KIND_ANALOG_OUT 4 -#define S2002_CFG_KIND_ENCODER_IN 5 -#define S2002_CFG_CMD(x) (((x) >> 8) & 0x3) -#define S2002_CFG_CMD_BITS 0 -#define S2002_CFG_CMD_MIN 1 -#define S2002_CFG_CMD_MAX 2 -#define S2002_CFG_BITS(x) (((x) >> 10) & 0x3f) -#define S2002_CFG_UNITS(x) (((x) >> 10) & 0x7) -#define S2002_CFG_SIGN(x) (((x) >> 13) & 0x1) -#define S2002_CFG_BASE(x) (((x) >> 14) & 0xfffff) - -static long serial2002_tty_ioctl(struct file *f, unsigned int op, - unsigned long param) -{ - if (f->f_op->unlocked_ioctl) - return f->f_op->unlocked_ioctl(f, op, param); - - return -ENOTTY; -} - -static int serial2002_tty_write(struct file *f, unsigned char *buf, int count) -{ - loff_t pos = 0; - - return kernel_write(f, buf, count, &pos); -} - -static void serial2002_tty_read_poll_wait(struct file *f, int timeout) -{ - struct poll_wqueues table; - ktime_t start, now; - - start = ktime_get(); - poll_initwait(&table); - while (1) { - long elapsed; - __poll_t mask; - - mask = vfs_poll(f, &table.pt); - if (mask & (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | - EPOLLHUP | EPOLLERR)) { - break; - } - now = ktime_get(); - elapsed = ktime_us_delta(now, start); - if (elapsed > timeout) - break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(((timeout - elapsed) * HZ) / 10000); - } - poll_freewait(&table); -} - -static int serial2002_tty_read(struct file *f, int timeout) -{ - unsigned char ch; - int result; - loff_t pos = 0; - - result = -1; - if (!IS_ERR(f)) { - if (file_can_poll(f)) { - serial2002_tty_read_poll_wait(f, timeout); - - if (kernel_read(f, &ch, 1, &pos) == 1) - result = ch; - } else { - /* Device does not support poll, busy wait */ - int retries = 0; - - while (1) { - retries++; - if (retries >= timeout) - break; - - if (kernel_read(f, &ch, 1, &pos) == 1) { - result = ch; - break; - } - usleep_range(100, 1000); - } - } - } - return result; -} - -static void serial2002_tty_setspeed(struct file *f, int speed) -{ - struct termios termios; - struct serial_struct serial; - mm_segment_t oldfs; - - oldfs = get_fs(); - set_fs(KERNEL_DS); - - /* Set speed */ - serial2002_tty_ioctl(f, TCGETS, (unsigned long)&termios); - termios.c_iflag = 0; - termios.c_oflag = 0; - termios.c_lflag = 0; - termios.c_cflag = CLOCAL | CS8 | CREAD; - termios.c_cc[VMIN] = 0; - termios.c_cc[VTIME] = 0; - switch (speed) { - case 2400: - termios.c_cflag |= B2400; - break; - case 4800: - termios.c_cflag |= B4800; - break; - case 9600: - termios.c_cflag |= B9600; - break; - case 19200: - termios.c_cflag |= B19200; - break; - case 38400: - termios.c_cflag |= B38400; - break; - case 57600: - termios.c_cflag |= B57600; - break; - case 115200: - termios.c_cflag |= B115200; - break; - default: - termios.c_cflag |= B9600; - break; - } - serial2002_tty_ioctl(f, TCSETS, (unsigned long)&termios); - - /* Set low latency */ - serial2002_tty_ioctl(f, TIOCGSERIAL, (unsigned long)&serial); - serial.flags |= ASYNC_LOW_LATENCY; - serial2002_tty_ioctl(f, TIOCSSERIAL, (unsigned long)&serial); - - set_fs(oldfs); -} - -static void serial2002_poll_digital(struct file *f, int channel) -{ - char cmd; - - cmd = 0x40 | (channel & 0x1f); - serial2002_tty_write(f, &cmd, 1); -} - -static void serial2002_poll_channel(struct file *f, int channel) -{ - char cmd; - - cmd = 0x60 | (channel & 0x1f); - serial2002_tty_write(f, &cmd, 1); -} - -static struct serial_data serial2002_read(struct file *f, int timeout) -{ - struct serial_data result; - int length; - - result.kind = is_invalid; - result.index = 0; - result.value = 0; - length = 0; - while (1) { - int data = serial2002_tty_read(f, timeout); - - length++; - if (data < 0) { - break; - } else if (data & 0x80) { - result.value = (result.value << 7) | (data & 0x7f); - } else { - if (length == 1) { - switch ((data >> 5) & 0x03) { - case 0: - result.value = 0; - result.kind = is_digital; - break; - case 1: - result.value = 1; - result.kind = is_digital; - break; - } - } else { - result.value = - (result.value << 2) | ((data & 0x60) >> 5); - result.kind = is_channel; - } - result.index = data & 0x1f; - break; - } - } - return result; -} - -static void serial2002_write(struct file *f, struct serial_data data) -{ - if (data.kind == is_digital) { - unsigned char ch = - ((data.value << 5) & 0x20) | (data.index & 0x1f); - serial2002_tty_write(f, &ch, 1); - } else { - unsigned char ch[6]; - int i = 0; - - if (data.value >= (1L << 30)) { - ch[i] = 0x80 | ((data.value >> 30) & 0x03); - i++; - } - if (data.value >= (1L << 23)) { - ch[i] = 0x80 | ((data.value >> 23) & 0x7f); - i++; - } - if (data.value >= (1L << 16)) { - ch[i] = 0x80 | ((data.value >> 16) & 0x7f); - i++; - } - if (data.value >= (1L << 9)) { - ch[i] = 0x80 | ((data.value >> 9) & 0x7f); - i++; - } - ch[i] = 0x80 | ((data.value >> 2) & 0x7f); - i++; - ch[i] = ((data.value << 5) & 0x60) | (data.index & 0x1f); - i++; - serial2002_tty_write(f, ch, i); - } -} - -struct config_t { - short int kind; - short int bits; - int min; - int max; -}; - -static int serial2002_setup_subdevice(struct comedi_subdevice *s, - struct config_t *cfg, - struct serial2002_range_table_t *range, - unsigned char *mapping, - int kind) -{ - const struct comedi_lrange **range_table_list = NULL; - unsigned int *maxdata_list; - int j, chan; - - for (chan = 0, j = 0; j < 32; j++) { - if (cfg[j].kind == kind) - chan++; - } - s->n_chan = chan; - s->maxdata = 0; - kfree(s->maxdata_list); - maxdata_list = kmalloc_array(s->n_chan, sizeof(unsigned int), - GFP_KERNEL); - if (!maxdata_list) - return -ENOMEM; - s->maxdata_list = maxdata_list; - kfree(s->range_table_list); - s->range_table = NULL; - s->range_table_list = NULL; - if (kind == 1 || kind == 2) { - s->range_table = &range_digital; - } else if (range) { - range_table_list = kmalloc_array(s->n_chan, sizeof(*range), - GFP_KERNEL); - if (!range_table_list) - return -ENOMEM; - s->range_table_list = range_table_list; - } - for (chan = 0, j = 0; j < 32; j++) { - if (cfg[j].kind == kind) { - if (mapping) - mapping[chan] = j; - if (range && range_table_list) { - range[j].length = 1; - range[j].range.min = cfg[j].min; - range[j].range.max = cfg[j].max; - range_table_list[chan] = - (const struct comedi_lrange *)&range[j]; - } - if (cfg[j].bits < 32) - maxdata_list[chan] = (1u << cfg[j].bits) - 1; - else - maxdata_list[chan] = 0xffffffff; - chan++; - } - } - return 0; -} - -static int serial2002_setup_subdevs(struct comedi_device *dev) -{ - struct serial2002_private *devpriv = dev->private; - struct config_t *di_cfg; - struct config_t *do_cfg; - struct config_t *ai_cfg; - struct config_t *ao_cfg; - struct config_t *cfg; - struct comedi_subdevice *s; - int result = 0; - int i; - - /* Allocate the temporary structs to hold the configuration data */ - di_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); - do_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); - ai_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); - ao_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); - if (!di_cfg || !do_cfg || !ai_cfg || !ao_cfg) { - result = -ENOMEM; - goto err_alloc_configs; - } - - /* Read the configuration from the connected device */ - serial2002_tty_setspeed(devpriv->tty, devpriv->speed); - serial2002_poll_channel(devpriv->tty, 31); - while (1) { - struct serial_data data = serial2002_read(devpriv->tty, 1000); - int kind = S2002_CFG_KIND(data.value); - int channel = S2002_CFG_CHAN(data.value); - int range = S2002_CFG_BASE(data.value); - int cmd = S2002_CFG_CMD(data.value); - - if (data.kind != is_channel || data.index != 31 || - kind == S2002_CFG_KIND_INVALID) - break; - - switch (kind) { - case S2002_CFG_KIND_DIGITAL_IN: - cfg = di_cfg; - break; - case S2002_CFG_KIND_DIGITAL_OUT: - cfg = do_cfg; - break; - case S2002_CFG_KIND_ANALOG_IN: - cfg = ai_cfg; - break; - case S2002_CFG_KIND_ANALOG_OUT: - cfg = ao_cfg; - break; - case S2002_CFG_KIND_ENCODER_IN: - cfg = ai_cfg; - break; - default: - cfg = NULL; - break; - } - if (!cfg) - continue; /* unknown kind, skip it */ - - cfg[channel].kind = kind; - - switch (cmd) { - case S2002_CFG_CMD_BITS: - cfg[channel].bits = S2002_CFG_BITS(data.value); - break; - case S2002_CFG_CMD_MIN: - case S2002_CFG_CMD_MAX: - switch (S2002_CFG_UNITS(data.value)) { - case 0: - range *= 1000000; - break; - case 1: - range *= 1000; - break; - case 2: - range *= 1; - break; - } - if (S2002_CFG_SIGN(data.value)) - range = -range; - if (cmd == S2002_CFG_CMD_MIN) - cfg[channel].min = range; - else - cfg[channel].max = range; - break; - } - } - - /* Fill in subdevice data */ - for (i = 0; i <= 4; i++) { - unsigned char *mapping = NULL; - struct serial2002_range_table_t *range = NULL; - int kind = 0; - - s = &dev->subdevices[i]; - - switch (i) { - case 0: - cfg = di_cfg; - mapping = devpriv->digital_in_mapping; - kind = S2002_CFG_KIND_DIGITAL_IN; - break; - case 1: - cfg = do_cfg; - mapping = devpriv->digital_out_mapping; - kind = S2002_CFG_KIND_DIGITAL_OUT; - break; - case 2: - cfg = ai_cfg; - mapping = devpriv->analog_in_mapping; - range = devpriv->in_range; - kind = S2002_CFG_KIND_ANALOG_IN; - break; - case 3: - cfg = ao_cfg; - mapping = devpriv->analog_out_mapping; - range = devpriv->out_range; - kind = S2002_CFG_KIND_ANALOG_OUT; - break; - case 4: - cfg = ai_cfg; - mapping = devpriv->encoder_in_mapping; - range = devpriv->in_range; - kind = S2002_CFG_KIND_ENCODER_IN; - break; - } - - if (serial2002_setup_subdevice(s, cfg, range, mapping, kind)) - break; /* err handled below */ - } - if (i <= 4) { - /* - * Failed to allocate maxdata_list or range_table_list - * for a subdevice that needed it. - */ - result = -ENOMEM; - for (i = 0; i <= 4; i++) { - s = &dev->subdevices[i]; - kfree(s->maxdata_list); - s->maxdata_list = NULL; - kfree(s->range_table_list); - s->range_table_list = NULL; - } - } - -err_alloc_configs: - kfree(di_cfg); - kfree(do_cfg); - kfree(ai_cfg); - kfree(ao_cfg); - - if (result) { - if (devpriv->tty) { - filp_close(devpriv->tty, NULL); - devpriv->tty = NULL; - } - } - - return result; -} - -static int serial2002_open(struct comedi_device *dev) -{ - struct serial2002_private *devpriv = dev->private; - int result; - char port[20]; - - sprintf(port, "/dev/ttyS%d", devpriv->port); - devpriv->tty = filp_open(port, O_RDWR, 0); - if (IS_ERR(devpriv->tty)) { - result = (int)PTR_ERR(devpriv->tty); - dev_err(dev->class_dev, "file open error = %d\n", result); - } else { - result = serial2002_setup_subdevs(dev); - } - return result; -} - -static void serial2002_close(struct comedi_device *dev) -{ - struct serial2002_private *devpriv = dev->private; - - if (!IS_ERR(devpriv->tty) && devpriv->tty) - filp_close(devpriv->tty, NULL); -} - -static int serial2002_di_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct serial2002_private *devpriv = dev->private; - int n; - int chan; - - chan = devpriv->digital_in_mapping[CR_CHAN(insn->chanspec)]; - for (n = 0; n < insn->n; n++) { - struct serial_data read; - - serial2002_poll_digital(devpriv->tty, chan); - while (1) { - read = serial2002_read(devpriv->tty, 1000); - if (read.kind != is_digital || read.index == chan) - break; - } - data[n] = read.value; - } - return n; -} - -static int serial2002_do_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct serial2002_private *devpriv = dev->private; - int n; - int chan; - - chan = devpriv->digital_out_mapping[CR_CHAN(insn->chanspec)]; - for (n = 0; n < insn->n; n++) { - struct serial_data write; - - write.kind = is_digital; - write.index = chan; - write.value = data[n]; - serial2002_write(devpriv->tty, write); - } - return n; -} - -static int serial2002_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct serial2002_private *devpriv = dev->private; - int n; - int chan; - - chan = devpriv->analog_in_mapping[CR_CHAN(insn->chanspec)]; - for (n = 0; n < insn->n; n++) { - struct serial_data read; - - serial2002_poll_channel(devpriv->tty, chan); - while (1) { - read = serial2002_read(devpriv->tty, 1000); - if (read.kind != is_channel || read.index == chan) - break; - } - data[n] = read.value; - } - return n; -} - -static int serial2002_ao_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct serial2002_private *devpriv = dev->private; - int n; - int chan; - - chan = devpriv->analog_out_mapping[CR_CHAN(insn->chanspec)]; - for (n = 0; n < insn->n; n++) { - struct serial_data write; - - write.kind = is_channel; - write.index = chan; - write.value = data[n]; - serial2002_write(devpriv->tty, write); - devpriv->ao_readback[chan] = data[n]; - } - return n; -} - -static int serial2002_ao_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct serial2002_private *devpriv = dev->private; - int n; - int chan = CR_CHAN(insn->chanspec); - - for (n = 0; n < insn->n; n++) - data[n] = devpriv->ao_readback[chan]; - - return n; -} - -static int serial2002_encoder_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct serial2002_private *devpriv = dev->private; - int n; - int chan; - - chan = devpriv->encoder_in_mapping[CR_CHAN(insn->chanspec)]; - for (n = 0; n < insn->n; n++) { - struct serial_data read; - - serial2002_poll_channel(devpriv->tty, chan); - while (1) { - read = serial2002_read(devpriv->tty, 1000); - if (read.kind != is_channel || read.index == chan) - break; - } - data[n] = read.value; - } - return n; -} - -static int serial2002_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - struct serial2002_private *devpriv; - struct comedi_subdevice *s; - int ret; - - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - - devpriv->port = it->options[0]; - devpriv->speed = it->options[1]; - - ret = comedi_alloc_subdevices(dev, 5); - if (ret) - return ret; - - /* digital input subdevice */ - s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_read = serial2002_di_insn_read; - - /* digital output subdevice */ - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_write = serial2002_do_insn_write; - - /* analog input subdevice */ - s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_read = serial2002_ai_insn_read; - - /* analog output subdevice */ - s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_write = serial2002_ao_insn_write; - s->insn_read = serial2002_ao_insn_read; - - /* encoder input subdevice */ - s = &dev->subdevices[4]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_LSAMPL; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_read = serial2002_encoder_insn_read; - - dev->open = serial2002_open; - dev->close = serial2002_close; - - return 0; -} - -static void serial2002_detach(struct comedi_device *dev) -{ - struct comedi_subdevice *s; - int i; - - for (i = 0; i < dev->n_subdevices; i++) { - s = &dev->subdevices[i]; - kfree(s->maxdata_list); - kfree(s->range_table_list); - } -} - -static struct comedi_driver serial2002_driver = { - .driver_name = "serial2002", - .module = THIS_MODULE, - .attach = serial2002_attach, - .detach = serial2002_detach, -}; -module_comedi_driver(serial2002_driver); - -MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); -MODULE_LICENSE("GPL"); |