aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi')
-rw-r--r--drivers/staging/comedi/TODO1
-rw-r--r--drivers/staging/comedi/comedi.h599
-rw-r--r--drivers/staging/comedi/comedi_fops.c86
-rw-r--r--drivers/staging/comedi/comedi_pcmcia.h3
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c2
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c4
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c68
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c141
-rw-r--r--drivers/staging/comedi/drivers/comedi_isadma.c3
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c47
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c18
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c4
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c2
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c32
-rw-r--r--drivers/staging/comedi/drivers/mite.c72
-rw-r--r--drivers/staging/comedi/drivers/mite.h3
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_c_common.c0
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c625
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c20
-rw-r--r--drivers/staging/comedi/drivers/ni_tiocmd.c2
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c5
-rw-r--r--drivers/staging/comedi/drivers/s626.c33
23 files changed, 1224 insertions, 550 deletions
diff --git a/drivers/staging/comedi/TODO b/drivers/staging/comedi/TODO
index b68fbdb5eebf..f733c017f181 100644
--- a/drivers/staging/comedi/TODO
+++ b/drivers/staging/comedi/TODO
@@ -3,6 +3,7 @@ TODO:
- Lindent
- remove all wrappers
- audit userspace interface
+ - Fix coverity 1195261
- cleanup the individual comedi drivers as well
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
index 83bd309d011b..ad5297f6d418 100644
--- a/drivers/staging/comedi/comedi.h
+++ b/drivers/staging/comedi/comedi.h
@@ -1,6 +1,6 @@
/*
- * include/comedi.h (installed as /usr/include/comedi.h)
- * header file for comedi
+ * comedi.h
+ * header file for COMEDI user API
*
* COMEDI - Linux Control and Measurement Device Interface
* Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org>
@@ -72,12 +72,12 @@
#define CR_AREF(a) (((a) >> 24) & 0x03)
#define CR_FLAGS_MASK 0xfc000000
-#define CR_ALT_FILTER (1 << 26)
+#define CR_ALT_FILTER 0x04000000
#define CR_DITHER CR_ALT_FILTER
#define CR_DEGLITCH CR_ALT_FILTER
-#define CR_ALT_SOURCE (1 << 27)
-#define CR_EDGE (1 << 30)
-#define CR_INVERT (1 << 31)
+#define CR_ALT_SOURCE 0x08000000
+#define CR_EDGE 0x40000000
+#define CR_INVERT 0x80000000
#define AREF_GROUND 0x00 /* analog ref = analog ground */
#define AREF_COMMON 0x01 /* analog ref = analog common */
@@ -120,13 +120,6 @@
#define INSN_WAIT (5 | INSN_MASK_WRITE | INSN_MASK_SPECIAL)
#define INSN_INTTRIG (6 | INSN_MASK_WRITE | INSN_MASK_SPECIAL)
-/* trigger flags */
-/* These flags are used in comedi_trig structures */
-
-#define TRIG_DITHER 0x0002 /* enable dithering */
-#define TRIG_DEGLITCH 0x0004 /* enable deglitching */
-#define TRIG_CONFIG 0x0010 /* perform configuration, not triggering */
-
/* command flags */
/* These flags are used in comedi_cmd structures */
@@ -190,11 +183,8 @@
#define SDF_MAXDATA 0x0010 /* maxdata depends on channel */
#define SDF_FLAGS 0x0020 /* flags depend on channel */
#define SDF_RANGETYPE 0x0040 /* range type depends on channel */
-#define SDF_MODE0 0x0080 /* can do mode 0 */
-#define SDF_MODE1 0x0100 /* can do mode 1 */
-#define SDF_MODE2 0x0200 /* can do mode 2 */
-#define SDF_MODE3 0x0400 /* can do mode 3 */
-#define SDF_MODE4 0x0800 /* can do mode 4 */
+#define SDF_PWM_COUNTER 0x0080 /* PWM can automatically switch off */
+#define SDF_PWM_HBRIDGE 0x0100 /* PWM is signed (H-bridge) */
#define SDF_CMD 0x1000 /* can do commands (deprecated) */
#define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */
#define SDF_CMD_WRITE 0x4000 /* can do output commands */
@@ -217,30 +207,94 @@
#define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */
#define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */
#define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */
-/* re recycle these flags for PWM */
-#define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */
-#define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */
/* subdevice types */
+/**
+ * enum comedi_subdevice_type - COMEDI subdevice types
+ * @COMEDI_SUBD_UNUSED: Unused subdevice.
+ * @COMEDI_SUBD_AI: Analog input.
+ * @COMEDI_SUBD_AO: Analog output.
+ * @COMEDI_SUBD_DI: Digital input.
+ * @COMEDI_SUBD_DO: Digital output.
+ * @COMEDI_SUBD_DIO: Digital input/output.
+ * @COMEDI_SUBD_COUNTER: Counter.
+ * @COMEDI_SUBD_TIMER: Timer.
+ * @COMEDI_SUBD_MEMORY: Memory, EEPROM, DPRAM.
+ * @COMEDI_SUBD_CALIB: Calibration DACs.
+ * @COMEDI_SUBD_PROC: Processor, DSP.
+ * @COMEDI_SUBD_SERIAL: Serial I/O.
+ * @COMEDI_SUBD_PWM: Pulse-Width Modulation output.
+ */
enum comedi_subdevice_type {
- COMEDI_SUBD_UNUSED, /* unused by driver */
- COMEDI_SUBD_AI, /* analog input */
- COMEDI_SUBD_AO, /* analog output */
- COMEDI_SUBD_DI, /* digital input */
- COMEDI_SUBD_DO, /* digital output */
- COMEDI_SUBD_DIO, /* digital input/output */
- COMEDI_SUBD_COUNTER, /* counter */
- COMEDI_SUBD_TIMER, /* timer */
- COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */
- COMEDI_SUBD_CALIB, /* calibration DACs */
- COMEDI_SUBD_PROC, /* processor, DSP */
- COMEDI_SUBD_SERIAL, /* serial IO */
- COMEDI_SUBD_PWM /* PWM */
+ COMEDI_SUBD_UNUSED,
+ COMEDI_SUBD_AI,
+ COMEDI_SUBD_AO,
+ COMEDI_SUBD_DI,
+ COMEDI_SUBD_DO,
+ COMEDI_SUBD_DIO,
+ COMEDI_SUBD_COUNTER,
+ COMEDI_SUBD_TIMER,
+ COMEDI_SUBD_MEMORY,
+ COMEDI_SUBD_CALIB,
+ COMEDI_SUBD_PROC,
+ COMEDI_SUBD_SERIAL,
+ COMEDI_SUBD_PWM
};
/* configuration instructions */
+/**
+ * enum configuration_ids - COMEDI configuration instruction codes
+ * @INSN_CONFIG_DIO_INPUT: Configure digital I/O as input.
+ * @INSN_CONFIG_DIO_OUTPUT: Configure digital I/O as output.
+ * @INSN_CONFIG_DIO_OPENDRAIN: Configure digital I/O as open-drain (or open
+ * collector) output.
+ * @INSN_CONFIG_ANALOG_TRIG: Configure analog trigger.
+ * @INSN_CONFIG_ALT_SOURCE: Configure alternate input source.
+ * @INSN_CONFIG_DIGITAL_TRIG: Configure digital trigger.
+ * @INSN_CONFIG_BLOCK_SIZE: Configure block size for DMA transfers.
+ * @INSN_CONFIG_TIMER_1: Configure divisor for external clock.
+ * @INSN_CONFIG_FILTER: Configure a filter.
+ * @INSN_CONFIG_CHANGE_NOTIFY: Configure change notification for digital
+ * inputs. (New drivers should use
+ * %INSN_CONFIG_DIGITAL_TRIG instead.)
+ * @INSN_CONFIG_SERIAL_CLOCK: Configure clock for serial I/O.
+ * @INSN_CONFIG_BIDIRECTIONAL_DATA: Send and receive byte over serial I/O.
+ * @INSN_CONFIG_DIO_QUERY: Query direction of digital I/O channel.
+ * @INSN_CONFIG_PWM_OUTPUT: Configure pulse-width modulator output.
+ * @INSN_CONFIG_GET_PWM_OUTPUT: Get pulse-width modulator output configuration.
+ * @INSN_CONFIG_ARM: Arm a subdevice or channel.
+ * @INSN_CONFIG_DISARM: Disarm a subdevice or channel.
+ * @INSN_CONFIG_GET_COUNTER_STATUS: Get counter status.
+ * @INSN_CONFIG_RESET: Reset a subdevice or channel.
+ * @INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: Configure counter/timer as
+ * single pulse generator.
+ * @INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR: Configure counter/timer as
+ * pulse train generator.
+ * @INSN_CONFIG_GPCT_QUADRATURE_ENCODER: Configure counter as a quadrature
+ * encoder.
+ * @INSN_CONFIG_SET_GATE_SRC: Set counter/timer gate source.
+ * @INSN_CONFIG_GET_GATE_SRC: Get counter/timer gate source.
+ * @INSN_CONFIG_SET_CLOCK_SRC: Set counter/timer master clock source.
+ * @INSN_CONFIG_GET_CLOCK_SRC: Get counter/timer master clock source.
+ * @INSN_CONFIG_SET_OTHER_SRC: Set counter/timer "other" source.
+ * @INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: Get size (in bytes) of subdevice's
+ * on-board FIFOs used during streaming
+ * input/output.
+ * @INSN_CONFIG_SET_COUNTER_MODE: Set counter/timer mode.
+ * @INSN_CONFIG_8254_SET_MODE: (Deprecated) Same as
+ * %INSN_CONFIG_SET_COUNTER_MODE.
+ * @INSN_CONFIG_8254_READ_STATUS: Read status of 8254 counter channel.
+ * @INSN_CONFIG_SET_ROUTING: Set routing for a channel.
+ * @INSN_CONFIG_GET_ROUTING: Get routing for a channel.
+ * @INSN_CONFIG_PWM_SET_PERIOD: Set PWM period in nanoseconds.
+ * @INSN_CONFIG_PWM_GET_PERIOD: Get PWM period in nanoseconds.
+ * @INSN_CONFIG_GET_PWM_STATUS: Get PWM status.
+ * @INSN_CONFIG_PWM_SET_H_BRIDGE: Set PWM H bridge duty cycle and polarity for
+ * a relay simultaneously.
+ * @INSN_CONFIG_PWM_GET_H_BRIDGE: Get PWM H bridge duty cycle and polarity.
+ */
enum configuration_ids {
INSN_CONFIG_DIO_INPUT = 0,
INSN_CONFIG_DIO_OUTPUT = 1,
@@ -265,72 +319,76 @@ enum configuration_ids {
INSN_CONFIG_DISARM = 32,
INSN_CONFIG_GET_COUNTER_STATUS = 33,
INSN_CONFIG_RESET = 34,
- /* Use CTR as single pulsegenerator */
INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001,
- /* Use CTR as pulsetraingenerator */
INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002,
- /* Use the counter as encoder */
INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003,
- INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */
- INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */
- /* Set master clock source */
+ INSN_CONFIG_SET_GATE_SRC = 2001,
+ INSN_CONFIG_GET_GATE_SRC = 2002,
INSN_CONFIG_SET_CLOCK_SRC = 2003,
- INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */
- INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */
- /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */
- /* Get size in bytes of subdevice's on-board fifos used during
- * streaming input/output
- */
+ INSN_CONFIG_GET_CLOCK_SRC = 2004,
+ INSN_CONFIG_SET_OTHER_SRC = 2005,
INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006,
INSN_CONFIG_SET_COUNTER_MODE = 4097,
- /* INSN_CONFIG_8254_SET_MODE is deprecated */
INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE,
INSN_CONFIG_8254_READ_STATUS = 4098,
INSN_CONFIG_SET_ROUTING = 4099,
INSN_CONFIG_GET_ROUTING = 4109,
- /* PWM */
- INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */
- INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */
- INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */
- /* sets H bridge: duty cycle and sign bit for a relay at the
- * same time
- */
+ INSN_CONFIG_PWM_SET_PERIOD = 5000,
+ INSN_CONFIG_PWM_GET_PERIOD = 5001,
+ INSN_CONFIG_GET_PWM_STATUS = 5002,
INSN_CONFIG_PWM_SET_H_BRIDGE = 5003,
- /* gets H bridge data: duty cycle and the sign bit */
INSN_CONFIG_PWM_GET_H_BRIDGE = 5004
};
-/*
- * Settings for INSN_CONFIG_DIGITAL_TRIG:
- * data[0] = INSN_CONFIG_DIGITAL_TRIG
- * data[1] = trigger ID
- * data[2] = configuration operation
- * data[3] = configuration parameter 1
- * data[4] = configuration parameter 2
- * data[5] = configuration parameter 3
+/**
+ * enum comedi_digital_trig_op - operations for configuring a digital trigger
+ * @COMEDI_DIGITAL_TRIG_DISABLE: Return digital trigger to its default,
+ * inactive, unconfigured state.
+ * @COMEDI_DIGITAL_TRIG_ENABLE_EDGES: Set rising and/or falling edge inputs
+ * that each can fire the trigger.
+ * @COMEDI_DIGITAL_TRIG_ENABLE_LEVELS: Set a combination of high and/or low
+ * level inputs that can fire the trigger.
+ *
+ * These are used with the %INSN_CONFIG_DIGITAL_TRIG configuration instruction.
+ * The data for the configuration instruction is as follows...
*
- * operation parameter 1 parameter 2 parameter 3
- * --------------------------------- ----------- ----------- -----------
- * COMEDI_DIGITAL_TRIG_DISABLE
- * COMEDI_DIGITAL_TRIG_ENABLE_EDGES left-shift rising-edges falling-edges
- * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS left-shift high-levels low-levels
+ * data[%0] = %INSN_CONFIG_DIGITAL_TRIG
*
- * COMEDI_DIGITAL_TRIG_DISABLE returns the trigger to its default, inactive,
- * unconfigured state.
+ * data[%1] = trigger ID
*
- * COMEDI_DIGITAL_TRIG_ENABLE_EDGES sets the rising and/or falling edge inputs
- * that each can fire the trigger.
+ * data[%2] = configuration operation
*
- * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS sets a combination of high and/or low
- * level inputs that can fire the trigger.
+ * data[%3] = configuration parameter 1
*
- * "left-shift" is useful if the trigger has more than 32 inputs to specify the
- * first input for this configuration.
+ * data[%4] = configuration parameter 2
*
- * Some sequences of INSN_CONFIG_DIGITAL_TRIG instructions may have a (partly)
+ * data[%5] = configuration parameter 3
+ *
+ * The trigger ID (data[%1]) is used to differentiate multiple digital triggers
+ * belonging to the same subdevice. The configuration operation (data[%2]) is
+ * one of the enum comedi_digital_trig_op values. The configuration
+ * parameters (data[%3], data[%4], and data[%5]) depend on the operation; they
+ * are not used with %COMEDI_DIGITAL_TRIG_DISABLE.
+ *
+ * For %COMEDI_DIGITAL_TRIG_ENABLE_EDGES and %COMEDI_DIGITAL_TRIG_ENABLE_LEVELS,
+ * configuration parameter 1 (data[%3]) contains a "left-shift" value that
+ * specifies the input corresponding to bit 0 of configuration parameters 2
+ * and 3. This is useful if the trigger has more than 32 inputs.
+ *
+ * For %COMEDI_DIGITAL_TRIG_ENABLE_EDGES, configuration parameter 2 (data[%4])
+ * specifies which of up to 32 inputs have rising-edge sensitivity, and
+ * configuration parameter 3 (data[%5]) specifies which of up to 32 inputs
+ * have falling-edge sensitivity that can fire the trigger.
+ *
+ * For %COMEDI_DIGITAL_TRIG_ENABLE_LEVELS, configuration parameter 2 (data[%4])
+ * specifies which of up to 32 inputs must be at a high level, and
+ * configuration parameter 3 (data[%5]) specifies which of up to 32 inputs
+ * must be at a low level for the trigger to fire.
+ *
+ * Some sequences of %INSN_CONFIG_DIGITAL_TRIG instructions may have a (partly)
* accumulative effect, depending on the low-level driver. This is useful
- * when setting up a trigger that has more than 32 inputs or has a combination
- * of edge and level triggered inputs.
+ * when setting up a trigger that has more than 32 inputs, or has a combination
+ * of edge- and level-triggered inputs.
*/
enum comedi_digital_trig_op {
COMEDI_DIGITAL_TRIG_DISABLE = 0,
@@ -338,18 +396,49 @@ enum comedi_digital_trig_op {
COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = 2
};
+/**
+ * enum comedi_io_direction - COMEDI I/O directions
+ * @COMEDI_INPUT: Input.
+ * @COMEDI_OUTPUT: Output.
+ * @COMEDI_OPENDRAIN: Open-drain (or open-collector) output.
+ *
+ * These are used by the %INSN_CONFIG_DIO_QUERY configuration instruction to
+ * report a direction. They may also be used in other places where a direction
+ * needs to be specified.
+ */
enum comedi_io_direction {
COMEDI_INPUT = 0,
COMEDI_OUTPUT = 1,
COMEDI_OPENDRAIN = 2
};
+/**
+ * enum comedi_support_level - support level for a COMEDI feature
+ * @COMEDI_UNKNOWN_SUPPORT: Unspecified support for feature.
+ * @COMEDI_SUPPORTED: Feature is supported.
+ * @COMEDI_UNSUPPORTED: Feature is unsupported.
+ */
enum comedi_support_level {
COMEDI_UNKNOWN_SUPPORT = 0,
COMEDI_SUPPORTED,
COMEDI_UNSUPPORTED
};
+/**
+ * enum comedi_counter_status_flags - counter status bits
+ * @COMEDI_COUNTER_ARMED: Counter is armed.
+ * @COMEDI_COUNTER_COUNTING: Counter is counting.
+ * @COMEDI_COUNTER_TERMINAL_COUNT: Counter reached terminal count.
+ *
+ * These bitwise values are used by the %INSN_CONFIG_GET_COUNTER_STATUS
+ * configuration instruction to report the status of a counter.
+ */
+enum comedi_counter_status_flags {
+ COMEDI_COUNTER_ARMED = 0x1,
+ COMEDI_COUNTER_COUNTING = 0x2,
+ COMEDI_COUNTER_TERMINAL_COUNT = 0x4,
+};
+
/* ioctls */
#define CIO 'd'
@@ -357,7 +446,7 @@ enum comedi_support_level {
#define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo)
#define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo)
#define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo)
-#define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
+/* _IOWR(CIO, 4, ...) is reserved */
#define COMEDI_LOCK _IO(CIO, 5)
#define COMEDI_UNLOCK _IO(CIO, 6)
#define COMEDI_CANCEL _IO(CIO, 7)
@@ -374,21 +463,19 @@ enum comedi_support_level {
/* structures */
-struct comedi_trig {
- unsigned int subdev; /* subdevice */
- unsigned int mode; /* mode */
- unsigned int flags;
- unsigned int n_chan; /* number of channels */
- unsigned int *chanlist; /* channel/range list */
- short *data; /* data list, size depends on subd flags */
- unsigned int n; /* number of scans */
- unsigned int trigsrc;
- unsigned int trigvar;
- unsigned int trigvar1;
- unsigned int data_len;
- unsigned int unused[3];
-};
-
+/**
+ * struct comedi_insn - COMEDI instruction
+ * @insn: COMEDI instruction type (%INSN_xxx).
+ * @n: Length of @data[].
+ * @data: Pointer to data array operated on by the instruction.
+ * @subdev: Subdevice index.
+ * @chanspec: A packed "chanspec" value consisting of channel number,
+ * analog range index, analog reference type, and flags.
+ * @unused: Reserved for future use.
+ *
+ * This is used with the %COMEDI_INSN ioctl, and indirectly with the
+ * %COMEDI_INSNLIST ioctl.
+ */
struct comedi_insn {
unsigned int insn;
unsigned int n;
@@ -398,11 +485,95 @@ struct comedi_insn {
unsigned int unused[3];
};
+/**
+ * struct comedi_insnlist - list of COMEDI instructions
+ * @n_insns: Number of COMEDI instructions.
+ * @insns: Pointer to array COMEDI instructions.
+ *
+ * This is used with the %COMEDI_INSNLIST ioctl.
+ */
struct comedi_insnlist {
unsigned int n_insns;
struct comedi_insn __user *insns;
};
+/**
+ * struct comedi_cmd - COMEDI asynchronous acquisition command details
+ * @subdev: Subdevice index.
+ * @flags: Command flags (%CMDF_xxx).
+ * @start_src: "Start acquisition" trigger source (%TRIG_xxx).
+ * @start_arg: "Start acquisition" trigger argument.
+ * @scan_begin_src: "Scan begin" trigger source.
+ * @scan_begin_arg: "Scan begin" trigger argument.
+ * @convert_src: "Convert" trigger source.
+ * @convert_arg: "Convert" trigger argument.
+ * @scan_end_src: "Scan end" trigger source.
+ * @scan_end_arg: "Scan end" trigger argument.
+ * @stop_src: "Stop acquisition" trigger source.
+ * @stop_arg: "Stop acquisition" trigger argument.
+ * @chanlist: Pointer to array of "chanspec" values, containing a
+ * sequence of channel numbers packed with analog range
+ * index, etc.
+ * @chanlist_len: Number of channels in sequence.
+ * @data: Pointer to miscellaneous set-up data (not used).
+ * @data_len: Length of miscellaneous set-up data.
+ *
+ * This is used with the %COMEDI_CMD or %COMEDI_CMDTEST ioctl to set-up
+ * or validate an asynchronous acquisition command. The ioctl may modify
+ * the &struct comedi_cmd and copy it back to the caller.
+ *
+ * Optional command @flags values that can be ORed together...
+ *
+ * %CMDF_BOGUS - makes %COMEDI_CMD ioctl return error %EAGAIN instead of
+ * starting the command.
+ *
+ * %CMDF_PRIORITY - requests "hard real-time" processing (which is not
+ * supported in this version of COMEDI).
+ *
+ * %CMDF_WAKE_EOS - requests the command makes data available for reading
+ * after every "scan" period.
+ *
+ * %CMDF_WRITE - marks the command as being in the "write" (to device)
+ * direction. This does not need to be specified by the caller unless the
+ * subdevice supports commands in either direction.
+ *
+ * %CMDF_RAWDATA - prevents the command from "munging" the data between the
+ * COMEDI sample format and the raw hardware sample format.
+ *
+ * %CMDF_ROUND_NEAREST - requests timing periods to be rounded to nearest
+ * supported values.
+ *
+ * %CMDF_ROUND_DOWN - requests timing periods to be rounded down to supported
+ * values (frequencies rounded up).
+ *
+ * %CMDF_ROUND_UP - requests timing periods to be rounded up to supported
+ * values (frequencies rounded down).
+ *
+ * Trigger source values for @start_src, @scan_begin_src, @convert_src,
+ * @scan_end_src, and @stop_src...
+ *
+ * %TRIG_ANY - "all ones" value used to test which trigger sources are
+ * supported.
+ *
+ * %TRIG_INVALID - "all zeroes" value used to indicate that all requested
+ * trigger sources are invalid.
+ *
+ * %TRIG_NONE - never trigger (often used as a @stop_src value).
+ *
+ * %TRIG_NOW - trigger after '_arg' nanoseconds.
+ *
+ * %TRIG_FOLLOW - trigger follows another event.
+ *
+ * %TRIG_TIMER - trigger every '_arg' nanoseconds.
+ *
+ * %TRIG_COUNT - trigger when count '_arg' is reached.
+ *
+ * %TRIG_EXT - trigger on external signal specified by '_arg'.
+ *
+ * %TRIG_INT - trigger on internal, software trigger specified by '_arg'.
+ *
+ * %TRIG_OTHER - trigger on other, driver-defined signal specified by '_arg'.
+ */
struct comedi_cmd {
unsigned int subdev;
unsigned int flags;
@@ -422,13 +593,31 @@ struct comedi_cmd {
unsigned int stop_src;
unsigned int stop_arg;
- unsigned int *chanlist; /* channel/range list */
+ unsigned int *chanlist;
unsigned int chanlist_len;
- short __user *data; /* data list, size depends on subd flags */
+ short __user *data;
unsigned int data_len;
};
+/**
+ * struct comedi_chaninfo - used to retrieve per-channel information
+ * @subdev: Subdevice index.
+ * @maxdata_list: Optional pointer to per-channel maximum data values.
+ * @flaglist: Optional pointer to per-channel flags.
+ * @rangelist: Optional pointer to per-channel range types.
+ * @unused: Reserved for future use.
+ *
+ * This is used with the %COMEDI_CHANINFO ioctl to get per-channel information
+ * for the subdevice. Use of this requires knowledge of the number of channels
+ * and subdevice flags obtained using the %COMEDI_SUBDINFO ioctl.
+ *
+ * The @maxdata_list member must be %NULL unless the %SDF_MAXDATA subdevice
+ * flag is set. The @flaglist member must be %NULL unless the %SDF_FLAGS
+ * subdevice flag is set. The @rangelist member must be %NULL unless the
+ * %SDF_RANGETYPE subdevice flag is set. Otherwise, the arrays they point to
+ * must be at least as long as the number of channels.
+ */
struct comedi_chaninfo {
unsigned int subdev;
unsigned int __user *maxdata_list;
@@ -437,17 +626,149 @@ struct comedi_chaninfo {
unsigned int unused[4];
};
+/**
+ * struct comedi_rangeinfo - used to retrieve the range table for a channel
+ * @range_type: Encodes subdevice index (bits 27:24), channel index
+ * (bits 23:16) and range table length (bits 15:0).
+ * @range_ptr: Pointer to array of @struct comedi_krange to be filled
+ * in with the range table for the channel or subdevice.
+ *
+ * This is used with the %COMEDI_RANGEINFO ioctl to retrieve the range table
+ * for a specific channel (if the subdevice has the %SDF_RANGETYPE flag set to
+ * indicate that the range table depends on the channel), or for the subdevice
+ * as a whole (if the %SDF_RANGETYPE flag is clear, indicating the range table
+ * is shared by all channels).
+ *
+ * The @range_type value is an input to the ioctl and comes from a previous
+ * use of the %COMEDI_SUBDINFO ioctl (if the %SDF_RANGETYPE flag is clear),
+ * or the %COMEDI_CHANINFO ioctl (if the %SDF_RANGETYPE flag is set).
+ */
struct comedi_rangeinfo {
unsigned int range_type;
void __user *range_ptr;
};
+/**
+ * struct comedi_krange - describes a range in a range table
+ * @min: Minimum value in millionths (1e-6) of a unit.
+ * @max: Maximum value in millionths (1e-6) of a unit.
+ * @flags: Indicates the units (in bits 7:0) OR'ed with optional flags.
+ *
+ * A range table is associated with a single channel, or with all channels in a
+ * subdevice, and a list of one or more ranges. A %struct comedi_krange
+ * describes the physical range of units for one of those ranges. Sample
+ * values in COMEDI are unsigned from %0 up to some 'maxdata' value. The
+ * mapping from sample values to physical units is assumed to be nomimally
+ * linear (for the purpose of describing the range), with sample value %0
+ * mapping to @min, and the 'maxdata' sample value mapping to @max.
+ *
+ * The currently defined units are %UNIT_volt (%0), %UNIT_mA (%1), and
+ * %UNIT_none (%2). The @min and @max values are the physical range multiplied
+ * by 1e6, so a @max value of %1000000 (with %UNIT_volt) represents a maximal
+ * value of 1 volt.
+ *
+ * The only defined flag value is %RF_EXTERNAL (%0x100), indicating that the
+ * the range needs to be multiplied by an external reference.
+ */
struct comedi_krange {
- int min; /* fixed point, multiply by 1e-6 */
- int max; /* fixed point, multiply by 1e-6 */
+ int min;
+ int max;
unsigned int flags;
};
+/**
+ * struct comedi_subdinfo - used to retrieve information about a subdevice
+ * @type: Type of subdevice from &enum comedi_subdevice_type.
+ * @n_chan: Number of channels the subdevice supports.
+ * @subd_flags: A mixture of static and dynamic flags describing
+ * aspects of the subdevice and its current state.
+ * @timer_type: Timer type. Always set to %5 ("nanosecond timer").
+ * @len_chanlist: Maximum length of a channel list if the subdevice
+ * supports asynchronous acquisition commands.
+ * @maxdata: Maximum sample value for all channels if the
+ * %SDF_MAXDATA subdevice flag is clear.
+ * @flags: Channel flags for all channels if the %SDF_FLAGS
+ * subdevice flag is clear.
+ * @range_type: The range type for all channels if the %SDF_RANGETYPE
+ * subdevice flag is clear. Encodes the subdevice index
+ * (bits 27:24), a dummy channel index %0 (bits 23:16),
+ * and the range table length (bits 15:0).
+ * @settling_time_0: Not used.
+ * @insn_bits_support: Set to %COMEDI_SUPPORTED if the subdevice supports the
+ * %INSN_BITS instruction, or to %COMEDI_UNSUPPORTED if it
+ * does not.
+ * @unused: Reserved for future use.
+ *
+ * This is used with the %COMEDI_SUBDINFO ioctl which copies an array of
+ * &struct comedi_subdinfo back to user space, with one element per subdevice.
+ * Use of this requires knowledge of the number of subdevices obtained from
+ * the %COMEDI_DEVINFO ioctl.
+ *
+ * These are the @subd_flags values that may be ORed together...
+ *
+ * %SDF_BUSY - the subdevice is busy processing an asynchronous command or a
+ * synchronous instruction.
+ *
+ * %SDF_BUSY_OWNER - the subdevice is busy processing an asynchronous
+ * acquisition command started on the current file object (the file object
+ * issuing the %COMEDI_SUBDINFO ioctl).
+ *
+ * %SDF_LOCKED - the subdevice is locked by a %COMEDI_LOCK ioctl.
+ *
+ * %SDF_LOCK_OWNER - the subdevice is locked by a %COMEDI_LOCK ioctl from the
+ * current file object.
+ *
+ * %SDF_MAXDATA - maximum sample values are channel-specific.
+ *
+ * %SDF_FLAGS - channel flags are channel-specific.
+ *
+ * %SDF_RANGETYPE - range types are channel-specific.
+ *
+ * %SDF_PWM_COUNTER - PWM can switch off automatically.
+ *
+ * %SDF_PWM_HBRIDGE - or PWM is signed (H-bridge).
+ *
+ * %SDF_CMD - the subdevice supports asynchronous commands.
+ *
+ * %SDF_SOFT_CALIBRATED - the subdevice uses software calibration.
+ *
+ * %SDF_CMD_WRITE - the subdevice supports asynchronous commands in the output
+ * ("write") direction.
+ *
+ * %SDF_CMD_READ - the subdevice supports asynchronous commands in the input
+ * ("read") direction.
+ *
+ * %SDF_READABLE - the subdevice is readable (e.g. analog input).
+ *
+ * %SDF_WRITABLE (aliased as %SDF_WRITEABLE) - the subdevice is writable (e.g.
+ * analog output).
+ *
+ * %SDF_INTERNAL - the subdevice has no externally visible lines.
+ *
+ * %SDF_GROUND - the subdevice can use ground as an analog reference.
+ *
+ * %SDF_COMMON - the subdevice can use a common analog reference.
+ *
+ * %SDF_DIFF - the subdevice can use differential inputs (or outputs).
+ *
+ * %SDF_OTHER - the subdevice can use some other analog reference.
+ *
+ * %SDF_DITHER - the subdevice can do dithering.
+ *
+ * %SDF_DEGLITCH - the subdevice can do deglitching.
+ *
+ * %SDF_MMAP - this is never set.
+ *
+ * %SDF_RUNNING - an asynchronous command is still running.
+ *
+ * %SDF_LSAMPL - the subdevice uses "long" (32-bit) samples (for asynchronous
+ * command data).
+ *
+ * %SDF_PACKED - the subdevice packs several DIO samples into a single sample
+ * (for asynchronous command data).
+ *
+ * No "channel flags" (@flags) values are currently defined.
+ */
struct comedi_subdinfo {
unsigned int type;
unsigned int n_chan;
@@ -455,14 +776,26 @@ struct comedi_subdinfo {
unsigned int timer_type;
unsigned int len_chanlist;
unsigned int maxdata;
- unsigned int flags; /* channel flags */
- unsigned int range_type; /* lookup in kernel */
+ unsigned int flags;
+ unsigned int range_type;
unsigned int settling_time_0;
- /* see support_level enum for values */
unsigned insn_bits_support;
unsigned int unused[8];
};
+/**
+ * struct comedi_devinfo - used to retrieve information about a COMEDI device
+ * @version_code: COMEDI version code.
+ * @n_subdevs: Number of subdevices the device has.
+ * @driver_name: Null-terminated COMEDI driver name.
+ * @board_name: Null-terminated COMEDI board name.
+ * @read_subdevice: Index of the current "read" subdevice (%-1 if none).
+ * @write_subdevice: Index of the current "write" subdevice (%-1 if none).
+ * @unused: Reserved for future use.
+ *
+ * This is used with the %COMEDI_DEVINFO ioctl to get basic information about
+ * the device.
+ */
struct comedi_devinfo {
unsigned int version_code;
unsigned int n_subdevs;
@@ -473,11 +806,45 @@ struct comedi_devinfo {
int unused[30];
};
+/**
+ * struct comedi_devconfig - used to configure a legacy COMEDI device
+ * @board_name: Null-terminated string specifying the type of board
+ * to configure.
+ * @options: An array of integer configuration options.
+ *
+ * This is used with the %COMEDI_DEVCONFIG ioctl to configure a "legacy" COMEDI
+ * device, such as an ISA card. Not all COMEDI drivers support this. Those
+ * that do either expect the specified board name to match one of a list of
+ * names registered with the COMEDI core, or expect the specified board name
+ * to match the COMEDI driver name itself. The configuration options are
+ * handled in a driver-specific manner.
+ */
struct comedi_devconfig {
char board_name[COMEDI_NAMELEN];
int options[COMEDI_NDEVCONFOPTS];
};
+/**
+ * struct comedi_bufconfig - used to set or get buffer size for a subdevice
+ * @subdevice: Subdevice index.
+ * @flags: Not used.
+ * @maximum_size: Maximum allowed buffer size.
+ * @size: Buffer size.
+ * @unused: Reserved for future use.
+ *
+ * This is used with the %COMEDI_BUFCONFIG ioctl to get or configure the
+ * maximum buffer size and current buffer size for a COMEDI subdevice that
+ * supports asynchronous commands. If the subdevice does not support
+ * asynchronous commands, @maximum_size and @size are ignored and set to 0.
+ *
+ * On ioctl input, non-zero values of @maximum_size and @size specify a
+ * new maximum size and new current size (in bytes), respectively. These
+ * will by rounded up to a multiple of %PAGE_SIZE. Specifying a new maximum
+ * size requires admin capabilities.
+ *
+ * On ioctl output, @maximum_size and @size and set to the current maximum
+ * buffer size and current buffer size, respectively.
+ */
struct comedi_bufconfig {
unsigned int subdevice;
unsigned int flags;
@@ -488,6 +855,23 @@ struct comedi_bufconfig {
unsigned int unused[4];
};
+/**
+ * struct comedi_bufinfo - used to manipulate buffer position for a subdevice
+ * @subdevice: Subdevice index.
+ * @bytes_read: Specify amount to advance read position for an
+ * asynchronous command in the input ("read") direction.
+ * @buf_write_ptr: Current write position (index) within the buffer.
+ * @buf_read_ptr: Current read position (index) within the buffer.
+ * @buf_write_count: Total amount written, modulo 2^32.
+ * @buf_read_count: Total amount read, modulo 2^32.
+ * @bytes_written: Specify amount to advance write position for an
+ * asynchronous command in the output ("write") direction.
+ * @unused: Reserved for future use.
+ *
+ * This is used with the %COMEDI_BUFINFO ioctl to optionally advance the
+ * current read or write position in an asynchronous acquisition data buffer,
+ * and to get the current read and write positions in the buffer.
+ */
struct comedi_bufinfo {
unsigned int subdevice;
unsigned int bytes_read;
@@ -510,13 +894,13 @@ struct comedi_bufinfo {
#define RANGE_LENGTH(b) ((b) & 0xffff)
#define RF_UNIT(flags) ((flags) & 0xff)
-#define RF_EXTERNAL (1 << 8)
+#define RF_EXTERNAL 0x100
#define UNIT_volt 0
#define UNIT_mA 1
#define UNIT_none 2
-#define COMEDI_MIN_SPEED ((unsigned int)0xffffffff)
+#define COMEDI_MIN_SPEED 0xffffffffu
/**********************************************************/
/* everything after this line is ALPHA */
@@ -849,13 +1233,6 @@ enum ni_660x_pfi_routing {
#define NI_EXT_PFI(x) (NI_USUAL_PFI_SELECT(x) - 1)
#define NI_EXT_RTSI(x) (NI_USUAL_RTSI_SELECT(x) - 1)
-/* status bits for INSN_CONFIG_GET_COUNTER_STATUS */
-enum comedi_counter_status_flags {
- COMEDI_COUNTER_ARMED = 0x1,
- COMEDI_COUNTER_COUNTING = 0x2,
- COMEDI_COUNTER_TERMINAL_COUNT = 0x4,
-};
-
/*
* Clock sources for CDIO subdevice on NI m-series boards. Used as the
* scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index d57fadef47fc..7c7b477b0f28 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -686,13 +686,6 @@ static bool __comedi_is_subdevice_running(struct comedi_subdevice *s)
return comedi_is_runflags_running(runflags);
}
-static bool comedi_is_subdevice_idle(struct comedi_subdevice *s)
-{
- unsigned runflags = comedi_get_subdevice_runflags(s);
-
- return !(runflags & COMEDI_SRF_BUSY_MASK);
-}
-
bool comedi_can_auto_free_spriv(struct comedi_subdevice *s)
{
unsigned runflags = __comedi_get_subdevice_runflags(s);
@@ -1111,6 +1104,9 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
struct comedi_bufinfo bi;
struct comedi_subdevice *s;
struct comedi_async *async;
+ unsigned int runflags;
+ int retval = 0;
+ bool become_nonbusy = false;
if (copy_from_user(&bi, arg, sizeof(bi)))
return -EFAULT;
@@ -1122,48 +1118,56 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
async = s->async;
- if (!async) {
- dev_dbg(dev->class_dev,
- "subdevice does not have async capability\n");
- bi.buf_write_ptr = 0;
- bi.buf_read_ptr = 0;
- bi.buf_write_count = 0;
- bi.buf_read_count = 0;
- bi.bytes_read = 0;
- bi.bytes_written = 0;
- goto copyback;
- }
- if (!s->busy) {
- bi.bytes_read = 0;
- bi.bytes_written = 0;
- goto copyback_position;
- }
- if (s->busy != file)
- return -EACCES;
-
- if (bi.bytes_read && !(async->cmd.flags & CMDF_WRITE)) {
- bi.bytes_read = comedi_buf_read_alloc(s, bi.bytes_read);
- comedi_buf_read_free(s, bi.bytes_read);
+ if (!async || s->busy != file)
+ return -EINVAL;
- if (comedi_is_subdevice_idle(s) &&
- comedi_buf_read_n_available(s) == 0) {
- do_become_nonbusy(dev, s);
+ runflags = comedi_get_subdevice_runflags(s);
+ if (!(async->cmd.flags & CMDF_WRITE)) {
+ /* command was set up in "read" direction */
+ if (bi.bytes_read) {
+ comedi_buf_read_alloc(s, bi.bytes_read);
+ bi.bytes_read = comedi_buf_read_free(s, bi.bytes_read);
}
+ /*
+ * If nothing left to read, and command has stopped, and
+ * {"read" position not updated or command stopped normally},
+ * then become non-busy.
+ */
+ if (comedi_buf_read_n_available(s) == 0 &&
+ !comedi_is_runflags_running(runflags) &&
+ (bi.bytes_read == 0 ||
+ !comedi_is_runflags_in_error(runflags))) {
+ become_nonbusy = true;
+ if (comedi_is_runflags_in_error(runflags))
+ retval = -EPIPE;
+ }
+ bi.bytes_written = 0;
+ } else {
+ /* command was set up in "write" direction */
+ if (!comedi_is_runflags_running(runflags)) {
+ bi.bytes_written = 0;
+ become_nonbusy = true;
+ if (comedi_is_runflags_in_error(runflags))
+ retval = -EPIPE;
+ } else if (bi.bytes_written) {
+ comedi_buf_write_alloc(s, bi.bytes_written);
+ bi.bytes_written =
+ comedi_buf_write_free(s, bi.bytes_written);
+ }
+ bi.bytes_read = 0;
}
- if (bi.bytes_written && (async->cmd.flags & CMDF_WRITE)) {
- bi.bytes_written =
- comedi_buf_write_alloc(s, bi.bytes_written);
- comedi_buf_write_free(s, bi.bytes_written);
- }
-
-copyback_position:
bi.buf_write_count = async->buf_write_count;
bi.buf_write_ptr = async->buf_write_ptr;
bi.buf_read_count = async->buf_read_count;
bi.buf_read_ptr = async->buf_read_ptr;
-copyback:
+ if (become_nonbusy)
+ do_become_nonbusy(dev, s);
+
+ if (retval)
+ return retval;
+
if (copy_to_user(arg, &bi, sizeof(bi)))
return -EFAULT;
@@ -2220,7 +2224,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
retval = -EFAULT;
goto done;
}
- if (size & (~PAGE_MASK)) {
+ if (offset_in_page(size)) {
retval = -EFAULT;
goto done;
}
diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h
index 5d3db2b9b4a1..5a572c200a8b 100644
--- a/drivers/staging/comedi/comedi_pcmcia.h
+++ b/drivers/staging/comedi/comedi_pcmcia.h
@@ -39,7 +39,8 @@ void comedi_pcmcia_driver_unregister(struct comedi_driver *,
struct pcmcia_driver *);
/**
- * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver
+ * module_comedi_pcmcia_driver() - Helper macro for registering a comedi
+ * PCMCIA driver
* @__comedi_driver: comedi_driver struct
* @__pcmcia_driver: pcmcia_driver struct
*
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index 995096c78844..b6af3eba91fd 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -496,7 +496,7 @@ static int apci3xxx_ai_ns_to_timer(struct comedi_device *dev,
switch (flags & CMDF_ROUND_MASK) {
case CMDF_ROUND_NEAREST:
default:
- timer = (*ns + base / 2) / base;
+ timer = DIV_ROUND_CLOSEST(*ns, base);
break;
case CMDF_ROUND_DOWN:
timer = *ns / base;
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 4b39f6960c0a..907c39cc89d7 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -637,12 +637,12 @@ static unsigned int pci230_divide_ns(uint64_t ns, unsigned int timebase,
switch (flags & CMDF_ROUND_MASK) {
default:
case CMDF_ROUND_NEAREST:
- div += (rem + (timebase / 2)) / timebase;
+ div += DIV_ROUND_CLOSEST(rem, timebase);
break;
case CMDF_ROUND_DOWN:
break;
case CMDF_ROUND_UP:
- div += (rem + timebase - 1) / timebase;
+ div += DIV_ROUND_UP(rem, timebase);
break;
}
return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index d33b8fe872a7..c773b8ca6599 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -1376,7 +1376,7 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev,
num_entries = fifo->max_segment_length;
/* 1 == 256 entries, 2 == 512 entries, etc */
- num_increments = (num_entries + increment_size / 2) / increment_size;
+ num_increments = DIV_ROUND_CLOSEST(num_entries, increment_size);
bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask;
devpriv->fifo_size_bits &= ~fifo->fifo_size_reg_mask;
@@ -1480,35 +1480,39 @@ static int alloc_and_init_dma_members(struct comedi_device *dev)
/* allocate pci dma buffers */
for (i = 0; i < ai_dma_ring_count(board); i++) {
devpriv->ai_buffer[i] =
- pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
- &devpriv->ai_buffer_bus_addr[i]);
+ dma_alloc_coherent(&pcidev->dev, DMA_BUFFER_SIZE,
+ &devpriv->ai_buffer_bus_addr[i],
+ GFP_KERNEL);
if (!devpriv->ai_buffer[i])
return -ENOMEM;
}
for (i = 0; i < AO_DMA_RING_COUNT; i++) {
if (ao_cmd_is_supported(board)) {
devpriv->ao_buffer[i] =
- pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
- &devpriv->
- ao_buffer_bus_addr[i]);
+ dma_alloc_coherent(&pcidev->dev,
+ DMA_BUFFER_SIZE,
+ &devpriv->
+ ao_buffer_bus_addr[i],
+ GFP_KERNEL);
if (!devpriv->ao_buffer[i])
return -ENOMEM;
}
}
/* allocate dma descriptors */
devpriv->ai_dma_desc =
- pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) *
- ai_dma_ring_count(board),
- &devpriv->ai_dma_desc_bus_addr);
+ dma_alloc_coherent(&pcidev->dev, sizeof(struct plx_dma_desc) *
+ ai_dma_ring_count(board),
+ &devpriv->ai_dma_desc_bus_addr, GFP_KERNEL);
if (!devpriv->ai_dma_desc)
return -ENOMEM;
if (ao_cmd_is_supported(board)) {
devpriv->ao_dma_desc =
- pci_alloc_consistent(pcidev,
- sizeof(struct plx_dma_desc) *
- AO_DMA_RING_COUNT,
- &devpriv->ao_dma_desc_bus_addr);
+ dma_alloc_coherent(&pcidev->dev,
+ sizeof(struct plx_dma_desc) *
+ AO_DMA_RING_COUNT,
+ &devpriv->ao_dma_desc_bus_addr,
+ GFP_KERNEL);
if (!devpriv->ao_dma_desc)
return -ENOMEM;
}
@@ -1564,31 +1568,31 @@ static void cb_pcidas64_free_dma(struct comedi_device *dev)
/* free pci dma buffers */
for (i = 0; i < ai_dma_ring_count(board); i++) {
if (devpriv->ai_buffer[i])
- pci_free_consistent(pcidev,
- DMA_BUFFER_SIZE,
- devpriv->ai_buffer[i],
- devpriv->ai_buffer_bus_addr[i]);
+ dma_free_coherent(&pcidev->dev,
+ DMA_BUFFER_SIZE,
+ devpriv->ai_buffer[i],
+ devpriv->ai_buffer_bus_addr[i]);
}
for (i = 0; i < AO_DMA_RING_COUNT; i++) {
if (devpriv->ao_buffer[i])
- pci_free_consistent(pcidev,
- DMA_BUFFER_SIZE,
- devpriv->ao_buffer[i],
- devpriv->ao_buffer_bus_addr[i]);
+ dma_free_coherent(&pcidev->dev,
+ DMA_BUFFER_SIZE,
+ devpriv->ao_buffer[i],
+ devpriv->ao_buffer_bus_addr[i]);
}
/* free dma descriptors */
if (devpriv->ai_dma_desc)
- pci_free_consistent(pcidev,
- sizeof(struct plx_dma_desc) *
- ai_dma_ring_count(board),
- devpriv->ai_dma_desc,
- devpriv->ai_dma_desc_bus_addr);
+ dma_free_coherent(&pcidev->dev,
+ sizeof(struct plx_dma_desc) *
+ ai_dma_ring_count(board),
+ devpriv->ai_dma_desc,
+ devpriv->ai_dma_desc_bus_addr);
if (devpriv->ao_dma_desc)
- pci_free_consistent(pcidev,
- sizeof(struct plx_dma_desc) *
- AO_DMA_RING_COUNT,
- devpriv->ao_dma_desc,
- devpriv->ao_dma_desc_bus_addr);
+ dma_free_coherent(&pcidev->dev,
+ sizeof(struct plx_dma_desc) *
+ AO_DMA_RING_COUNT,
+ devpriv->ao_dma_desc,
+ devpriv->ao_dma_desc_bus_addr);
}
static inline void warn_external_queue(struct comedi_device *dev)
@@ -2004,7 +2008,7 @@ static unsigned int get_divisor(unsigned int ns, unsigned int flags)
break;
case CMDF_ROUND_NEAREST:
default:
- divisor = (ns + TIMER_BASE / 2) / TIMER_BASE;
+ divisor = DIV_ROUND_CLOSEST(ns, TIMER_BASE);
break;
}
return divisor;
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 19210d89f2b2..84ef45457c60 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -1,77 +1,78 @@
/*
- comedi/drivers/cb_pcimdda.c
- Computer Boards PCIM-DDA06-16 Comedi driver
- Author: Calin Culianu <calin@ajvar.org>
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
+ * comedi/drivers/cb_pcimdda.c
+ * Computer Boards PCIM-DDA06-16 Comedi driver
+ * Author: Calin Culianu <calin@ajvar.org>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
/*
-Driver: cb_pcimdda
-Description: Measurement Computing PCIM-DDA06-16
-Devices: [Measurement Computing] PCIM-DDA06-16 (cb_pcimdda)
-Author: Calin Culianu <calin@ajvar.org>
-Updated: Mon, 14 Apr 2008 15:15:51 +0100
-Status: works
-
-All features of the PCIM-DDA06-16 board are supported. This board
-has 6 16-bit AO channels, and the usual 8255 DIO setup. (24 channels,
-configurable in banks of 8 and 4, etc.). This board does not support commands.
-
-The board has a peculiar way of specifying AO gain/range settings -- You have
-1 jumper bank on the card, which either makes all 6 AO channels either
-5 Volt unipolar, 5V bipolar, 10 Volt unipolar or 10V bipolar.
-
-Since there is absolutely _no_ way to tell in software how this jumper is set
-(well, at least according to the rather thin spec. from Measurement Computing
- that comes with the board), the driver assumes the jumper is at its factory
-default setting of +/-5V.
-
-Also of note is the fact that this board features another jumper, whose
-state is also completely invisible to software. It toggles two possible AO
-output modes on the board:
-
- - Update Mode: Writing to an AO channel instantaneously updates the actual
- signal output by the DAC on the board (this is the factory default).
- - Simultaneous XFER Mode: Writing to an AO channel has no effect until
- you read from any one of the AO channels. This is useful for loading
- all 6 AO values, and then reading from any one of the AO channels on the
- device to instantly update all 6 AO values in unison. Useful for some
- control apps, I would assume? If your jumper is in this setting, then you
- need to issue your comedi_data_write()s to load all the values you want,
- then issue one comedi_data_read() on any channel on the AO subdevice
- to initiate the simultaneous XFER.
-
-Configuration Options: not applicable, uses PCI auto config
-*/
+ * Driver: cb_pcimdda
+ * Description: Measurement Computing PCIM-DDA06-16
+ * Devices: [Measurement Computing] PCIM-DDA06-16 (cb_pcimdda)
+ * Author: Calin Culianu <calin@ajvar.org>
+ * Updated: Mon, 14 Apr 2008 15:15:51 +0100
+ * Status: works
+ *
+ * All features of the PCIM-DDA06-16 board are supported.
+ * This board has 6 16-bit AO channels, and the usual 8255 DIO setup.
+ * (24 channels, configurable in banks of 8 and 4, etc.).
+ * This board does not support commands.
+ *
+ * The board has a peculiar way of specifying AO gain/range settings -- You have
+ * 1 jumper bank on the card, which either makes all 6 AO channels either
+ * 5 Volt unipolar, 5V bipolar, 10 Volt unipolar or 10V bipolar.
+ *
+ * Since there is absolutely _no_ way to tell in software how this jumper is set
+ * (well, at least according to the rather thin spec. from Measurement Computing
+ * that comes with the board), the driver assumes the jumper is at its factory
+ * default setting of +/-5V.
+ *
+ * Also of note is the fact that this board features another jumper, whose
+ * state is also completely invisible to software. It toggles two possible AO
+ * output modes on the board:
+ *
+ * - Update Mode: Writing to an AO channel instantaneously updates the actual
+ * signal output by the DAC on the board (this is the factory default).
+ * - Simultaneous XFER Mode: Writing to an AO channel has no effect until
+ * you read from any one of the AO channels. This is useful for loading
+ * all 6 AO values, and then reading from any one of the AO channels on the
+ * device to instantly update all 6 AO values in unison. Useful for some
+ * control apps, I would assume? If your jumper is in this setting, then you
+ * need to issue your comedi_data_write()s to load all the values you want,
+ * then issue one comedi_data_read() on any channel on the AO subdevice
+ * to initiate the simultaneous XFER.
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
/*
- This is a driver for the Computer Boards PCIM-DDA06-16 Analog Output
- card. This board has a unique register layout and as such probably
- deserves its own driver file.
-
- It is theoretically possible to integrate this board into the cb_pcidda
- file, but since that isn't my code, I didn't want to significantly
- modify that file to support this board (I thought it impolite to do so).
-
- At any rate, if you feel ambitious, please feel free to take
- the code out of this file and combine it with a more unified driver
- file.
-
- I would like to thank Timothy Curry <Timothy.Curry@rdec.redstone.army.mil>
- for lending me a board so that I could write this driver.
-
- -Calin Culianu <calin@ajvar.org>
+ * This is a driver for the Computer Boards PCIM-DDA06-16 Analog Output
+ * card. This board has a unique register layout and as such probably
+ * deserves its own driver file.
+ *
+ * It is theoretically possible to integrate this board into the cb_pcidda
+ * file, but since that isn't my code, I didn't want to significantly
+ * modify that file to support this board (I thought it impolite to do so).
+ *
+ * At any rate, if you feel ambitious, please feel free to take
+ * the code out of this file and combine it with a more unified driver
+ * file.
+ *
+ * I would like to thank Timothy Curry <Timothy.Curry@rdec.redstone.army.mil>
+ * for lending me a board so that I could write this driver.
+ *
+ * -Calin Culianu <calin@ajvar.org>
*/
#include <linux/module.h>
diff --git a/drivers/staging/comedi/drivers/comedi_isadma.c b/drivers/staging/comedi/drivers/comedi_isadma.c
index 6ba71d114a95..68ef9b1750be 100644
--- a/drivers/staging/comedi/drivers/comedi_isadma.c
+++ b/drivers/staging/comedi/drivers/comedi_isadma.c
@@ -132,8 +132,7 @@ unsigned int comedi_isadma_poll(struct comedi_isadma *dma)
result = result1;
if (result >= desc->size || result == 0)
return 0;
- else
- return desc->size - result;
+ return desc->size - result;
}
EXPORT_SYMBOL_GPL(comedi_isadma_poll);
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 4956a49a6140..5f848396c2f7 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -1,29 +1,30 @@
/*
- comedi/drivers/contec_pci_dio.c
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ * comedi/drivers/contec_pci_dio.c
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
/*
-Driver: contec_pci_dio
-Description: Contec PIO1616L digital I/O board
-Devices: [Contec] PIO1616L (contec_pci_dio)
-Author: Stefano Rivoir <s.rivoir@gts.it>
-Updated: Wed, 27 Jun 2007 13:00:06 +0100
-Status: works
-
-Configuration Options: not applicable, uses comedi PCI auto config
-*/
+ * Driver: contec_pci_dio
+ * Description: Contec PIO1616L digital I/O board
+ * Devices: [Contec] PIO1616L (contec_pci_dio)
+ * Author: Stefano Rivoir <s.rivoir@gts.it>
+ * Updated: Wed, 27 Jun 2007 13:00:06 +0100
+ * Status: works
+ *
+ * Configuration Options: not applicable, uses comedi PCI auto config
+ */
#include <linux/module.h>
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index 80e38dedd359..6c7b4d27c27c 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -68,17 +68,17 @@ Configuration options:
/* Command modifiers (only used with read/write), EXTTRIG can be
used with some other commands.
*/
-#define DT_MOD_DMA (1<<4)
-#define DT_MOD_CONT (1<<5)
-#define DT_MOD_EXTCLK (1<<6)
-#define DT_MOD_EXTTRIG (1<<7)
+#define DT_MOD_DMA BIT(4)
+#define DT_MOD_CONT BIT(5)
+#define DT_MOD_EXTCLK BIT(6)
+#define DT_MOD_EXTTRIG BIT(7)
/* Bits in status register */
-#define DT_S_DATA_OUT_READY (1<<0)
-#define DT_S_DATA_IN_FULL (1<<1)
-#define DT_S_READY (1<<2)
-#define DT_S_COMMAND (1<<3)
-#define DT_S_COMPOSITE_ERROR (1<<7)
+#define DT_S_DATA_OUT_READY BIT(0)
+#define DT_S_DATA_IN_FULL BIT(1)
+#define DT_S_READY BIT(2)
+#define DT_S_COMMAND BIT(3)
+#define DT_S_COMPOSITE_ERROR BIT(7)
/* registers */
#define DT2801_DATA 0
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 5a536a00066f..40bf00984fa5 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -371,13 +371,13 @@ static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
switch (flags & CMDF_ROUND_MASK) {
case CMDF_ROUND_NEAREST:
default:
- divider = (*ns + base / 2) / base;
+ divider = DIV_ROUND_CLOSEST(*ns, base);
break;
case CMDF_ROUND_DOWN:
divider = (*ns) / base;
break;
case CMDF_ROUND_UP:
- divider = (*ns + base - 1) / base;
+ divider = DIV_ROUND_UP(*ns, base);
break;
}
if (divider < 256) {
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index ab7a332fbcc4..19e0b7be8495 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -361,7 +361,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
switch (flags & CMDF_ROUND_MASK) {
case CMDF_ROUND_NEAREST:
default:
- divider = (*nanosec + base / 2) / base;
+ divider = DIV_ROUND_CLOSEST(*nanosec, base);
break;
case CMDF_ROUND_DOWN:
divider = (*nanosec) / base;
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index 46ca5d938d5b..63b5cbc44bda 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -499,18 +499,18 @@ static void gsc_hpdi_free_dma(struct comedi_device *dev)
/* free pci dma buffers */
for (i = 0; i < NUM_DMA_BUFFERS; i++) {
if (devpriv->dio_buffer[i])
- pci_free_consistent(pcidev,
- DMA_BUFFER_SIZE,
- devpriv->dio_buffer[i],
- devpriv->dio_buffer_phys_addr[i]);
+ dma_free_coherent(&pcidev->dev,
+ DMA_BUFFER_SIZE,
+ devpriv->dio_buffer[i],
+ devpriv->dio_buffer_phys_addr[i]);
}
/* free dma descriptors */
if (devpriv->dma_desc)
- pci_free_consistent(pcidev,
- sizeof(struct plx_dma_desc) *
- NUM_DMA_DESCRIPTORS,
- devpriv->dma_desc,
- devpriv->dma_desc_phys_addr);
+ dma_free_coherent(&pcidev->dev,
+ sizeof(struct plx_dma_desc) *
+ NUM_DMA_DESCRIPTORS,
+ devpriv->dma_desc,
+ devpriv->dma_desc_phys_addr);
}
static int gsc_hpdi_init(struct comedi_device *dev)
@@ -630,14 +630,16 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev,
/* allocate pci dma buffers */
for (i = 0; i < NUM_DMA_BUFFERS; i++) {
devpriv->dio_buffer[i] =
- pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
- &devpriv->dio_buffer_phys_addr[i]);
+ dma_alloc_coherent(&pcidev->dev, DMA_BUFFER_SIZE,
+ &devpriv->dio_buffer_phys_addr[i],
+ GFP_KERNEL);
}
/* allocate dma descriptors */
- devpriv->dma_desc = pci_alloc_consistent(pcidev,
- sizeof(struct plx_dma_desc) *
- NUM_DMA_DESCRIPTORS,
- &devpriv->dma_desc_phys_addr);
+ devpriv->dma_desc = dma_alloc_coherent(&pcidev->dev,
+ sizeof(struct plx_dma_desc) *
+ NUM_DMA_DESCRIPTORS,
+ &devpriv->dma_desc_phys_addr,
+ GFP_KERNEL);
if (devpriv->dma_desc_phys_addr & 0xf) {
dev_warn(dev->class_dev,
" dma descriptors not quad-word aligned (bug)\n");
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
index fa7ae2c04556..8f24702c3380 100644
--- a/drivers/staging/comedi/drivers/mite.c
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -297,7 +297,6 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
{
struct comedi_async *async = s->async;
unsigned int n_links;
- int i;
if (ring->descriptors) {
dma_free_coherent(ring->hw_dev,
@@ -326,17 +325,58 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
}
ring->n_links = n_links;
- for (i = 0; i < n_links; i++) {
+ return mite_init_ring_descriptors(ring, s, n_links << PAGE_SHIFT);
+}
+EXPORT_SYMBOL_GPL(mite_buf_change);
+
+/*
+ * initializes the ring buffer descriptors to provide correct DMA transfer links
+ * to the exact amount of memory required. When the ring buffer is allocated in
+ * mite_buf_change, the default is to initialize the ring to refer to the entire
+ * DMA data buffer. A command may call this function later to re-initialize and
+ * shorten the amount of memory that will be transferred.
+ */
+int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring,
+ struct comedi_subdevice *s,
+ unsigned int nbytes)
+{
+ struct comedi_async *async = s->async;
+ unsigned int n_full_links = nbytes >> PAGE_SHIFT;
+ unsigned int remainder = nbytes % PAGE_SIZE;
+ int i;
+
+ dev_dbg(s->device->class_dev,
+ "mite: init ring buffer to %u bytes\n", nbytes);
+
+ if ((n_full_links + (remainder > 0 ? 1 : 0)) > ring->n_links) {
+ dev_err(s->device->class_dev,
+ "mite: ring buffer too small for requested init\n");
+ return -ENOMEM;
+ }
+
+ /* We set the descriptors for all full links. */
+ for (i = 0; i < n_full_links; ++i) {
ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE);
ring->descriptors[i].addr =
cpu_to_le32(async->buf_map->page_list[i].dma_addr);
ring->descriptors[i].next =
- cpu_to_le32(ring->descriptors_dma_addr + (i +
- 1) *
- sizeof(struct mite_dma_descriptor));
+ cpu_to_le32(ring->descriptors_dma_addr +
+ (i + 1) * sizeof(struct mite_dma_descriptor));
}
- ring->descriptors[n_links - 1].next =
- cpu_to_le32(ring->descriptors_dma_addr);
+
+ /* the last link is either a remainder or was a full link. */
+ if (remainder > 0) {
+ /* set the lesser count for the remainder link */
+ ring->descriptors[i].count = cpu_to_le32(remainder);
+ ring->descriptors[i].addr =
+ cpu_to_le32(async->buf_map->page_list[i].dma_addr);
+ /* increment i so that assignment below refs last link */
+ ++i;
+ }
+
+ /* Assign the last link->next to point back to the head of the list. */
+ ring->descriptors[i - 1].next = cpu_to_le32(ring->descriptors_dma_addr);
+
/*
* barrier is meant to insure that all the writes to the dma descriptors
* have completed before the dma controller is commanded to read them
@@ -344,7 +384,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
smp_wmb();
return 0;
}
-EXPORT_SYMBOL_GPL(mite_buf_change);
+EXPORT_SYMBOL_GPL(mite_init_ring_descriptors);
void mite_prep_dma(struct mite_channel *mite_chan,
unsigned int num_device_bits, unsigned int num_memory_bits)
@@ -552,6 +592,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
unsigned int old_alloc_count = async->buf_read_alloc_count;
u32 nbytes_ub, nbytes_lb;
int count;
+ bool finite_regen = (cmd->stop_src == TRIG_NONE && stop_count != 0);
/* read alloc as much as we can */
comedi_buf_read_alloc(s, async->prealloc_bufsz);
@@ -561,11 +602,24 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan);
if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_ub - stop_count) > 0)
nbytes_ub = stop_count;
- if ((int)(nbytes_ub - old_alloc_count) > 0) {
+
+ if ((!finite_regen || stop_count > old_alloc_count) &&
+ ((int)(nbytes_ub - old_alloc_count) > 0)) {
dev_warn(s->device->class_dev, "mite: DMA underrun\n");
async->events |= COMEDI_CB_OVERFLOW;
return -1;
}
+
+ if (finite_regen) {
+ /*
+ * This is a special case where we continuously output a finite
+ * buffer. In this case, we do not free any of the memory,
+ * hence we expect that old_alloc_count will reach a maximum of
+ * stop_count bytes.
+ */
+ return 0;
+ }
+
count = nbytes_lb - async->buf_read_count;
if (count <= 0)
return 0;
diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
index c32d4e4ddccc..87534b07ec81 100644
--- a/drivers/staging/comedi/drivers/mite.h
+++ b/drivers/staging/comedi/drivers/mite.h
@@ -110,6 +110,9 @@ void mite_prep_dma(struct mite_channel *mite_chan,
unsigned int num_device_bits, unsigned int num_memory_bits);
int mite_buf_change(struct mite_dma_descriptor_ring *ring,
struct comedi_subdevice *s);
+int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring,
+ struct comedi_subdevice *s,
+ unsigned int nbytes);
enum mite_registers {
/*
diff --git a/drivers/staging/comedi/drivers/ni_mio_c_common.c b/drivers/staging/comedi/drivers/ni_mio_c_common.c
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/staging/comedi/drivers/ni_mio_c_common.c
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 5e8130a7d670..d1226c97664b 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -1166,8 +1166,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev,
comedi_buf_write_samples(s, &data, 1);
}
} else {
- if (n > sizeof(devpriv->ai_fifo_buffer) /
- sizeof(devpriv->ai_fifo_buffer[0])) {
+ if (n > ARRAY_SIZE(devpriv->ai_fifo_buffer)) {
dev_err(dev->class_dev,
"bug! ai_fifo_buffer too small\n");
async->events |= COMEDI_CB_ERROR;
@@ -1242,9 +1241,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
NISTC_AI_STATUS1_FIFO_E;
while (fifo_empty == 0) {
for (i = 0;
- i <
- sizeof(devpriv->ai_fifo_buffer) /
- sizeof(devpriv->ai_fifo_buffer[0]); i++) {
+ i < ARRAY_SIZE(devpriv->ai_fifo_buffer); i++) {
fifo_empty = ni_stc_readw(dev,
NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_E;
@@ -1500,7 +1497,8 @@ static void handle_b_interrupt(struct comedi_device *dev,
s->async->events |= COMEDI_CB_OVERFLOW;
}
- if (b_status & NISTC_AO_STATUS1_BC_TC)
+ if (s->async->cmd.stop_src != TRIG_NONE &&
+ b_status & NISTC_AO_STATUS1_BC_TC)
s->async->events |= COMEDI_CB_EOA;
#ifndef PCIDMA
@@ -2054,13 +2052,13 @@ static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec,
switch (flags & CMDF_ROUND_MASK) {
case CMDF_ROUND_NEAREST:
default:
- divider = (nanosec + devpriv->clock_ns / 2) / devpriv->clock_ns;
+ divider = DIV_ROUND_CLOSEST(nanosec, devpriv->clock_ns);
break;
case CMDF_ROUND_DOWN:
divider = (nanosec) / devpriv->clock_ns;
break;
case CMDF_ROUND_UP:
- divider = (nanosec + devpriv->clock_ns - 1) / devpriv->clock_ns;
+ divider = DIV_ROUND_UP(nanosec, devpriv->clock_ns);
break;
}
return divider - 1;
@@ -2073,6 +2071,37 @@ static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer)
return devpriv->clock_ns * (timer + 1);
}
+static void ni_cmd_set_mite_transfer(struct mite_dma_descriptor_ring *ring,
+ struct comedi_subdevice *sdev,
+ const struct comedi_cmd *cmd,
+ unsigned int max_count) {
+#ifdef PCIDMA
+ unsigned int nbytes = max_count;
+
+ if (cmd->stop_arg > 0 && cmd->stop_arg < max_count)
+ nbytes = cmd->stop_arg;
+ nbytes *= comedi_bytes_per_scan(sdev);
+
+ if (nbytes > sdev->async->prealloc_bufsz) {
+ if (cmd->stop_arg > 0)
+ dev_err(sdev->device->class_dev,
+ "ni_cmd_set_mite_transfer: tried exact data transfer limits greater than buffer size\n");
+
+ /*
+ * we can only transfer up to the size of the buffer. In this
+ * case, the user is expected to continue to write into the
+ * comedi buffer (already implemented as a ring buffer).
+ */
+ nbytes = sdev->async->prealloc_bufsz;
+ }
+
+ mite_init_ring_descriptors(ring, sdev, nbytes);
+#else
+ dev_err(sdev->device->class_dev,
+ "ni_cmd_set_mite_transfer: exact data transfer limits not implemented yet without DMA\n");
+#endif
+}
+
static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev,
unsigned num_channels)
{
@@ -2428,7 +2457,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
break;
case TRIG_EXT:
- mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg);
+ mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 +
+ CR_CHAN(cmd->convert_arg));
if ((cmd->convert_arg & CR_INVERT) == 0)
mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY;
ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG);
@@ -2902,8 +2932,6 @@ static int ni_ao_inttrig(struct comedi_device *dev,
ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM |
NISTC_AO_CMD1_UC_ARM |
NISTC_AO_CMD1_BC_ARM |
- NISTC_AO_CMD1_DAC1_UPDATE_MODE |
- NISTC_AO_CMD1_DAC0_UPDATE_MODE |
devpriv->ao_cmd1,
NISTC_AO_CMD1_REG);
@@ -2913,42 +2941,68 @@ static int ni_ao_inttrig(struct comedi_device *dev,
return 0;
}
-static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+/*
+ * begin ni_ao_cmd.
+ * Organized similar to NI-STC and MHDDK examples.
+ * ni_ao_cmd is broken out into configuration sub-routines for clarity.
+ */
+
+static void ni_ao_cmd_personalize(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
{
const struct ni_board_struct *board = dev->board_ptr;
- struct ni_private *devpriv = dev->private;
- const struct comedi_cmd *cmd = &s->async->cmd;
- int bits;
- int i;
- unsigned trigvar;
- unsigned val;
-
- if (dev->irq == 0) {
- dev_err(dev->class_dev, "cannot run command without an irq\n");
- return -EIO;
- }
+ unsigned bits;
ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
+ bits =
+ /* fast CPU interface--only eseries */
+ /* ((slow CPU interface) ? 0 : AO_Fast_CPU) | */
+ NISTC_AO_PERSONAL_BC_SRC_SEL |
+ 0 /* (use_original_pulse ? 0 : NISTC_AO_PERSONAL_UPDATE_TIMEBASE) */ |
+ /*
+ * FIXME: start setting following bit when appropriate. Need to
+ * determine whether board is E4 or E1.
+ * FROM MHHDK:
+ * if board is E4 or E1
+ * Set bit "NISTC_AO_PERSONAL_UPDATE_PW" to 0
+ * else
+ * set it to 1
+ */
+ NISTC_AO_PERSONAL_UPDATE_PW |
+ /* FIXME: when should we set following bit to zero? */
+ NISTC_AO_PERSONAL_TMRDACWR_PW |
+ (board->ao_fifo_depth ?
+ NISTC_AO_PERSONAL_FIFO_ENA : NISTC_AO_PERSONAL_DMA_PIO_CTRL)
+ ;
+#if 0
+ /*
+ * FIXME:
+ * add something like ".has_individual_dacs = 0" to ni_board_struct
+ * since, as F Hess pointed out, not all in m series have singles. not
+ * sure if e-series all have duals...
+ */
- if (devpriv->is_6xxx) {
- ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
- NI611X_AO_MISC_REG);
+ /*
+ * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit for
+ * 6281, verified with bus analyzer.
+ */
+ if (devpriv->is_m_series)
+ bits |= NISTC_AO_PERSONAL_NUM_DAC;
+#endif
+ ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG);
- bits = 0;
- for (i = 0; i < cmd->chanlist_len; i++) {
- int chan;
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
- chan = CR_CHAN(cmd->chanlist[i]);
- bits |= 1 << chan;
- ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG);
- }
- ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG);
- }
+static void ni_ao_cmd_set_trigger(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
- ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ /* sync */
if (cmd->stop_src == TRIG_NONE) {
devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS;
devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE;
@@ -2958,177 +3012,351 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
- val = devpriv->ao_trigger_select;
- switch (cmd->start_src) {
- case TRIG_INT:
- case TRIG_NOW:
- val &= ~(NISTC_AO_TRIG_START1_POLARITY |
- NISTC_AO_TRIG_START1_SEL_MASK);
- val |= NISTC_AO_TRIG_START1_EDGE |
- NISTC_AO_TRIG_START1_SYNC;
- break;
- case TRIG_EXT:
- val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1);
- if (cmd->start_arg & CR_INVERT) {
- /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */
- val |= NISTC_AO_TRIG_START1_POLARITY;
- }
- if (cmd->start_arg & CR_EDGE) {
- /* 0=edge detection disabled, 1=enabled */
- val |= NISTC_AO_TRIG_START1_EDGE;
+ {
+ unsigned int trigsel = devpriv->ao_trigger_select;
+
+ switch (cmd->start_src) {
+ case TRIG_INT:
+ case TRIG_NOW:
+ trigsel &= ~(NISTC_AO_TRIG_START1_POLARITY |
+ NISTC_AO_TRIG_START1_SEL_MASK);
+ trigsel |= NISTC_AO_TRIG_START1_EDGE |
+ NISTC_AO_TRIG_START1_SYNC;
+ break;
+ case TRIG_EXT:
+ trigsel = NISTC_AO_TRIG_START1_SEL(
+ CR_CHAN(cmd->start_arg) + 1);
+ if (cmd->start_arg & CR_INVERT)
+ /*
+ * 0=active high, 1=active low.
+ * see daq-stc 3-24 (p186)
+ */
+ trigsel |= NISTC_AO_TRIG_START1_POLARITY;
+ if (cmd->start_arg & CR_EDGE)
+ /* 0=edge detection disabled, 1=enabled */
+ trigsel |= NISTC_AO_TRIG_START1_EDGE;
+ break;
+ default:
+ BUG();
+ break;
}
+
+ devpriv->ao_trigger_select = trigsel;
ni_stc_writew(dev, devpriv->ao_trigger_select,
NISTC_AO_TRIG_SEL_REG);
- break;
- default:
- BUG();
- break;
}
- devpriv->ao_trigger_select = val;
- ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG);
+ /* AO_Delayed_START1 = 0, we do not support delayed start...yet */
+ /* sync */
+ /* select DA_START1 as PFI6/AO_START1 when configured as an output */
devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN;
ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_counters(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
+ /* Not supporting 'waveform staging' or 'local buffer with pauses' */
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ /*
+ * This relies on ao_mode1/(Trigger_Once | Continuous) being set in
+ * set_trigger above. It is unclear whether we really need to re-write
+ * this register with these values. The mhddk examples for e-series
+ * show writing this in both places, but the examples for m-series show
+ * a single write in the set_counters function (here).
+ */
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+
+ /* sync (upload number of buffer iterations -1) */
+ /* indicate that we want to use BC_Load_A_Register as the source */
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC;
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
- if (cmd->stop_src == TRIG_NONE)
- ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG);
- else
- ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG);
+
+ /*
+ * if the BC_TC interrupt is still issued in spite of UC, BC, UI
+ * ignoring BC_TC, then we will need to find a way to ignore that
+ * interrupt in continuous mode.
+ */
+ ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); /* iter once */
+
+ /* sync (issue command to load number of buffer iterations -1) */
ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG);
+
+ /* sync (upload number of updates in buffer) */
+ /* indicate that we want to use UC_Load_A_Register as the source */
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC;
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
- switch (cmd->stop_src) {
- case TRIG_COUNT:
+
+ /*
+ * if a user specifies '0', this automatically assumes the entire 24bit
+ * address space is available for the (multiple iterations of single
+ * buffer) MISB. Otherwise, stop_arg specifies the MISB length that
+ * will be used, regardless of whether we are in continuous mode or not.
+ * In continuous mode, the output will just iterate indefinitely over
+ * the MISB.
+ */
+ {
+ unsigned int stop_arg = cmd->stop_arg > 0 ?
+ (cmd->stop_arg & 0xffffff) : 0xffffff;
+
if (devpriv->is_m_series) {
- /* this is how the NI example code does it for m-series boards, verified correct with 6259 */
- ni_stc_writel(dev, cmd->stop_arg - 1,
- NISTC_AO_UC_LOADA_REG);
+ /*
+ * this is how the NI example code does it for m-series
+ * boards, verified correct with 6259
+ */
+ ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG);
+
+ /* sync (issue cmd to load number of updates in MISB) */
ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
NISTC_AO_CMD1_REG);
} else {
- ni_stc_writel(dev, cmd->stop_arg,
- NISTC_AO_UC_LOADA_REG);
+ ni_stc_writel(dev, stop_arg, NISTC_AO_UC_LOADA_REG);
+
+ /* sync (issue cmd to load number of updates in MISB) */
ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, cmd->stop_arg - 1,
- NISTC_AO_UC_LOADA_REG);
+
+ /*
+ * sync (upload number of updates-1 in MISB)
+ * --eseries only?
+ */
+ ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG);
}
- break;
- case TRIG_NONE:
- ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
- break;
- default:
- ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG);
}
- devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK |
- NISTC_AO_MODE1_UI_SRC_MASK |
- NISTC_AO_MODE1_UPDATE_SRC_POLARITY |
- NISTC_AO_MODE1_UI_SRC_POLARITY);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_update(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
+ /*
+ * zero out these bit fields to be set below. Does an ao-reset do this
+ * automatically?
+ */
+ devpriv->ao_mode1 &= ~(
+ NISTC_AO_MODE1_UI_SRC_MASK |
+ NISTC_AO_MODE1_UI_SRC_POLARITY |
+ NISTC_AO_MODE1_UPDATE_SRC_MASK |
+ NISTC_AO_MODE1_UPDATE_SRC_POLARITY
+ );
+
switch (cmd->scan_begin_src) {
case TRIG_TIMER:
- devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA;
- trigvar =
- ni_ns_to_timer(dev, cmd->scan_begin_arg,
- CMDF_ROUND_NEAREST);
- ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG);
+ devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA;
+
+ /*
+ * NOTE: there are several other ways of configuring internal
+ * updates, but we'll only support one for now: using
+ * AO_IN_TIMEBASE, w/o waveform staging, w/o a delay between
+ * START1 and first update, and also w/o local buffer mode w/
+ * pauses.
+ */
+
+ /*
+ * This is already done above:
+ * devpriv->ao_mode1 &= ~(
+ * // set UPDATE_Source to UI_TC:
+ * NISTC_AO_MODE1_UPDATE_SRC_MASK |
+ * // set UPDATE_Source_Polarity to rising (required?)
+ * NISTC_AO_MODE1_UPDATE_SRC_POLARITY |
+ * // set UI_Source to AO_IN_TIMEBASE1:
+ * NISTC_AO_MODE1_UI_SRC_MASK |
+ * // set UI_Source_Polarity to rising (required?)
+ * NISTC_AO_MODE1_UI_SRC_POLARITY
+ * );
+ */
+
+ /*
+ * TODO: use ao_ui_clock_source to allow all possible signals
+ * to be routed to UI_Source_Select. See tSTC.h for
+ * eseries/ni67xx and tMSeries.h for mseries.
+ */
+
+ {
+ unsigned trigvar = ni_ns_to_timer(dev,
+ cmd->scan_begin_arg,
+ CMDF_ROUND_NEAREST);
+
+ /*
+ * Wait N TB3 ticks after the start trigger before
+ * clocking(N must be >=2).
+ */
+ /* following line: 2-1 per STC */
+ ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD,
+ NISTC_AO_CMD1_REG);
+ /* following line: N-1 per STC */
+ ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG);
+ }
break;
case TRIG_EXT:
- devpriv->ao_mode1 |=
- NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg);
+ /* FIXME: assert scan_begin_arg != 0, ret failure otherwise */
+ devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA;
+ devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC(
+ CR_CHAN(cmd->scan_begin_arg));
if (cmd->scan_begin_arg & CR_INVERT)
devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY;
- devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA;
break;
default:
BUG();
break;
}
+
ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) |
NISTC_AO_MODE2_UI_INIT_LOAD_SRC);
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+ /* Configure DAQ-STC for Timed update mode */
+ devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE |
+ NISTC_AO_CMD1_DAC0_UPDATE_MODE;
+ /* We are not using UPDATE2-->don't have to set DACx_Source_Select */
+ ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_channels(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct ni_private *devpriv = dev->private;
+ const struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned bits = 0;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
+ if (devpriv->is_6xxx) {
+ unsigned int i;
+
+ bits = 0;
+ for (i = 0; i < cmd->chanlist_len; ++i) {
+ int chan = CR_CHAN(cmd->chanlist[i]);
+
+ bits |= 1 << chan;
+ ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG);
+ }
+ ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG);
+ }
+
+ ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
+
if (cmd->scan_end_arg > 1) {
devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN;
- ni_stc_writew(dev,
- NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) |
- NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ,
- NISTC_AO_OUT_CTRL_REG);
- } else {
- unsigned bits;
+ bits = NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1)
+ | NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ;
+ } else {
devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN;
bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ;
- if (devpriv->is_m_series || devpriv->is_6xxx) {
+ if (devpriv->is_m_series | devpriv->is_6xxx)
bits |= NISTC_AO_OUT_CTRL_CHANS(0);
- } else {
- bits |=
- NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0]));
- }
- ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG);
+ else
+ bits |= NISTC_AO_OUT_CTRL_CHANS(
+ CR_CHAN(cmd->chanlist[0]));
}
+
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE |
- NISTC_AO_CMD1_DAC0_UPDATE_MODE,
- NISTC_AO_CMD1_REG);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_stop_conditions(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR;
ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ /*
+ * Since we are not supporting waveform staging, we ignore these errors:
+ * NISTC_AO_MODE3_STOP_ON_BC_TC_ERR,
+ * NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR
+ */
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_fifo_mode(struct comedi_device *dev)
+{
+ struct ni_private *devpriv = dev->private;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK;
#ifdef PCIDMA
devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F;
#else
devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF;
#endif
+ /* NOTE: this is where use_onboard_memory=True would be implemented */
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA;
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
- bits = NISTC_AO_PERSONAL_BC_SRC_SEL |
- NISTC_AO_PERSONAL_UPDATE_PW |
- NISTC_AO_PERSONAL_TMRDACWR_PW;
- if (board->ao_fifo_depth)
- bits |= NISTC_AO_PERSONAL_FIFO_ENA;
- else
- bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL;
-#if 0
- /*
- * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit
- * for 6281, verified with bus analyzer.
- */
- if (devpriv->is_m_series)
- bits |= NISTC_AO_PERSONAL_NUM_DAC;
-#endif
- ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG);
- /* enable sending of ao dma requests */
+ /* enable sending of ao fifo requests (dma request) */
ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG);
ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
- if (cmd->stop_src == TRIG_COUNT) {
- ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC,
- NISTC_INTB_ACK_REG);
+ /* we are not supporting boards with virtual fifos */
+}
+
+static void ni_ao_cmd_set_interrupts(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ if (s->async->cmd.stop_src == TRIG_COUNT)
ni_set_bits(dev, NISTC_INTB_ENA_REG,
NISTC_INTB_ENA_AO_BC_TC, 1);
- }
s->async->inttrig = ni_ao_inttrig;
+}
+
+static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+ struct ni_private *devpriv = dev->private;
+ const struct comedi_cmd *cmd = &s->async->cmd;
+
+ if (dev->irq == 0) {
+ dev_err(dev->class_dev, "cannot run command without an irq");
+ return -EIO;
+ }
+
+ /* ni_ao_reset should have already been done */
+ ni_ao_cmd_personalize(dev, cmd);
+ /* clearing fifo and preload happens elsewhere */
+ ni_ao_cmd_set_trigger(dev, cmd);
+ ni_ao_cmd_set_counters(dev, cmd);
+ ni_ao_cmd_set_update(dev, cmd);
+ ni_ao_cmd_set_channels(dev, s);
+ ni_ao_cmd_set_stop_conditions(dev, cmd);
+ ni_ao_cmd_set_fifo_mode(dev);
+ ni_cmd_set_mite_transfer(devpriv->ao_mite_ring, s, cmd, 0x00ffffff);
+ ni_ao_cmd_set_interrupts(dev, s);
+
+ /*
+ * arm(ing) and star(ting) happen in ni_ao_inttrig, which _must_ be
+ * called for ao commands since 1) TRIG_NOW is not supported and 2) DMA
+ * must be setup and initially written to before arm/start happen.
+ */
return 0;
}
+/* end ni_ao_cmd */
+
static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
@@ -3187,11 +3415,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
cmd->chanlist_len);
-
- if (cmd->stop_src == TRIG_COUNT)
- err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
- else /* TRIG_NONE */
- err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
+ err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
if (err)
return 3;
@@ -3214,48 +3438,70 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ /* See 3.6.1.2 "Resetting", of DAQ-STC Technical Reference Manual */
+
+ /*
+ * In the following, the "--sync" comments are meant to denote
+ * asynchronous boundaries for setting the registers as described in the
+ * DAQ-STC mostly in the order also described in the DAQ-STC.
+ */
+
struct ni_private *devpriv = dev->private;
ni_release_ao_mite_channel(dev);
+ /* --sync (reset AO) */
+ if (devpriv->is_m_series)
+ /* following example in mhddk for m-series */
+ ni_stc_writew(dev, NISTC_RESET_AO, NISTC_RESET_REG);
+
+ /*--sync (start config) */
ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
+ /*--sync (Disarm) */
ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
- ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0);
- ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG);
- ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG);
- ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL |
- NISTC_AO_PERSONAL_UPDATE_PW |
- NISTC_AO_PERSONAL_TMRDACWR_PW,
- NISTC_AO_PERSONAL_REG);
- ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG);
- ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG);
- devpriv->ao_cmd1 = 0;
- ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
- devpriv->ao_cmd2 = 0;
- ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
+
+ /*
+ * --sync
+ * (clear bunch of registers--mseries mhddk examples do not include
+ * this)
+ */
+ devpriv->ao_cmd1 = 0;
+ devpriv->ao_cmd2 = 0;
devpriv->ao_mode1 = 0;
- ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
devpriv->ao_mode2 = 0;
- ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
if (devpriv->is_m_series)
devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE;
else
devpriv->ao_mode3 = 0;
- ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
devpriv->ao_trigger_select = 0;
- ni_stc_writew(dev, devpriv->ao_trigger_select,
- NISTC_AO_TRIG_SEL_REG);
- if (devpriv->is_6xxx) {
- unsigned immediate_bits = 0;
- unsigned i;
- for (i = 0; i < s->n_chan; ++i)
- immediate_bits |= 1 << i;
- ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_PERSONAL_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_CMD1_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_CMD2_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_MODE1_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_MODE2_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG);
+ ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_TRIG_SEL_REG);
+
+ /*--sync (disable interrupts) */
+ ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0);
+
+ /*--sync (ack) */
+ ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG);
+ ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG);
+
+ /*--not in DAQ-STC. which doc? */
+ if (devpriv->is_6xxx) {
+ ni_ao_win_outw(dev, (1u << s->n_chan) - 1u,
+ NI671X_AO_IMMEDIATE_REG);
ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
NI611X_AO_MISC_REG);
}
ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+ /*--end */
return 0;
}
@@ -3381,7 +3627,9 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
cmd->chanlist_len);
- err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
+ err |= comedi_check_trigger_arg_max(&cmd->stop_arg,
+ s->async->prealloc_bufsz /
+ comedi_bytes_per_scan(s));
if (err)
return 3;
@@ -3458,6 +3706,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev,
static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct ni_private *devpriv = dev->private;
const struct comedi_cmd *cmd = &s->async->cmd;
unsigned cdo_mode_bits;
int retval;
@@ -3482,6 +3731,10 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (retval < 0)
return retval;
+ ni_cmd_set_mite_transfer(devpriv->cdo_mite_ring, s, cmd,
+ s->async->prealloc_bufsz /
+ comedi_bytes_per_scan(s));
+
s->async->inttrig = ni_cdo_inttrig;
return 0;
@@ -3980,34 +4233,30 @@ static int ni_m_series_pwm_config(struct comedi_device *dev,
case INSN_CONFIG_PWM_OUTPUT:
switch (data[1]) {
case CMDF_ROUND_NEAREST:
- up_count =
- (data[2] +
- devpriv->clock_ns / 2) / devpriv->clock_ns;
+ up_count = DIV_ROUND_CLOSEST(data[2],
+ devpriv->clock_ns);
break;
case CMDF_ROUND_DOWN:
up_count = data[2] / devpriv->clock_ns;
break;
case CMDF_ROUND_UP:
up_count =
- (data[2] + devpriv->clock_ns -
- 1) / devpriv->clock_ns;
+ DIV_ROUND_UP(data[2], devpriv->clock_ns);
break;
default:
return -EINVAL;
}
switch (data[3]) {
case CMDF_ROUND_NEAREST:
- down_count =
- (data[4] +
- devpriv->clock_ns / 2) / devpriv->clock_ns;
+ down_count = DIV_ROUND_CLOSEST(data[4],
+ devpriv->clock_ns);
break;
case CMDF_ROUND_DOWN:
down_count = data[4] / devpriv->clock_ns;
break;
case CMDF_ROUND_UP:
down_count =
- (data[4] + devpriv->clock_ns -
- 1) / devpriv->clock_ns;
+ DIV_ROUND_UP(data[4], devpriv->clock_ns);
break;
default:
return -EINVAL;
@@ -4044,34 +4293,30 @@ static int ni_6143_pwm_config(struct comedi_device *dev,
case INSN_CONFIG_PWM_OUTPUT:
switch (data[1]) {
case CMDF_ROUND_NEAREST:
- up_count =
- (data[2] +
- devpriv->clock_ns / 2) / devpriv->clock_ns;
+ up_count = DIV_ROUND_CLOSEST(data[2],
+ devpriv->clock_ns);
break;
case CMDF_ROUND_DOWN:
up_count = data[2] / devpriv->clock_ns;
break;
case CMDF_ROUND_UP:
up_count =
- (data[2] + devpriv->clock_ns -
- 1) / devpriv->clock_ns;
+ DIV_ROUND_UP(data[2], devpriv->clock_ns);
break;
default:
return -EINVAL;
}
switch (data[3]) {
case CMDF_ROUND_NEAREST:
- down_count =
- (data[4] +
- devpriv->clock_ns / 2) / devpriv->clock_ns;
+ down_count = DIV_ROUND_CLOSEST(data[4],
+ devpriv->clock_ns);
break;
case CMDF_ROUND_DOWN:
down_count = data[4] / devpriv->clock_ns;
break;
case CMDF_ROUND_UP:
down_count =
- (data[4] + devpriv->clock_ns -
- 1) / devpriv->clock_ns;
+ DIV_ROUND_UP(data[4], devpriv->clock_ns);
break;
default:
return -EINVAL;
@@ -4665,9 +4910,9 @@ static int ni_mseries_get_pll_parameters(unsigned reference_period_ns,
*freq_divider = best_div;
*freq_multiplier = best_mult;
- *actual_period_ns =
- (best_period_picosec * fudge_factor_80_to_20Mhz +
- (pico_per_nano / 2)) / pico_per_nano;
+ *actual_period_ns = DIV_ROUND_CLOSEST(best_period_picosec *
+ fudge_factor_80_to_20Mhz,
+ pico_per_nano);
return 0;
}
@@ -5024,7 +5269,6 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
unsigned long flags;
#ifdef PCIDMA
struct ni_private *devpriv = dev->private;
- struct mite_struct *mite = devpriv->mite;
#endif
if (!dev->attached)
@@ -5036,8 +5280,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG);
b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG);
#ifdef PCIDMA
- if (mite) {
- struct ni_private *devpriv = dev->private;
+ if (devpriv->mite) {
unsigned long flags_too;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too);
@@ -5053,7 +5296,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
ao_mite_status = mite_get_status(devpriv->ao_mite_chan);
if (ao_mite_status & CHSR_LINKC)
writel(CHOR_CLRLC,
- mite->mite_io_addr +
+ devpriv->mite->mite_io_addr +
MITE_CHOR(devpriv->
ao_mite_chan->channel));
}
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index ac79099bc23e..7112c3fec8bb 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -525,13 +525,13 @@ static int ni_pcidio_ns_to_timer(int *nanosec, unsigned int flags)
switch (flags & CMDF_ROUND_MASK) {
case CMDF_ROUND_NEAREST:
default:
- divider = (*nanosec + base / 2) / base;
+ divider = DIV_ROUND_CLOSEST(*nanosec, base);
break;
case CMDF_ROUND_DOWN:
divider = (*nanosec) / base;
break;
case CMDF_ROUND_UP:
- divider = (*nanosec + base - 1) / base;
+ divider = DIV_ROUND_UP(*nanosec, base);
break;
}
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index 30a5a75d1fe7..231e37d6b7c6 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -26,7 +26,8 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio),
PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E,
PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E,
PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224,
- PCI-6225, PXI-6225, PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PXIe-6251,
+ PCI-6225, PXI-6225, PCI-6229, PCI-6250,
+ PCI-6251, PXI-6251, PCIe-6251, PXIe-6251,
PCI-6254, PCI-6259, PCIe-6259,
PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289,
PCI-6711, PXI-6711, PCI-6713, PXI-6713,
@@ -193,6 +194,7 @@ enum ni_pcimio_boardid {
BOARD_PCI6229,
BOARD_PCI6250,
BOARD_PCI6251,
+ BOARD_PXI6251,
BOARD_PCIE6251,
BOARD_PXIE6251,
BOARD_PCI6254,
@@ -811,6 +813,21 @@ static const struct ni_board_struct ni_boards[] = {
.ao_speed = 350,
.caldac = { caldac_none },
},
+ [BOARD_PXI6251] = {
+ .name = "pxi-6251",
+ .n_adchan = 16,
+ .ai_maxdata = 0xffff,
+ .ai_fifo_depth = 4095,
+ .gainlkup = ai_gain_628x,
+ .ai_speed = 800,
+ .n_aochan = 2,
+ .ao_maxdata = 0xffff,
+ .ao_fifo_depth = 8191,
+ .ao_range_table = &range_ni_M_625x_ao,
+ .reg_type = ni_reg_625x,
+ .ao_speed = 350,
+ .caldac = { caldac_none },
+ },
[BOARD_PCIE6251] = {
.name = "pcie-6251",
.n_adchan = 16,
@@ -1290,6 +1307,7 @@ static const struct pci_device_id ni_pcimio_pci_table[] = {
{ PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN },
{ PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 },
{ PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 },
+ { PCI_VDEVICE(NI, 0x70ad), BOARD_PXI6251 },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table);
diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
index 437f723bb34d..823e47910004 100644
--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
+++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
@@ -92,7 +92,7 @@ static int ni_tio_input_inttrig(struct comedi_device *dev,
unsigned long flags;
int ret = 0;
- if (trig_num != cmd->start_src)
+ if (trig_num != cmd->start_arg)
return -EINVAL;
spin_lock_irqsave(&counter->lock, flags);
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 68ac02b68cb2..9b6c56773247 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -892,9 +892,8 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->xfer_count = cmd->chanlist_len;
} else { /* make a multiple of scan length */
devpriv->xfer_count =
- (devpriv->xfer_count +
- cmd->chanlist_len - 1)
- / cmd->chanlist_len;
+ DIV_ROUND_UP(devpriv->xfer_count,
+ cmd->chanlist_len);
devpriv->xfer_count *= cmd->chanlist_len;
}
devpriv->flags |= SEND_EOS;
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 35f0f676eb28..c5e08635e01e 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -1167,12 +1167,6 @@ static void s626_set_clk_mult(struct comedi_device *dev,
s626_set_mode(dev, chan, mode, false);
}
-static uint16_t s626_get_clk_mult(struct comedi_device *dev,
- unsigned int chan)
-{
- return S626_GET_STD_CLKMULT(s626_get_mode(dev, chan));
-}
-
/*
* Return/set the clock polarity.
*/
@@ -1188,12 +1182,6 @@ static void s626_set_clk_pol(struct comedi_device *dev,
s626_set_mode(dev, chan, mode, false);
}
-static uint16_t s626_get_clk_pol(struct comedi_device *dev,
- unsigned int chan)
-{
- return S626_GET_STD_CLKPOL(s626_get_mode(dev, chan));
-}
-
/*
* Return/set the encoder mode.
*/
@@ -1209,27 +1197,6 @@ static void s626_set_enc_mode(struct comedi_device *dev,
s626_set_mode(dev, chan, mode, false);
}
-static uint16_t s626_get_enc_mode(struct comedi_device *dev,
- unsigned int chan)
-{
- return S626_GET_STD_ENCMODE(s626_get_mode(dev, chan));
-}
-
-/*
- * Return/set the index polarity.
- */
-static void s626_set_index_pol(struct comedi_device *dev,
- unsigned int chan, uint16_t value)
-{
- uint16_t mode;
-
- mode = s626_get_mode(dev, chan);
- mode &= ~S626_STDMSK_INDXPOL;
- mode |= S626_SET_STD_INDXPOL(value != 0);
-
- s626_set_mode(dev, chan, mode, false);
-}
-
static uint16_t s626_get_index_pol(struct comedi_device *dev,
unsigned int chan)
{