Commit 3b6b25b5ddf4485e89432a35a7d79d371ba6eba1
1 parent
2434358ac7
Exists in
master
and in
7 other branches
Staging: comedi: range.c: properly mark up __user pointers
This is the start of cleaning up the user pointer markings in the comedi core. Cc: Ian Abbott <abbotti@mev.co.uk> Cc: Frank Mori Hess <fmhess@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Showing 5 changed files with 10 additions and 8 deletions Inline Diff
drivers/staging/comedi/comedi.h
1 | /* | 1 | /* |
2 | include/comedi.h (installed as /usr/include/comedi.h) | 2 | include/comedi.h (installed as /usr/include/comedi.h) |
3 | header file for comedi | 3 | header file for comedi |
4 | 4 | ||
5 | COMEDI - Linux Control and Measurement Device Interface | 5 | COMEDI - Linux Control and Measurement Device Interface |
6 | Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> | 6 | Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org> |
7 | 7 | ||
8 | This program is free software; you can redistribute it and/or modify | 8 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU Lesser General Public License as published by | 9 | it under the terms of the GNU Lesser General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or | 10 | the Free Software Foundation; either version 2 of the License, or |
11 | (at your option) any later version. | 11 | (at your option) any later version. |
12 | 12 | ||
13 | This program is distributed in the hope that it will be useful, | 13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. | 16 | GNU General Public License for more details. |
17 | 17 | ||
18 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software | 19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | 21 | ||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #ifndef _COMEDI_H | 24 | #ifndef _COMEDI_H |
25 | #define _COMEDI_H | 25 | #define _COMEDI_H |
26 | 26 | ||
27 | #define COMEDI_MAJORVERSION 0 | 27 | #define COMEDI_MAJORVERSION 0 |
28 | #define COMEDI_MINORVERSION 7 | 28 | #define COMEDI_MINORVERSION 7 |
29 | #define COMEDI_MICROVERSION 76 | 29 | #define COMEDI_MICROVERSION 76 |
30 | #define VERSION "0.7.76" | 30 | #define VERSION "0.7.76" |
31 | 31 | ||
32 | /* comedi's major device number */ | 32 | /* comedi's major device number */ |
33 | #define COMEDI_MAJOR 98 | 33 | #define COMEDI_MAJOR 98 |
34 | 34 | ||
35 | /* | 35 | /* |
36 | maximum number of minor devices. This can be increased, although | 36 | maximum number of minor devices. This can be increased, although |
37 | kernel structures are currently statically allocated, thus you | 37 | kernel structures are currently statically allocated, thus you |
38 | don't want this to be much more than you actually use. | 38 | don't want this to be much more than you actually use. |
39 | */ | 39 | */ |
40 | #define COMEDI_NDEVICES 16 | 40 | #define COMEDI_NDEVICES 16 |
41 | 41 | ||
42 | /* number of config options in the config structure */ | 42 | /* number of config options in the config structure */ |
43 | #define COMEDI_NDEVCONFOPTS 32 | 43 | #define COMEDI_NDEVCONFOPTS 32 |
44 | /*length of nth chunk of firmware data*/ | 44 | /*length of nth chunk of firmware data*/ |
45 | #define COMEDI_DEVCONF_AUX_DATA3_LENGTH 25 | 45 | #define COMEDI_DEVCONF_AUX_DATA3_LENGTH 25 |
46 | #define COMEDI_DEVCONF_AUX_DATA2_LENGTH 26 | 46 | #define COMEDI_DEVCONF_AUX_DATA2_LENGTH 26 |
47 | #define COMEDI_DEVCONF_AUX_DATA1_LENGTH 27 | 47 | #define COMEDI_DEVCONF_AUX_DATA1_LENGTH 27 |
48 | #define COMEDI_DEVCONF_AUX_DATA0_LENGTH 28 | 48 | #define COMEDI_DEVCONF_AUX_DATA0_LENGTH 28 |
49 | #define COMEDI_DEVCONF_AUX_DATA_HI 29 /* most significant 32 bits of pointer address (if needed) */ | 49 | #define COMEDI_DEVCONF_AUX_DATA_HI 29 /* most significant 32 bits of pointer address (if needed) */ |
50 | #define COMEDI_DEVCONF_AUX_DATA_LO 30 /* least significant 32 bits of pointer address */ | 50 | #define COMEDI_DEVCONF_AUX_DATA_LO 30 /* least significant 32 bits of pointer address */ |
51 | #define COMEDI_DEVCONF_AUX_DATA_LENGTH 31 /* total data length */ | 51 | #define COMEDI_DEVCONF_AUX_DATA_LENGTH 31 /* total data length */ |
52 | 52 | ||
53 | /* max length of device and driver names */ | 53 | /* max length of device and driver names */ |
54 | #define COMEDI_NAMELEN 20 | 54 | #define COMEDI_NAMELEN 20 |
55 | 55 | ||
56 | /* packs and unpacks a channel/range number */ | 56 | /* packs and unpacks a channel/range number */ |
57 | 57 | ||
58 | #define CR_PACK(chan, rng, aref) ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan)) | 58 | #define CR_PACK(chan, rng, aref) ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan)) |
59 | #define CR_PACK_FLAGS(chan, range, aref, flags) (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK)) | 59 | #define CR_PACK_FLAGS(chan, range, aref, flags) (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK)) |
60 | 60 | ||
61 | #define CR_CHAN(a) ((a)&0xffff) | 61 | #define CR_CHAN(a) ((a)&0xffff) |
62 | #define CR_RANGE(a) (((a)>>16)&0xff) | 62 | #define CR_RANGE(a) (((a)>>16)&0xff) |
63 | #define CR_AREF(a) (((a)>>24)&0x03) | 63 | #define CR_AREF(a) (((a)>>24)&0x03) |
64 | 64 | ||
65 | #define CR_FLAGS_MASK 0xfc000000 | 65 | #define CR_FLAGS_MASK 0xfc000000 |
66 | #define CR_ALT_FILTER (1<<26) | 66 | #define CR_ALT_FILTER (1<<26) |
67 | #define CR_DITHER CR_ALT_FILTER | 67 | #define CR_DITHER CR_ALT_FILTER |
68 | #define CR_DEGLITCH CR_ALT_FILTER | 68 | #define CR_DEGLITCH CR_ALT_FILTER |
69 | #define CR_ALT_SOURCE (1<<27) | 69 | #define CR_ALT_SOURCE (1<<27) |
70 | #define CR_EDGE (1<<30) | 70 | #define CR_EDGE (1<<30) |
71 | #define CR_INVERT (1<<31) | 71 | #define CR_INVERT (1<<31) |
72 | 72 | ||
73 | #define AREF_GROUND 0x00 /* analog ref = analog ground */ | 73 | #define AREF_GROUND 0x00 /* analog ref = analog ground */ |
74 | #define AREF_COMMON 0x01 /* analog ref = analog common */ | 74 | #define AREF_COMMON 0x01 /* analog ref = analog common */ |
75 | #define AREF_DIFF 0x02 /* analog ref = differential */ | 75 | #define AREF_DIFF 0x02 /* analog ref = differential */ |
76 | #define AREF_OTHER 0x03 /* analog ref = other (undefined) */ | 76 | #define AREF_OTHER 0x03 /* analog ref = other (undefined) */ |
77 | 77 | ||
78 | /* counters -- these are arbitrary values */ | 78 | /* counters -- these are arbitrary values */ |
79 | #define GPCT_RESET 0x0001 | 79 | #define GPCT_RESET 0x0001 |
80 | #define GPCT_SET_SOURCE 0x0002 | 80 | #define GPCT_SET_SOURCE 0x0002 |
81 | #define GPCT_SET_GATE 0x0004 | 81 | #define GPCT_SET_GATE 0x0004 |
82 | #define GPCT_SET_DIRECTION 0x0008 | 82 | #define GPCT_SET_DIRECTION 0x0008 |
83 | #define GPCT_SET_OPERATION 0x0010 | 83 | #define GPCT_SET_OPERATION 0x0010 |
84 | #define GPCT_ARM 0x0020 | 84 | #define GPCT_ARM 0x0020 |
85 | #define GPCT_DISARM 0x0040 | 85 | #define GPCT_DISARM 0x0040 |
86 | #define GPCT_GET_INT_CLK_FRQ 0x0080 | 86 | #define GPCT_GET_INT_CLK_FRQ 0x0080 |
87 | 87 | ||
88 | #define GPCT_INT_CLOCK 0x0001 | 88 | #define GPCT_INT_CLOCK 0x0001 |
89 | #define GPCT_EXT_PIN 0x0002 | 89 | #define GPCT_EXT_PIN 0x0002 |
90 | #define GPCT_NO_GATE 0x0004 | 90 | #define GPCT_NO_GATE 0x0004 |
91 | #define GPCT_UP 0x0008 | 91 | #define GPCT_UP 0x0008 |
92 | #define GPCT_DOWN 0x0010 | 92 | #define GPCT_DOWN 0x0010 |
93 | #define GPCT_HWUD 0x0020 | 93 | #define GPCT_HWUD 0x0020 |
94 | #define GPCT_SIMPLE_EVENT 0x0040 | 94 | #define GPCT_SIMPLE_EVENT 0x0040 |
95 | #define GPCT_SINGLE_PERIOD 0x0080 | 95 | #define GPCT_SINGLE_PERIOD 0x0080 |
96 | #define GPCT_SINGLE_PW 0x0100 | 96 | #define GPCT_SINGLE_PW 0x0100 |
97 | #define GPCT_CONT_PULSE_OUT 0x0200 | 97 | #define GPCT_CONT_PULSE_OUT 0x0200 |
98 | #define GPCT_SINGLE_PULSE_OUT 0x0400 | 98 | #define GPCT_SINGLE_PULSE_OUT 0x0400 |
99 | 99 | ||
100 | /* instructions */ | 100 | /* instructions */ |
101 | 101 | ||
102 | #define INSN_MASK_WRITE 0x8000000 | 102 | #define INSN_MASK_WRITE 0x8000000 |
103 | #define INSN_MASK_READ 0x4000000 | 103 | #define INSN_MASK_READ 0x4000000 |
104 | #define INSN_MASK_SPECIAL 0x2000000 | 104 | #define INSN_MASK_SPECIAL 0x2000000 |
105 | 105 | ||
106 | #define INSN_READ (0 | INSN_MASK_READ) | 106 | #define INSN_READ (0 | INSN_MASK_READ) |
107 | #define INSN_WRITE (1 | INSN_MASK_WRITE) | 107 | #define INSN_WRITE (1 | INSN_MASK_WRITE) |
108 | #define INSN_BITS (2 | INSN_MASK_READ|INSN_MASK_WRITE) | 108 | #define INSN_BITS (2 | INSN_MASK_READ|INSN_MASK_WRITE) |
109 | #define INSN_CONFIG (3 | INSN_MASK_READ|INSN_MASK_WRITE) | 109 | #define INSN_CONFIG (3 | INSN_MASK_READ|INSN_MASK_WRITE) |
110 | #define INSN_GTOD (4 | INSN_MASK_READ|INSN_MASK_SPECIAL) | 110 | #define INSN_GTOD (4 | INSN_MASK_READ|INSN_MASK_SPECIAL) |
111 | #define INSN_WAIT (5 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) | 111 | #define INSN_WAIT (5 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) |
112 | #define INSN_INTTRIG (6 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) | 112 | #define INSN_INTTRIG (6 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) |
113 | 113 | ||
114 | /* trigger flags */ | 114 | /* trigger flags */ |
115 | /* These flags are used in comedi_trig structures */ | 115 | /* These flags are used in comedi_trig structures */ |
116 | 116 | ||
117 | #define TRIG_BOGUS 0x0001 /* do the motions */ | 117 | #define TRIG_BOGUS 0x0001 /* do the motions */ |
118 | #define TRIG_DITHER 0x0002 /* enable dithering */ | 118 | #define TRIG_DITHER 0x0002 /* enable dithering */ |
119 | #define TRIG_DEGLITCH 0x0004 /* enable deglitching */ | 119 | #define TRIG_DEGLITCH 0x0004 /* enable deglitching */ |
120 | /*#define TRIG_RT 0x0008 *//* perform op in real time */ | 120 | /*#define TRIG_RT 0x0008 *//* perform op in real time */ |
121 | #define TRIG_CONFIG 0x0010 /* perform configuration, not triggering */ | 121 | #define TRIG_CONFIG 0x0010 /* perform configuration, not triggering */ |
122 | #define TRIG_WAKE_EOS 0x0020 /* wake up on end-of-scan events */ | 122 | #define TRIG_WAKE_EOS 0x0020 /* wake up on end-of-scan events */ |
123 | /*#define TRIG_WRITE 0x0040*//* write to bidirectional devices */ | 123 | /*#define TRIG_WRITE 0x0040*//* write to bidirectional devices */ |
124 | 124 | ||
125 | /* command flags */ | 125 | /* command flags */ |
126 | /* These flags are used in comedi_cmd structures */ | 126 | /* These flags are used in comedi_cmd structures */ |
127 | 127 | ||
128 | #define CMDF_PRIORITY 0x00000008 /* try to use a real-time interrupt while performing command */ | 128 | #define CMDF_PRIORITY 0x00000008 /* try to use a real-time interrupt while performing command */ |
129 | 129 | ||
130 | #define TRIG_RT CMDF_PRIORITY /* compatibility definition */ | 130 | #define TRIG_RT CMDF_PRIORITY /* compatibility definition */ |
131 | 131 | ||
132 | #define CMDF_WRITE 0x00000040 | 132 | #define CMDF_WRITE 0x00000040 |
133 | #define TRIG_WRITE CMDF_WRITE /* compatibility definition */ | 133 | #define TRIG_WRITE CMDF_WRITE /* compatibility definition */ |
134 | 134 | ||
135 | #define CMDF_RAWDATA 0x00000080 | 135 | #define CMDF_RAWDATA 0x00000080 |
136 | 136 | ||
137 | #define COMEDI_EV_START 0x00040000 | 137 | #define COMEDI_EV_START 0x00040000 |
138 | #define COMEDI_EV_SCAN_BEGIN 0x00080000 | 138 | #define COMEDI_EV_SCAN_BEGIN 0x00080000 |
139 | #define COMEDI_EV_CONVERT 0x00100000 | 139 | #define COMEDI_EV_CONVERT 0x00100000 |
140 | #define COMEDI_EV_SCAN_END 0x00200000 | 140 | #define COMEDI_EV_SCAN_END 0x00200000 |
141 | #define COMEDI_EV_STOP 0x00400000 | 141 | #define COMEDI_EV_STOP 0x00400000 |
142 | 142 | ||
143 | #define TRIG_ROUND_MASK 0x00030000 | 143 | #define TRIG_ROUND_MASK 0x00030000 |
144 | #define TRIG_ROUND_NEAREST 0x00000000 | 144 | #define TRIG_ROUND_NEAREST 0x00000000 |
145 | #define TRIG_ROUND_DOWN 0x00010000 | 145 | #define TRIG_ROUND_DOWN 0x00010000 |
146 | #define TRIG_ROUND_UP 0x00020000 | 146 | #define TRIG_ROUND_UP 0x00020000 |
147 | #define TRIG_ROUND_UP_NEXT 0x00030000 | 147 | #define TRIG_ROUND_UP_NEXT 0x00030000 |
148 | 148 | ||
149 | /* trigger sources */ | 149 | /* trigger sources */ |
150 | 150 | ||
151 | #define TRIG_ANY 0xffffffff | 151 | #define TRIG_ANY 0xffffffff |
152 | #define TRIG_INVALID 0x00000000 | 152 | #define TRIG_INVALID 0x00000000 |
153 | 153 | ||
154 | #define TRIG_NONE 0x00000001 /* never trigger */ | 154 | #define TRIG_NONE 0x00000001 /* never trigger */ |
155 | #define TRIG_NOW 0x00000002 /* trigger now + N ns */ | 155 | #define TRIG_NOW 0x00000002 /* trigger now + N ns */ |
156 | #define TRIG_FOLLOW 0x00000004 /* trigger on next lower level trig */ | 156 | #define TRIG_FOLLOW 0x00000004 /* trigger on next lower level trig */ |
157 | #define TRIG_TIME 0x00000008 /* trigger at time N ns */ | 157 | #define TRIG_TIME 0x00000008 /* trigger at time N ns */ |
158 | #define TRIG_TIMER 0x00000010 /* trigger at rate N ns */ | 158 | #define TRIG_TIMER 0x00000010 /* trigger at rate N ns */ |
159 | #define TRIG_COUNT 0x00000020 /* trigger when count reaches N */ | 159 | #define TRIG_COUNT 0x00000020 /* trigger when count reaches N */ |
160 | #define TRIG_EXT 0x00000040 /* trigger on external signal N */ | 160 | #define TRIG_EXT 0x00000040 /* trigger on external signal N */ |
161 | #define TRIG_INT 0x00000080 /* trigger on comedi-internal signal N */ | 161 | #define TRIG_INT 0x00000080 /* trigger on comedi-internal signal N */ |
162 | #define TRIG_OTHER 0x00000100 /* driver defined */ | 162 | #define TRIG_OTHER 0x00000100 /* driver defined */ |
163 | 163 | ||
164 | /* subdevice flags */ | 164 | /* subdevice flags */ |
165 | 165 | ||
166 | #define SDF_BUSY 0x0001 /* device is busy */ | 166 | #define SDF_BUSY 0x0001 /* device is busy */ |
167 | #define SDF_BUSY_OWNER 0x0002 /* device is busy with your job */ | 167 | #define SDF_BUSY_OWNER 0x0002 /* device is busy with your job */ |
168 | #define SDF_LOCKED 0x0004 /* subdevice is locked */ | 168 | #define SDF_LOCKED 0x0004 /* subdevice is locked */ |
169 | #define SDF_LOCK_OWNER 0x0008 /* you own lock */ | 169 | #define SDF_LOCK_OWNER 0x0008 /* you own lock */ |
170 | #define SDF_MAXDATA 0x0010 /* maxdata depends on channel */ | 170 | #define SDF_MAXDATA 0x0010 /* maxdata depends on channel */ |
171 | #define SDF_FLAGS 0x0020 /* flags depend on channel */ | 171 | #define SDF_FLAGS 0x0020 /* flags depend on channel */ |
172 | #define SDF_RANGETYPE 0x0040 /* range type depends on channel */ | 172 | #define SDF_RANGETYPE 0x0040 /* range type depends on channel */ |
173 | #define SDF_MODE0 0x0080 /* can do mode 0 */ | 173 | #define SDF_MODE0 0x0080 /* can do mode 0 */ |
174 | #define SDF_MODE1 0x0100 /* can do mode 1 */ | 174 | #define SDF_MODE1 0x0100 /* can do mode 1 */ |
175 | #define SDF_MODE2 0x0200 /* can do mode 2 */ | 175 | #define SDF_MODE2 0x0200 /* can do mode 2 */ |
176 | #define SDF_MODE3 0x0400 /* can do mode 3 */ | 176 | #define SDF_MODE3 0x0400 /* can do mode 3 */ |
177 | #define SDF_MODE4 0x0800 /* can do mode 4 */ | 177 | #define SDF_MODE4 0x0800 /* can do mode 4 */ |
178 | #define SDF_CMD 0x1000 /* can do commands (deprecated) */ | 178 | #define SDF_CMD 0x1000 /* can do commands (deprecated) */ |
179 | #define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */ | 179 | #define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */ |
180 | #define SDF_CMD_WRITE 0x4000 /* can do output commands */ | 180 | #define SDF_CMD_WRITE 0x4000 /* can do output commands */ |
181 | #define SDF_CMD_READ 0x8000 /* can do input commands */ | 181 | #define SDF_CMD_READ 0x8000 /* can do input commands */ |
182 | 182 | ||
183 | #define SDF_READABLE 0x00010000 /* subdevice can be read (e.g. analog input) */ | 183 | #define SDF_READABLE 0x00010000 /* subdevice can be read (e.g. analog input) */ |
184 | #define SDF_WRITABLE 0x00020000 /* subdevice can be written (e.g. analog output) */ | 184 | #define SDF_WRITABLE 0x00020000 /* subdevice can be written (e.g. analog output) */ |
185 | #define SDF_WRITEABLE SDF_WRITABLE /* spelling error in API */ | 185 | #define SDF_WRITEABLE SDF_WRITABLE /* spelling error in API */ |
186 | #define SDF_INTERNAL 0x00040000 /* subdevice does not have externally visible lines */ | 186 | #define SDF_INTERNAL 0x00040000 /* subdevice does not have externally visible lines */ |
187 | #define SDF_GROUND 0x00100000 /* can do aref=ground */ | 187 | #define SDF_GROUND 0x00100000 /* can do aref=ground */ |
188 | #define SDF_COMMON 0x00200000 /* can do aref=common */ | 188 | #define SDF_COMMON 0x00200000 /* can do aref=common */ |
189 | #define SDF_DIFF 0x00400000 /* can do aref=diff */ | 189 | #define SDF_DIFF 0x00400000 /* can do aref=diff */ |
190 | #define SDF_OTHER 0x00800000 /* can do aref=other */ | 190 | #define SDF_OTHER 0x00800000 /* can do aref=other */ |
191 | #define SDF_DITHER 0x01000000 /* can do dithering */ | 191 | #define SDF_DITHER 0x01000000 /* can do dithering */ |
192 | #define SDF_DEGLITCH 0x02000000 /* can do deglitching */ | 192 | #define SDF_DEGLITCH 0x02000000 /* can do deglitching */ |
193 | #define SDF_MMAP 0x04000000 /* can do mmap() */ | 193 | #define SDF_MMAP 0x04000000 /* can do mmap() */ |
194 | #define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */ | 194 | #define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */ |
195 | #define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */ | 195 | #define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */ |
196 | #define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */ | 196 | #define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */ |
197 | /* re recyle these flags for PWM */ | 197 | /* re recyle these flags for PWM */ |
198 | #define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */ | 198 | #define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */ |
199 | #define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */ | 199 | #define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */ |
200 | 200 | ||
201 | /* subdevice types */ | 201 | /* subdevice types */ |
202 | 202 | ||
203 | enum comedi_subdevice_type { | 203 | enum comedi_subdevice_type { |
204 | COMEDI_SUBD_UNUSED, /* unused by driver */ | 204 | COMEDI_SUBD_UNUSED, /* unused by driver */ |
205 | COMEDI_SUBD_AI, /* analog input */ | 205 | COMEDI_SUBD_AI, /* analog input */ |
206 | COMEDI_SUBD_AO, /* analog output */ | 206 | COMEDI_SUBD_AO, /* analog output */ |
207 | COMEDI_SUBD_DI, /* digital input */ | 207 | COMEDI_SUBD_DI, /* digital input */ |
208 | COMEDI_SUBD_DO, /* digital output */ | 208 | COMEDI_SUBD_DO, /* digital output */ |
209 | COMEDI_SUBD_DIO, /* digital input/output */ | 209 | COMEDI_SUBD_DIO, /* digital input/output */ |
210 | COMEDI_SUBD_COUNTER, /* counter */ | 210 | COMEDI_SUBD_COUNTER, /* counter */ |
211 | COMEDI_SUBD_TIMER, /* timer */ | 211 | COMEDI_SUBD_TIMER, /* timer */ |
212 | COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */ | 212 | COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */ |
213 | COMEDI_SUBD_CALIB, /* calibration DACs */ | 213 | COMEDI_SUBD_CALIB, /* calibration DACs */ |
214 | COMEDI_SUBD_PROC, /* processor, DSP */ | 214 | COMEDI_SUBD_PROC, /* processor, DSP */ |
215 | COMEDI_SUBD_SERIAL, /* serial IO */ | 215 | COMEDI_SUBD_SERIAL, /* serial IO */ |
216 | COMEDI_SUBD_PWM /* PWM */ | 216 | COMEDI_SUBD_PWM /* PWM */ |
217 | }; | 217 | }; |
218 | 218 | ||
219 | /* configuration instructions */ | 219 | /* configuration instructions */ |
220 | 220 | ||
221 | enum configuration_ids { | 221 | enum configuration_ids { |
222 | INSN_CONFIG_DIO_INPUT = 0, | 222 | INSN_CONFIG_DIO_INPUT = 0, |
223 | INSN_CONFIG_DIO_OUTPUT = 1, | 223 | INSN_CONFIG_DIO_OUTPUT = 1, |
224 | INSN_CONFIG_DIO_OPENDRAIN = 2, | 224 | INSN_CONFIG_DIO_OPENDRAIN = 2, |
225 | INSN_CONFIG_ANALOG_TRIG = 16, | 225 | INSN_CONFIG_ANALOG_TRIG = 16, |
226 | /* INSN_CONFIG_WAVEFORM = 17, */ | 226 | /* INSN_CONFIG_WAVEFORM = 17, */ |
227 | /* INSN_CONFIG_TRIG = 18, */ | 227 | /* INSN_CONFIG_TRIG = 18, */ |
228 | /* INSN_CONFIG_COUNTER = 19, */ | 228 | /* INSN_CONFIG_COUNTER = 19, */ |
229 | INSN_CONFIG_ALT_SOURCE = 20, | 229 | INSN_CONFIG_ALT_SOURCE = 20, |
230 | INSN_CONFIG_DIGITAL_TRIG = 21, | 230 | INSN_CONFIG_DIGITAL_TRIG = 21, |
231 | INSN_CONFIG_BLOCK_SIZE = 22, | 231 | INSN_CONFIG_BLOCK_SIZE = 22, |
232 | INSN_CONFIG_TIMER_1 = 23, | 232 | INSN_CONFIG_TIMER_1 = 23, |
233 | INSN_CONFIG_FILTER = 24, | 233 | INSN_CONFIG_FILTER = 24, |
234 | INSN_CONFIG_CHANGE_NOTIFY = 25, | 234 | INSN_CONFIG_CHANGE_NOTIFY = 25, |
235 | 235 | ||
236 | /*ALPHA*/ INSN_CONFIG_SERIAL_CLOCK = 26, | 236 | /*ALPHA*/ INSN_CONFIG_SERIAL_CLOCK = 26, |
237 | INSN_CONFIG_BIDIRECTIONAL_DATA = 27, | 237 | INSN_CONFIG_BIDIRECTIONAL_DATA = 27, |
238 | INSN_CONFIG_DIO_QUERY = 28, | 238 | INSN_CONFIG_DIO_QUERY = 28, |
239 | INSN_CONFIG_PWM_OUTPUT = 29, | 239 | INSN_CONFIG_PWM_OUTPUT = 29, |
240 | INSN_CONFIG_GET_PWM_OUTPUT = 30, | 240 | INSN_CONFIG_GET_PWM_OUTPUT = 30, |
241 | INSN_CONFIG_ARM = 31, | 241 | INSN_CONFIG_ARM = 31, |
242 | INSN_CONFIG_DISARM = 32, | 242 | INSN_CONFIG_DISARM = 32, |
243 | INSN_CONFIG_GET_COUNTER_STATUS = 33, | 243 | INSN_CONFIG_GET_COUNTER_STATUS = 33, |
244 | INSN_CONFIG_RESET = 34, | 244 | INSN_CONFIG_RESET = 34, |
245 | INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, /* Use CTR as single pulsegenerator */ | 245 | INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, /* Use CTR as single pulsegenerator */ |
246 | INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, /* Use CTR as pulsetraingenerator */ | 246 | INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, /* Use CTR as pulsetraingenerator */ |
247 | INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, /* Use the counter as encoder */ | 247 | INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, /* Use the counter as encoder */ |
248 | INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */ | 248 | INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */ |
249 | INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */ | 249 | INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */ |
250 | INSN_CONFIG_SET_CLOCK_SRC = 2003, /* Set master clock source */ | 250 | INSN_CONFIG_SET_CLOCK_SRC = 2003, /* Set master clock source */ |
251 | INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ | 251 | INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ |
252 | INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ | 252 | INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ |
253 | /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ | 253 | /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ |
254 | INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, /* Get size in bytes of | 254 | INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, /* Get size in bytes of |
255 | subdevice's on-board | 255 | subdevice's on-board |
256 | fifos used during | 256 | fifos used during |
257 | streaming | 257 | streaming |
258 | input/output */ | 258 | input/output */ |
259 | INSN_CONFIG_SET_COUNTER_MODE = 4097, | 259 | INSN_CONFIG_SET_COUNTER_MODE = 4097, |
260 | INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */ | 260 | INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */ |
261 | INSN_CONFIG_8254_READ_STATUS = 4098, | 261 | INSN_CONFIG_8254_READ_STATUS = 4098, |
262 | INSN_CONFIG_SET_ROUTING = 4099, | 262 | INSN_CONFIG_SET_ROUTING = 4099, |
263 | INSN_CONFIG_GET_ROUTING = 4109, | 263 | INSN_CONFIG_GET_ROUTING = 4109, |
264 | /* PWM */ | 264 | /* PWM */ |
265 | INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */ | 265 | INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */ |
266 | INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ | 266 | INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ |
267 | INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ | 267 | INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ |
268 | INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, /* sets H bridge: duty cycle and sign bit for a relay at the same time */ | 268 | INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, /* sets H bridge: duty cycle and sign bit for a relay at the same time */ |
269 | INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 /* gets H bridge data: duty cycle and the sign bit */ | 269 | INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 /* gets H bridge data: duty cycle and the sign bit */ |
270 | }; | 270 | }; |
271 | 271 | ||
272 | enum comedi_io_direction { | 272 | enum comedi_io_direction { |
273 | COMEDI_INPUT = 0, | 273 | COMEDI_INPUT = 0, |
274 | COMEDI_OUTPUT = 1, | 274 | COMEDI_OUTPUT = 1, |
275 | COMEDI_OPENDRAIN = 2 | 275 | COMEDI_OPENDRAIN = 2 |
276 | }; | 276 | }; |
277 | 277 | ||
278 | enum comedi_support_level { | 278 | enum comedi_support_level { |
279 | COMEDI_UNKNOWN_SUPPORT = 0, | 279 | COMEDI_UNKNOWN_SUPPORT = 0, |
280 | COMEDI_SUPPORTED, | 280 | COMEDI_SUPPORTED, |
281 | COMEDI_UNSUPPORTED | 281 | COMEDI_UNSUPPORTED |
282 | }; | 282 | }; |
283 | 283 | ||
284 | /* ioctls */ | 284 | /* ioctls */ |
285 | 285 | ||
286 | #define CIO 'd' | 286 | #define CIO 'd' |
287 | #define COMEDI_DEVCONFIG _IOW(CIO, 0, struct comedi_devconfig) | 287 | #define COMEDI_DEVCONFIG _IOW(CIO, 0, struct comedi_devconfig) |
288 | #define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo) | 288 | #define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo) |
289 | #define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo) | 289 | #define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo) |
290 | #define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo) | 290 | #define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo) |
291 | #define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig) | 291 | #define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig) |
292 | #define COMEDI_LOCK _IO(CIO, 5) | 292 | #define COMEDI_LOCK _IO(CIO, 5) |
293 | #define COMEDI_UNLOCK _IO(CIO, 6) | 293 | #define COMEDI_UNLOCK _IO(CIO, 6) |
294 | #define COMEDI_CANCEL _IO(CIO, 7) | 294 | #define COMEDI_CANCEL _IO(CIO, 7) |
295 | #define COMEDI_RANGEINFO _IOR(CIO, 8, struct comedi_rangeinfo) | 295 | #define COMEDI_RANGEINFO _IOR(CIO, 8, struct comedi_rangeinfo) |
296 | #define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd) | 296 | #define COMEDI_CMD _IOR(CIO, 9, struct comedi_cmd) |
297 | #define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd) | 297 | #define COMEDI_CMDTEST _IOR(CIO, 10, struct comedi_cmd) |
298 | #define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist) | 298 | #define COMEDI_INSNLIST _IOR(CIO, 11, struct comedi_insnlist) |
299 | #define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn) | 299 | #define COMEDI_INSN _IOR(CIO, 12, struct comedi_insn) |
300 | #define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig) | 300 | #define COMEDI_BUFCONFIG _IOR(CIO, 13, struct comedi_bufconfig) |
301 | #define COMEDI_BUFINFO _IOWR(CIO, 14, struct comedi_bufinfo) | 301 | #define COMEDI_BUFINFO _IOWR(CIO, 14, struct comedi_bufinfo) |
302 | #define COMEDI_POLL _IO(CIO, 15) | 302 | #define COMEDI_POLL _IO(CIO, 15) |
303 | 303 | ||
304 | /* structures */ | 304 | /* structures */ |
305 | 305 | ||
306 | struct comedi_trig { | 306 | struct comedi_trig { |
307 | unsigned int subdev; /* subdevice */ | 307 | unsigned int subdev; /* subdevice */ |
308 | unsigned int mode; /* mode */ | 308 | unsigned int mode; /* mode */ |
309 | unsigned int flags; | 309 | unsigned int flags; |
310 | unsigned int n_chan; /* number of channels */ | 310 | unsigned int n_chan; /* number of channels */ |
311 | unsigned int *chanlist; /* channel/range list */ | 311 | unsigned int *chanlist; /* channel/range list */ |
312 | short *data; /* data list, size depends on subd flags */ | 312 | short *data; /* data list, size depends on subd flags */ |
313 | unsigned int n; /* number of scans */ | 313 | unsigned int n; /* number of scans */ |
314 | unsigned int trigsrc; | 314 | unsigned int trigsrc; |
315 | unsigned int trigvar; | 315 | unsigned int trigvar; |
316 | unsigned int trigvar1; | 316 | unsigned int trigvar1; |
317 | unsigned int data_len; | 317 | unsigned int data_len; |
318 | unsigned int unused[3]; | 318 | unsigned int unused[3]; |
319 | }; | 319 | }; |
320 | 320 | ||
321 | struct comedi_insn { | 321 | struct comedi_insn { |
322 | unsigned int insn; | 322 | unsigned int insn; |
323 | unsigned int n; | 323 | unsigned int n; |
324 | unsigned int *data; | 324 | unsigned int *data; |
325 | unsigned int subdev; | 325 | unsigned int subdev; |
326 | unsigned int chanspec; | 326 | unsigned int chanspec; |
327 | unsigned int unused[3]; | 327 | unsigned int unused[3]; |
328 | }; | 328 | }; |
329 | 329 | ||
330 | struct comedi_insnlist { | 330 | struct comedi_insnlist { |
331 | unsigned int n_insns; | 331 | unsigned int n_insns; |
332 | struct comedi_insn *insns; | 332 | struct comedi_insn *insns; |
333 | }; | 333 | }; |
334 | 334 | ||
335 | struct comedi_cmd { | 335 | struct comedi_cmd { |
336 | unsigned int subdev; | 336 | unsigned int subdev; |
337 | unsigned int flags; | 337 | unsigned int flags; |
338 | 338 | ||
339 | unsigned int start_src; | 339 | unsigned int start_src; |
340 | unsigned int start_arg; | 340 | unsigned int start_arg; |
341 | 341 | ||
342 | unsigned int scan_begin_src; | 342 | unsigned int scan_begin_src; |
343 | unsigned int scan_begin_arg; | 343 | unsigned int scan_begin_arg; |
344 | 344 | ||
345 | unsigned int convert_src; | 345 | unsigned int convert_src; |
346 | unsigned int convert_arg; | 346 | unsigned int convert_arg; |
347 | 347 | ||
348 | unsigned int scan_end_src; | 348 | unsigned int scan_end_src; |
349 | unsigned int scan_end_arg; | 349 | unsigned int scan_end_arg; |
350 | 350 | ||
351 | unsigned int stop_src; | 351 | unsigned int stop_src; |
352 | unsigned int stop_arg; | 352 | unsigned int stop_arg; |
353 | 353 | ||
354 | unsigned int *chanlist; /* channel/range list */ | 354 | unsigned int *chanlist; /* channel/range list */ |
355 | unsigned int chanlist_len; | 355 | unsigned int chanlist_len; |
356 | 356 | ||
357 | short *data; /* data list, size depends on subd flags */ | 357 | short *data; /* data list, size depends on subd flags */ |
358 | unsigned int data_len; | 358 | unsigned int data_len; |
359 | }; | 359 | }; |
360 | 360 | ||
361 | struct comedi_chaninfo { | 361 | struct comedi_chaninfo { |
362 | unsigned int subdev; | 362 | unsigned int subdev; |
363 | unsigned int *maxdata_list; | 363 | unsigned int *maxdata_list; |
364 | unsigned int *flaglist; | 364 | unsigned int *flaglist; |
365 | unsigned int *rangelist; | 365 | unsigned int *rangelist; |
366 | unsigned int unused[4]; | 366 | unsigned int unused[4]; |
367 | }; | 367 | }; |
368 | 368 | ||
369 | struct comedi_rangeinfo { | 369 | struct comedi_rangeinfo { |
370 | unsigned int range_type; | 370 | unsigned int range_type; |
371 | void *range_ptr; | 371 | void __user *range_ptr; |
372 | }; | 372 | }; |
373 | 373 | ||
374 | struct comedi_krange { | 374 | struct comedi_krange { |
375 | int min; /* fixed point, multiply by 1e-6 */ | 375 | int min; /* fixed point, multiply by 1e-6 */ |
376 | int max; /* fixed point, multiply by 1e-6 */ | 376 | int max; /* fixed point, multiply by 1e-6 */ |
377 | unsigned int flags; | 377 | unsigned int flags; |
378 | }; | 378 | }; |
379 | 379 | ||
380 | struct comedi_subdinfo { | 380 | struct comedi_subdinfo { |
381 | unsigned int type; | 381 | unsigned int type; |
382 | unsigned int n_chan; | 382 | unsigned int n_chan; |
383 | unsigned int subd_flags; | 383 | unsigned int subd_flags; |
384 | unsigned int timer_type; | 384 | unsigned int timer_type; |
385 | unsigned int len_chanlist; | 385 | unsigned int len_chanlist; |
386 | unsigned int maxdata; | 386 | unsigned int maxdata; |
387 | unsigned int flags; /* channel flags */ | 387 | unsigned int flags; /* channel flags */ |
388 | unsigned int range_type; /* lookup in kernel */ | 388 | unsigned int range_type; /* lookup in kernel */ |
389 | unsigned int settling_time_0; | 389 | unsigned int settling_time_0; |
390 | unsigned insn_bits_support; /* see support_level enum for values */ | 390 | unsigned insn_bits_support; /* see support_level enum for values */ |
391 | unsigned int unused[8]; | 391 | unsigned int unused[8]; |
392 | }; | 392 | }; |
393 | 393 | ||
394 | struct comedi_devinfo { | 394 | struct comedi_devinfo { |
395 | unsigned int version_code; | 395 | unsigned int version_code; |
396 | unsigned int n_subdevs; | 396 | unsigned int n_subdevs; |
397 | char driver_name[COMEDI_NAMELEN]; | 397 | char driver_name[COMEDI_NAMELEN]; |
398 | char board_name[COMEDI_NAMELEN]; | 398 | char board_name[COMEDI_NAMELEN]; |
399 | int read_subdevice; | 399 | int read_subdevice; |
400 | int write_subdevice; | 400 | int write_subdevice; |
401 | int unused[30]; | 401 | int unused[30]; |
402 | }; | 402 | }; |
403 | 403 | ||
404 | struct comedi_devconfig { | 404 | struct comedi_devconfig { |
405 | char board_name[COMEDI_NAMELEN]; | 405 | char board_name[COMEDI_NAMELEN]; |
406 | int options[COMEDI_NDEVCONFOPTS]; | 406 | int options[COMEDI_NDEVCONFOPTS]; |
407 | }; | 407 | }; |
408 | 408 | ||
409 | struct comedi_bufconfig { | 409 | struct comedi_bufconfig { |
410 | unsigned int subdevice; | 410 | unsigned int subdevice; |
411 | unsigned int flags; | 411 | unsigned int flags; |
412 | 412 | ||
413 | unsigned int maximum_size; | 413 | unsigned int maximum_size; |
414 | unsigned int size; | 414 | unsigned int size; |
415 | 415 | ||
416 | unsigned int unused[4]; | 416 | unsigned int unused[4]; |
417 | }; | 417 | }; |
418 | 418 | ||
419 | struct comedi_bufinfo { | 419 | struct comedi_bufinfo { |
420 | unsigned int subdevice; | 420 | unsigned int subdevice; |
421 | unsigned int bytes_read; | 421 | unsigned int bytes_read; |
422 | 422 | ||
423 | unsigned int buf_write_ptr; | 423 | unsigned int buf_write_ptr; |
424 | unsigned int buf_read_ptr; | 424 | unsigned int buf_read_ptr; |
425 | unsigned int buf_write_count; | 425 | unsigned int buf_write_count; |
426 | unsigned int buf_read_count; | 426 | unsigned int buf_read_count; |
427 | 427 | ||
428 | unsigned int bytes_written; | 428 | unsigned int bytes_written; |
429 | 429 | ||
430 | unsigned int unused[4]; | 430 | unsigned int unused[4]; |
431 | }; | 431 | }; |
432 | 432 | ||
433 | /* range stuff */ | 433 | /* range stuff */ |
434 | 434 | ||
435 | #define __RANGE(a, b) ((((a)&0xffff)<<16)|((b)&0xffff)) | 435 | #define __RANGE(a, b) ((((a)&0xffff)<<16)|((b)&0xffff)) |
436 | 436 | ||
437 | #define RANGE_OFFSET(a) (((a)>>16)&0xffff) | 437 | #define RANGE_OFFSET(a) (((a)>>16)&0xffff) |
438 | #define RANGE_LENGTH(b) ((b)&0xffff) | 438 | #define RANGE_LENGTH(b) ((b)&0xffff) |
439 | 439 | ||
440 | #define RF_UNIT(flags) ((flags)&0xff) | 440 | #define RF_UNIT(flags) ((flags)&0xff) |
441 | #define RF_EXTERNAL (1<<8) | 441 | #define RF_EXTERNAL (1<<8) |
442 | 442 | ||
443 | #define UNIT_volt 0 | 443 | #define UNIT_volt 0 |
444 | #define UNIT_mA 1 | 444 | #define UNIT_mA 1 |
445 | #define UNIT_none 2 | 445 | #define UNIT_none 2 |
446 | 446 | ||
447 | #define COMEDI_MIN_SPEED ((unsigned int)0xffffffff) | 447 | #define COMEDI_MIN_SPEED ((unsigned int)0xffffffff) |
448 | 448 | ||
449 | /* callback stuff */ | 449 | /* callback stuff */ |
450 | /* only relevant to kernel modules. */ | 450 | /* only relevant to kernel modules. */ |
451 | 451 | ||
452 | #define COMEDI_CB_EOS 1 /* end of scan */ | 452 | #define COMEDI_CB_EOS 1 /* end of scan */ |
453 | #define COMEDI_CB_EOA 2 /* end of acquisition */ | 453 | #define COMEDI_CB_EOA 2 /* end of acquisition */ |
454 | #define COMEDI_CB_BLOCK 4 /* data has arrived: wakes up read() / write() */ | 454 | #define COMEDI_CB_BLOCK 4 /* data has arrived: wakes up read() / write() */ |
455 | #define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */ | 455 | #define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */ |
456 | #define COMEDI_CB_ERROR 16 /* card error during acquisition */ | 456 | #define COMEDI_CB_ERROR 16 /* card error during acquisition */ |
457 | #define COMEDI_CB_OVERFLOW 32 /* buffer overflow/underflow */ | 457 | #define COMEDI_CB_OVERFLOW 32 /* buffer overflow/underflow */ |
458 | 458 | ||
459 | /**********************************************************/ | 459 | /**********************************************************/ |
460 | /* everything after this line is ALPHA */ | 460 | /* everything after this line is ALPHA */ |
461 | /**********************************************************/ | 461 | /**********************************************************/ |
462 | 462 | ||
463 | /* | 463 | /* |
464 | 8254 specific configuration. | 464 | 8254 specific configuration. |
465 | 465 | ||
466 | It supports two config commands: | 466 | It supports two config commands: |
467 | 467 | ||
468 | 0 ID: INSN_CONFIG_SET_COUNTER_MODE | 468 | 0 ID: INSN_CONFIG_SET_COUNTER_MODE |
469 | 1 8254 Mode | 469 | 1 8254 Mode |
470 | I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 | 470 | I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 |
471 | OR'ed with: | 471 | OR'ed with: |
472 | I8254_BCD, I8254_BINARY | 472 | I8254_BCD, I8254_BINARY |
473 | 473 | ||
474 | 0 ID: INSN_CONFIG_8254_READ_STATUS | 474 | 0 ID: INSN_CONFIG_8254_READ_STATUS |
475 | 1 <-- Status byte returned here. | 475 | 1 <-- Status byte returned here. |
476 | B7 = Output | 476 | B7 = Output |
477 | B6 = NULL Count | 477 | B6 = NULL Count |
478 | B5 - B0 Current mode. | 478 | B5 - B0 Current mode. |
479 | 479 | ||
480 | */ | 480 | */ |
481 | 481 | ||
482 | enum i8254_mode { | 482 | enum i8254_mode { |
483 | I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ | 483 | I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ |
484 | I8254_MODE1 = (1 << 1), /* Hardware retriggerable one-shot */ | 484 | I8254_MODE1 = (1 << 1), /* Hardware retriggerable one-shot */ |
485 | I8254_MODE2 = (2 << 1), /* Rate generator */ | 485 | I8254_MODE2 = (2 << 1), /* Rate generator */ |
486 | I8254_MODE3 = (3 << 1), /* Square wave mode */ | 486 | I8254_MODE3 = (3 << 1), /* Square wave mode */ |
487 | I8254_MODE4 = (4 << 1), /* Software triggered strobe */ | 487 | I8254_MODE4 = (4 << 1), /* Software triggered strobe */ |
488 | I8254_MODE5 = (5 << 1), /* Hardware triggered strobe (retriggerable) */ | 488 | I8254_MODE5 = (5 << 1), /* Hardware triggered strobe (retriggerable) */ |
489 | I8254_BCD = 1, /* use binary-coded decimal instead of binary (pretty useless) */ | 489 | I8254_BCD = 1, /* use binary-coded decimal instead of binary (pretty useless) */ |
490 | I8254_BINARY = 0 | 490 | I8254_BINARY = 0 |
491 | }; | 491 | }; |
492 | 492 | ||
493 | static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) | 493 | static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) |
494 | { | 494 | { |
495 | if (pfi_channel < 10) | 495 | if (pfi_channel < 10) |
496 | return 0x1 + pfi_channel; | 496 | return 0x1 + pfi_channel; |
497 | else | 497 | else |
498 | return 0xb + pfi_channel; | 498 | return 0xb + pfi_channel; |
499 | } static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) { | 499 | } static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) { |
500 | if (rtsi_channel < 7) | 500 | if (rtsi_channel < 7) |
501 | return 0xb + rtsi_channel; | 501 | return 0xb + rtsi_channel; |
502 | else | 502 | else |
503 | return 0x1b; | 503 | return 0x1b; |
504 | } | 504 | } |
505 | /* mode bits for NI general-purpose counters, set with | 505 | /* mode bits for NI general-purpose counters, set with |
506 | * INSN_CONFIG_SET_COUNTER_MODE */ | 506 | * INSN_CONFIG_SET_COUNTER_MODE */ |
507 | #define NI_GPCT_COUNTING_MODE_SHIFT 16 | 507 | #define NI_GPCT_COUNTING_MODE_SHIFT 16 |
508 | #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 | 508 | #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 |
509 | #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 | 509 | #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 |
510 | enum ni_gpct_mode_bits { | 510 | enum ni_gpct_mode_bits { |
511 | NI_GPCT_GATE_ON_BOTH_EDGES_BIT = 0x4, | 511 | NI_GPCT_GATE_ON_BOTH_EDGES_BIT = 0x4, |
512 | NI_GPCT_EDGE_GATE_MODE_MASK = 0x18, | 512 | NI_GPCT_EDGE_GATE_MODE_MASK = 0x18, |
513 | NI_GPCT_EDGE_GATE_STARTS_STOPS_BITS = 0x0, | 513 | NI_GPCT_EDGE_GATE_STARTS_STOPS_BITS = 0x0, |
514 | NI_GPCT_EDGE_GATE_STOPS_STARTS_BITS = 0x8, | 514 | NI_GPCT_EDGE_GATE_STOPS_STARTS_BITS = 0x8, |
515 | NI_GPCT_EDGE_GATE_STARTS_BITS = 0x10, | 515 | NI_GPCT_EDGE_GATE_STARTS_BITS = 0x10, |
516 | NI_GPCT_EDGE_GATE_NO_STARTS_NO_STOPS_BITS = 0x18, | 516 | NI_GPCT_EDGE_GATE_NO_STARTS_NO_STOPS_BITS = 0x18, |
517 | NI_GPCT_STOP_MODE_MASK = 0x60, | 517 | NI_GPCT_STOP_MODE_MASK = 0x60, |
518 | NI_GPCT_STOP_ON_GATE_BITS = 0x00, | 518 | NI_GPCT_STOP_ON_GATE_BITS = 0x00, |
519 | NI_GPCT_STOP_ON_GATE_OR_TC_BITS = 0x20, | 519 | NI_GPCT_STOP_ON_GATE_OR_TC_BITS = 0x20, |
520 | NI_GPCT_STOP_ON_GATE_OR_SECOND_TC_BITS = 0x40, | 520 | NI_GPCT_STOP_ON_GATE_OR_SECOND_TC_BITS = 0x40, |
521 | NI_GPCT_LOAD_B_SELECT_BIT = 0x80, | 521 | NI_GPCT_LOAD_B_SELECT_BIT = 0x80, |
522 | NI_GPCT_OUTPUT_MODE_MASK = 0x300, | 522 | NI_GPCT_OUTPUT_MODE_MASK = 0x300, |
523 | NI_GPCT_OUTPUT_TC_PULSE_BITS = 0x100, | 523 | NI_GPCT_OUTPUT_TC_PULSE_BITS = 0x100, |
524 | NI_GPCT_OUTPUT_TC_TOGGLE_BITS = 0x200, | 524 | NI_GPCT_OUTPUT_TC_TOGGLE_BITS = 0x200, |
525 | NI_GPCT_OUTPUT_TC_OR_GATE_TOGGLE_BITS = 0x300, | 525 | NI_GPCT_OUTPUT_TC_OR_GATE_TOGGLE_BITS = 0x300, |
526 | NI_GPCT_HARDWARE_DISARM_MASK = 0xc00, | 526 | NI_GPCT_HARDWARE_DISARM_MASK = 0xc00, |
527 | NI_GPCT_NO_HARDWARE_DISARM_BITS = 0x000, | 527 | NI_GPCT_NO_HARDWARE_DISARM_BITS = 0x000, |
528 | NI_GPCT_DISARM_AT_TC_BITS = 0x400, | 528 | NI_GPCT_DISARM_AT_TC_BITS = 0x400, |
529 | NI_GPCT_DISARM_AT_GATE_BITS = 0x800, | 529 | NI_GPCT_DISARM_AT_GATE_BITS = 0x800, |
530 | NI_GPCT_DISARM_AT_TC_OR_GATE_BITS = 0xc00, | 530 | NI_GPCT_DISARM_AT_TC_OR_GATE_BITS = 0xc00, |
531 | NI_GPCT_LOADING_ON_TC_BIT = 0x1000, | 531 | NI_GPCT_LOADING_ON_TC_BIT = 0x1000, |
532 | NI_GPCT_LOADING_ON_GATE_BIT = 0x4000, | 532 | NI_GPCT_LOADING_ON_GATE_BIT = 0x4000, |
533 | NI_GPCT_COUNTING_MODE_MASK = 0x7 << NI_GPCT_COUNTING_MODE_SHIFT, | 533 | NI_GPCT_COUNTING_MODE_MASK = 0x7 << NI_GPCT_COUNTING_MODE_SHIFT, |
534 | NI_GPCT_COUNTING_MODE_NORMAL_BITS = | 534 | NI_GPCT_COUNTING_MODE_NORMAL_BITS = |
535 | 0x0 << NI_GPCT_COUNTING_MODE_SHIFT, | 535 | 0x0 << NI_GPCT_COUNTING_MODE_SHIFT, |
536 | NI_GPCT_COUNTING_MODE_QUADRATURE_X1_BITS = | 536 | NI_GPCT_COUNTING_MODE_QUADRATURE_X1_BITS = |
537 | 0x1 << NI_GPCT_COUNTING_MODE_SHIFT, | 537 | 0x1 << NI_GPCT_COUNTING_MODE_SHIFT, |
538 | NI_GPCT_COUNTING_MODE_QUADRATURE_X2_BITS = | 538 | NI_GPCT_COUNTING_MODE_QUADRATURE_X2_BITS = |
539 | 0x2 << NI_GPCT_COUNTING_MODE_SHIFT, | 539 | 0x2 << NI_GPCT_COUNTING_MODE_SHIFT, |
540 | NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS = | 540 | NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS = |
541 | 0x3 << NI_GPCT_COUNTING_MODE_SHIFT, | 541 | 0x3 << NI_GPCT_COUNTING_MODE_SHIFT, |
542 | NI_GPCT_COUNTING_MODE_TWO_PULSE_BITS = | 542 | NI_GPCT_COUNTING_MODE_TWO_PULSE_BITS = |
543 | 0x4 << NI_GPCT_COUNTING_MODE_SHIFT, | 543 | 0x4 << NI_GPCT_COUNTING_MODE_SHIFT, |
544 | NI_GPCT_COUNTING_MODE_SYNC_SOURCE_BITS = | 544 | NI_GPCT_COUNTING_MODE_SYNC_SOURCE_BITS = |
545 | 0x6 << NI_GPCT_COUNTING_MODE_SHIFT, | 545 | 0x6 << NI_GPCT_COUNTING_MODE_SHIFT, |
546 | NI_GPCT_INDEX_PHASE_MASK = 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, | 546 | NI_GPCT_INDEX_PHASE_MASK = 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, |
547 | NI_GPCT_INDEX_PHASE_LOW_A_LOW_B_BITS = | 547 | NI_GPCT_INDEX_PHASE_LOW_A_LOW_B_BITS = |
548 | 0x0 << NI_GPCT_INDEX_PHASE_BITSHIFT, | 548 | 0x0 << NI_GPCT_INDEX_PHASE_BITSHIFT, |
549 | NI_GPCT_INDEX_PHASE_LOW_A_HIGH_B_BITS = | 549 | NI_GPCT_INDEX_PHASE_LOW_A_HIGH_B_BITS = |
550 | 0x1 << NI_GPCT_INDEX_PHASE_BITSHIFT, | 550 | 0x1 << NI_GPCT_INDEX_PHASE_BITSHIFT, |
551 | NI_GPCT_INDEX_PHASE_HIGH_A_LOW_B_BITS = | 551 | NI_GPCT_INDEX_PHASE_HIGH_A_LOW_B_BITS = |
552 | 0x2 << NI_GPCT_INDEX_PHASE_BITSHIFT, | 552 | 0x2 << NI_GPCT_INDEX_PHASE_BITSHIFT, |
553 | NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_BITS = | 553 | NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_BITS = |
554 | 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, | 554 | 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT, |
555 | NI_GPCT_INDEX_ENABLE_BIT = 0x400000, | 555 | NI_GPCT_INDEX_ENABLE_BIT = 0x400000, |
556 | NI_GPCT_COUNTING_DIRECTION_MASK = | 556 | NI_GPCT_COUNTING_DIRECTION_MASK = |
557 | 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, | 557 | 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, |
558 | NI_GPCT_COUNTING_DIRECTION_DOWN_BITS = | 558 | NI_GPCT_COUNTING_DIRECTION_DOWN_BITS = |
559 | 0x00 << NI_GPCT_COUNTING_DIRECTION_SHIFT, | 559 | 0x00 << NI_GPCT_COUNTING_DIRECTION_SHIFT, |
560 | NI_GPCT_COUNTING_DIRECTION_UP_BITS = | 560 | NI_GPCT_COUNTING_DIRECTION_UP_BITS = |
561 | 0x1 << NI_GPCT_COUNTING_DIRECTION_SHIFT, | 561 | 0x1 << NI_GPCT_COUNTING_DIRECTION_SHIFT, |
562 | NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS = | 562 | NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS = |
563 | 0x2 << NI_GPCT_COUNTING_DIRECTION_SHIFT, | 563 | 0x2 << NI_GPCT_COUNTING_DIRECTION_SHIFT, |
564 | NI_GPCT_COUNTING_DIRECTION_HW_GATE_BITS = | 564 | NI_GPCT_COUNTING_DIRECTION_HW_GATE_BITS = |
565 | 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, | 565 | 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT, |
566 | NI_GPCT_RELOAD_SOURCE_MASK = 0xc000000, | 566 | NI_GPCT_RELOAD_SOURCE_MASK = 0xc000000, |
567 | NI_GPCT_RELOAD_SOURCE_FIXED_BITS = 0x0, | 567 | NI_GPCT_RELOAD_SOURCE_FIXED_BITS = 0x0, |
568 | NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS = 0x4000000, | 568 | NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS = 0x4000000, |
569 | NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS = 0x8000000, | 569 | NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS = 0x8000000, |
570 | NI_GPCT_OR_GATE_BIT = 0x10000000, | 570 | NI_GPCT_OR_GATE_BIT = 0x10000000, |
571 | NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 | 571 | NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 |
572 | }; | 572 | }; |
573 | 573 | ||
574 | /* Bits for setting a clock source with | 574 | /* Bits for setting a clock source with |
575 | * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ | 575 | * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ |
576 | enum ni_gpct_clock_source_bits { | 576 | enum ni_gpct_clock_source_bits { |
577 | NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, | 577 | NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, |
578 | NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, | 578 | NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, |
579 | NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1, | 579 | NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1, |
580 | NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2, | 580 | NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2, |
581 | NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3, | 581 | NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3, |
582 | NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4, | 582 | NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4, |
583 | NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5, | 583 | NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5, |
584 | NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, /* NI 660x-specific */ | 584 | NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, /* NI 660x-specific */ |
585 | NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7, | 585 | NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7, |
586 | NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8, | 586 | NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8, |
587 | NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9, | 587 | NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9, |
588 | NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000, | 588 | NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000, |
589 | NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0, | 589 | NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0, |
590 | NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, /* divide source by 2 */ | 590 | NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, /* divide source by 2 */ |
591 | NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, /* divide source by 8 */ | 591 | NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, /* divide source by 8 */ |
592 | NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 | 592 | NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 |
593 | }; | 593 | }; |
594 | static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) | 594 | static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) |
595 | { | 595 | { |
596 | /* NI 660x-specific */ | 596 | /* NI 660x-specific */ |
597 | return 0x10 + n; | 597 | return 0x10 + n; |
598 | } | 598 | } |
599 | static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) | 599 | static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) |
600 | { | 600 | { |
601 | return 0x18 + n; | 601 | return 0x18 + n; |
602 | } | 602 | } |
603 | static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) | 603 | static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) |
604 | { | 604 | { |
605 | /* no pfi on NI 660x */ | 605 | /* no pfi on NI 660x */ |
606 | return 0x20 + n; | 606 | return 0x20 + n; |
607 | } | 607 | } |
608 | 608 | ||
609 | /* Possibilities for setting a gate source with | 609 | /* Possibilities for setting a gate source with |
610 | INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. | 610 | INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. |
611 | May be bitwise-or'd with CR_EDGE or CR_INVERT. */ | 611 | May be bitwise-or'd with CR_EDGE or CR_INVERT. */ |
612 | enum ni_gpct_gate_select { | 612 | enum ni_gpct_gate_select { |
613 | /* m-series gates */ | 613 | /* m-series gates */ |
614 | NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, | 614 | NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, |
615 | NI_GPCT_AI_START2_GATE_SELECT = 0x12, | 615 | NI_GPCT_AI_START2_GATE_SELECT = 0x12, |
616 | NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13, | 616 | NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13, |
617 | NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14, | 617 | NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14, |
618 | NI_GPCT_AI_START1_GATE_SELECT = 0x1c, | 618 | NI_GPCT_AI_START1_GATE_SELECT = 0x1c, |
619 | NI_GPCT_NEXT_SOURCE_GATE_SELECT = 0x1d, | 619 | NI_GPCT_NEXT_SOURCE_GATE_SELECT = 0x1d, |
620 | NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT = 0x1e, | 620 | NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT = 0x1e, |
621 | NI_GPCT_LOGIC_LOW_GATE_SELECT = 0x1f, | 621 | NI_GPCT_LOGIC_LOW_GATE_SELECT = 0x1f, |
622 | /* more gates for 660x */ | 622 | /* more gates for 660x */ |
623 | NI_GPCT_SOURCE_PIN_i_GATE_SELECT = 0x100, | 623 | NI_GPCT_SOURCE_PIN_i_GATE_SELECT = 0x100, |
624 | NI_GPCT_GATE_PIN_i_GATE_SELECT = 0x101, | 624 | NI_GPCT_GATE_PIN_i_GATE_SELECT = 0x101, |
625 | /* more gates for 660x "second gate" */ | 625 | /* more gates for 660x "second gate" */ |
626 | NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, | 626 | NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, |
627 | NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, | 627 | NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, |
628 | /* m-series "second gate" sources are unknown, | 628 | /* m-series "second gate" sources are unknown, |
629 | we should add them here with an offset of 0x300 when known. */ | 629 | we should add them here with an offset of 0x300 when known. */ |
630 | NI_GPCT_DISABLED_GATE_SELECT = 0x8000, | 630 | NI_GPCT_DISABLED_GATE_SELECT = 0x8000, |
631 | }; | 631 | }; |
632 | static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) | 632 | static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) |
633 | { | 633 | { |
634 | return 0x102 + n; | 634 | return 0x102 + n; |
635 | } | 635 | } |
636 | static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) | 636 | static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) |
637 | { | 637 | { |
638 | return NI_USUAL_RTSI_SELECT(n); | 638 | return NI_USUAL_RTSI_SELECT(n); |
639 | } | 639 | } |
640 | static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) | 640 | static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) |
641 | { | 641 | { |
642 | return NI_USUAL_PFI_SELECT(n); | 642 | return NI_USUAL_PFI_SELECT(n); |
643 | } | 643 | } |
644 | static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) | 644 | static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) |
645 | { | 645 | { |
646 | return 0x202 + n; | 646 | return 0x202 + n; |
647 | } | 647 | } |
648 | 648 | ||
649 | /* Possibilities for setting a source with | 649 | /* Possibilities for setting a source with |
650 | INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ | 650 | INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ |
651 | enum ni_gpct_other_index { | 651 | enum ni_gpct_other_index { |
652 | NI_GPCT_SOURCE_ENCODER_A, | 652 | NI_GPCT_SOURCE_ENCODER_A, |
653 | NI_GPCT_SOURCE_ENCODER_B, | 653 | NI_GPCT_SOURCE_ENCODER_B, |
654 | NI_GPCT_SOURCE_ENCODER_Z | 654 | NI_GPCT_SOURCE_ENCODER_Z |
655 | }; | 655 | }; |
656 | enum ni_gpct_other_select { | 656 | enum ni_gpct_other_select { |
657 | /* m-series gates */ | 657 | /* m-series gates */ |
658 | /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */ | 658 | /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */ |
659 | NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, | 659 | NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, |
660 | }; | 660 | }; |
661 | static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) | 661 | static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) |
662 | { | 662 | { |
663 | return NI_USUAL_PFI_SELECT(n); | 663 | return NI_USUAL_PFI_SELECT(n); |
664 | } | 664 | } |
665 | 665 | ||
666 | /* start sources for ni general-purpose counters for use with | 666 | /* start sources for ni general-purpose counters for use with |
667 | INSN_CONFIG_ARM */ | 667 | INSN_CONFIG_ARM */ |
668 | enum ni_gpct_arm_source { | 668 | enum ni_gpct_arm_source { |
669 | NI_GPCT_ARM_IMMEDIATE = 0x0, | 669 | NI_GPCT_ARM_IMMEDIATE = 0x0, |
670 | NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter and | 670 | NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter and |
671 | the adjacent paired counter | 671 | the adjacent paired counter |
672 | simultaneously */ | 672 | simultaneously */ |
673 | /* NI doesn't document bits for selecting hardware arm triggers. If | 673 | /* NI doesn't document bits for selecting hardware arm triggers. If |
674 | * the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least | 674 | * the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least |
675 | * significant bits (3 bits for 660x or 5 bits for m-series) through to | 675 | * significant bits (3 bits for 660x or 5 bits for m-series) through to |
676 | * the hardware. This will at least allow someone to figure out what | 676 | * the hardware. This will at least allow someone to figure out what |
677 | * the bits do later. */ | 677 | * the bits do later. */ |
678 | NI_GPCT_ARM_UNKNOWN = 0x1000, | 678 | NI_GPCT_ARM_UNKNOWN = 0x1000, |
679 | }; | 679 | }; |
680 | 680 | ||
681 | /* digital filtering options for ni 660x for use with INSN_CONFIG_FILTER. */ | 681 | /* digital filtering options for ni 660x for use with INSN_CONFIG_FILTER. */ |
682 | enum ni_gpct_filter_select { | 682 | enum ni_gpct_filter_select { |
683 | NI_GPCT_FILTER_OFF = 0x0, | 683 | NI_GPCT_FILTER_OFF = 0x0, |
684 | NI_GPCT_FILTER_TIMEBASE_3_SYNC = 0x1, | 684 | NI_GPCT_FILTER_TIMEBASE_3_SYNC = 0x1, |
685 | NI_GPCT_FILTER_100x_TIMEBASE_1 = 0x2, | 685 | NI_GPCT_FILTER_100x_TIMEBASE_1 = 0x2, |
686 | NI_GPCT_FILTER_20x_TIMEBASE_1 = 0x3, | 686 | NI_GPCT_FILTER_20x_TIMEBASE_1 = 0x3, |
687 | NI_GPCT_FILTER_10x_TIMEBASE_1 = 0x4, | 687 | NI_GPCT_FILTER_10x_TIMEBASE_1 = 0x4, |
688 | NI_GPCT_FILTER_2x_TIMEBASE_1 = 0x5, | 688 | NI_GPCT_FILTER_2x_TIMEBASE_1 = 0x5, |
689 | NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 | 689 | NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 |
690 | }; | 690 | }; |
691 | 691 | ||
692 | /* PFI digital filtering options for ni m-series for use with | 692 | /* PFI digital filtering options for ni m-series for use with |
693 | * INSN_CONFIG_FILTER. */ | 693 | * INSN_CONFIG_FILTER. */ |
694 | enum ni_pfi_filter_select { | 694 | enum ni_pfi_filter_select { |
695 | NI_PFI_FILTER_OFF = 0x0, | 695 | NI_PFI_FILTER_OFF = 0x0, |
696 | NI_PFI_FILTER_125ns = 0x1, | 696 | NI_PFI_FILTER_125ns = 0x1, |
697 | NI_PFI_FILTER_6425ns = 0x2, | 697 | NI_PFI_FILTER_6425ns = 0x2, |
698 | NI_PFI_FILTER_2550us = 0x3 | 698 | NI_PFI_FILTER_2550us = 0x3 |
699 | }; | 699 | }; |
700 | 700 | ||
701 | /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ | 701 | /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ |
702 | enum ni_mio_clock_source { | 702 | enum ni_mio_clock_source { |
703 | NI_MIO_INTERNAL_CLOCK = 0, | 703 | NI_MIO_INTERNAL_CLOCK = 0, |
704 | NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use | 704 | NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use |
705 | NI_MIO_PLL_RTSI_CLOCK() */ | 705 | NI_MIO_PLL_RTSI_CLOCK() */ |
706 | /* the NI_MIO_PLL_* sources are m-series only */ | 706 | /* the NI_MIO_PLL_* sources are m-series only */ |
707 | NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, | 707 | NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, |
708 | NI_MIO_PLL_PXI10_CLOCK = 3, | 708 | NI_MIO_PLL_PXI10_CLOCK = 3, |
709 | NI_MIO_PLL_RTSI0_CLOCK = 4 | 709 | NI_MIO_PLL_RTSI0_CLOCK = 4 |
710 | }; | 710 | }; |
711 | static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) | 711 | static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) |
712 | { | 712 | { |
713 | return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel; | 713 | return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel; |
714 | } | 714 | } |
715 | 715 | ||
716 | /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. | 716 | /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. |
717 | The numbers assigned are not arbitrary, they correspond to the bits required | 717 | The numbers assigned are not arbitrary, they correspond to the bits required |
718 | to program the board. */ | 718 | to program the board. */ |
719 | enum ni_rtsi_routing { | 719 | enum ni_rtsi_routing { |
720 | NI_RTSI_OUTPUT_ADR_START1 = 0, | 720 | NI_RTSI_OUTPUT_ADR_START1 = 0, |
721 | NI_RTSI_OUTPUT_ADR_START2 = 1, | 721 | NI_RTSI_OUTPUT_ADR_START2 = 1, |
722 | NI_RTSI_OUTPUT_SCLKG = 2, | 722 | NI_RTSI_OUTPUT_SCLKG = 2, |
723 | NI_RTSI_OUTPUT_DACUPDN = 3, | 723 | NI_RTSI_OUTPUT_DACUPDN = 3, |
724 | NI_RTSI_OUTPUT_DA_START1 = 4, | 724 | NI_RTSI_OUTPUT_DA_START1 = 4, |
725 | NI_RTSI_OUTPUT_G_SRC0 = 5, | 725 | NI_RTSI_OUTPUT_G_SRC0 = 5, |
726 | NI_RTSI_OUTPUT_G_GATE0 = 6, | 726 | NI_RTSI_OUTPUT_G_GATE0 = 6, |
727 | NI_RTSI_OUTPUT_RGOUT0 = 7, | 727 | NI_RTSI_OUTPUT_RGOUT0 = 7, |
728 | NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, | 728 | NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, |
729 | NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI clock | 729 | NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI clock |
730 | on line 7 */ | 730 | on line 7 */ |
731 | }; | 731 | }; |
732 | static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) | 732 | static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) |
733 | { | 733 | { |
734 | return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; | 734 | return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; |
735 | } | 735 | } |
736 | 736 | ||
737 | /* Signals which can be routed to an NI PFI pin on an m-series board with | 737 | /* Signals which can be routed to an NI PFI pin on an m-series board with |
738 | * INSN_CONFIG_SET_ROUTING. These numbers are also returned by | 738 | * INSN_CONFIG_SET_ROUTING. These numbers are also returned by |
739 | * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing | 739 | * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing |
740 | * cannot be changed. The numbers assigned are not arbitrary, they correspond | 740 | * cannot be changed. The numbers assigned are not arbitrary, they correspond |
741 | * to the bits required to program the board. */ | 741 | * to the bits required to program the board. */ |
742 | enum ni_pfi_routing { | 742 | enum ni_pfi_routing { |
743 | NI_PFI_OUTPUT_PFI_DEFAULT = 0, | 743 | NI_PFI_OUTPUT_PFI_DEFAULT = 0, |
744 | NI_PFI_OUTPUT_AI_START1 = 1, | 744 | NI_PFI_OUTPUT_AI_START1 = 1, |
745 | NI_PFI_OUTPUT_AI_START2 = 2, | 745 | NI_PFI_OUTPUT_AI_START2 = 2, |
746 | NI_PFI_OUTPUT_AI_CONVERT = 3, | 746 | NI_PFI_OUTPUT_AI_CONVERT = 3, |
747 | NI_PFI_OUTPUT_G_SRC1 = 4, | 747 | NI_PFI_OUTPUT_G_SRC1 = 4, |
748 | NI_PFI_OUTPUT_G_GATE1 = 5, | 748 | NI_PFI_OUTPUT_G_GATE1 = 5, |
749 | NI_PFI_OUTPUT_AO_UPDATE_N = 6, | 749 | NI_PFI_OUTPUT_AO_UPDATE_N = 6, |
750 | NI_PFI_OUTPUT_AO_START1 = 7, | 750 | NI_PFI_OUTPUT_AO_START1 = 7, |
751 | NI_PFI_OUTPUT_AI_START_PULSE = 8, | 751 | NI_PFI_OUTPUT_AI_START_PULSE = 8, |
752 | NI_PFI_OUTPUT_G_SRC0 = 9, | 752 | NI_PFI_OUTPUT_G_SRC0 = 9, |
753 | NI_PFI_OUTPUT_G_GATE0 = 10, | 753 | NI_PFI_OUTPUT_G_GATE0 = 10, |
754 | NI_PFI_OUTPUT_EXT_STROBE = 11, | 754 | NI_PFI_OUTPUT_EXT_STROBE = 11, |
755 | NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12, | 755 | NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12, |
756 | NI_PFI_OUTPUT_GOUT0 = 13, | 756 | NI_PFI_OUTPUT_GOUT0 = 13, |
757 | NI_PFI_OUTPUT_GOUT1 = 14, | 757 | NI_PFI_OUTPUT_GOUT1 = 14, |
758 | NI_PFI_OUTPUT_FREQ_OUT = 15, | 758 | NI_PFI_OUTPUT_FREQ_OUT = 15, |
759 | NI_PFI_OUTPUT_PFI_DO = 16, | 759 | NI_PFI_OUTPUT_PFI_DO = 16, |
760 | NI_PFI_OUTPUT_I_ATRIG = 17, | 760 | NI_PFI_OUTPUT_I_ATRIG = 17, |
761 | NI_PFI_OUTPUT_RTSI0 = 18, | 761 | NI_PFI_OUTPUT_RTSI0 = 18, |
762 | NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26, | 762 | NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26, |
763 | NI_PFI_OUTPUT_SCXI_TRIG1 = 27, | 763 | NI_PFI_OUTPUT_SCXI_TRIG1 = 27, |
764 | NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28, | 764 | NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28, |
765 | NI_PFI_OUTPUT_CDI_SAMPLE = 29, | 765 | NI_PFI_OUTPUT_CDI_SAMPLE = 29, |
766 | NI_PFI_OUTPUT_CDO_UPDATE = 30 | 766 | NI_PFI_OUTPUT_CDO_UPDATE = 30 |
767 | }; | 767 | }; |
768 | static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) | 768 | static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) |
769 | { | 769 | { |
770 | return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; | 770 | return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; |
771 | } | 771 | } |
772 | 772 | ||
773 | /* Signals which can be routed to output on a NI PFI pin on a 660x board | 773 | /* Signals which can be routed to output on a NI PFI pin on a 660x board |
774 | with INSN_CONFIG_SET_ROUTING. The numbers assigned are | 774 | with INSN_CONFIG_SET_ROUTING. The numbers assigned are |
775 | not arbitrary, they correspond to the bits required | 775 | not arbitrary, they correspond to the bits required |
776 | to program the board. Lines 0 to 7 can only be set to | 776 | to program the board. Lines 0 to 7 can only be set to |
777 | NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to | 777 | NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to |
778 | NI_660X_PFI_OUTPUT_COUNTER. */ | 778 | NI_660X_PFI_OUTPUT_COUNTER. */ |
779 | enum ni_660x_pfi_routing { | 779 | enum ni_660x_pfi_routing { |
780 | NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ | 780 | NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ |
781 | NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ | 781 | NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ |
782 | }; | 782 | }; |
783 | 783 | ||
784 | /* NI External Trigger lines. These values are not arbitrary, but are related | 784 | /* NI External Trigger lines. These values are not arbitrary, but are related |
785 | * to the bits required to program the board (offset by 1 for historical | 785 | * to the bits required to program the board (offset by 1 for historical |
786 | * reasons). */ | 786 | * reasons). */ |
787 | static inline unsigned NI_EXT_PFI(unsigned pfi_channel) | 787 | static inline unsigned NI_EXT_PFI(unsigned pfi_channel) |
788 | { | 788 | { |
789 | return NI_USUAL_PFI_SELECT(pfi_channel) - 1; | 789 | return NI_USUAL_PFI_SELECT(pfi_channel) - 1; |
790 | } | 790 | } |
791 | static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) | 791 | static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) |
792 | { | 792 | { |
793 | return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1; | 793 | return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1; |
794 | } | 794 | } |
795 | 795 | ||
796 | /* status bits for INSN_CONFIG_GET_COUNTER_STATUS */ | 796 | /* status bits for INSN_CONFIG_GET_COUNTER_STATUS */ |
797 | enum comedi_counter_status_flags { | 797 | enum comedi_counter_status_flags { |
798 | COMEDI_COUNTER_ARMED = 0x1, | 798 | COMEDI_COUNTER_ARMED = 0x1, |
799 | COMEDI_COUNTER_COUNTING = 0x2, | 799 | COMEDI_COUNTER_COUNTING = 0x2, |
800 | COMEDI_COUNTER_TERMINAL_COUNT = 0x4, | 800 | COMEDI_COUNTER_TERMINAL_COUNT = 0x4, |
801 | }; | 801 | }; |
802 | 802 | ||
803 | /* Clock sources for CDIO subdevice on NI m-series boards. Used as the | 803 | /* Clock sources for CDIO subdevice on NI m-series boards. Used as the |
804 | * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd | 804 | * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd |
805 | * with CR_INVERT to change polarity. */ | 805 | * with CR_INVERT to change polarity. */ |
806 | enum ni_m_series_cdio_scan_begin_src { | 806 | enum ni_m_series_cdio_scan_begin_src { |
807 | NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, | 807 | NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, |
808 | NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, | 808 | NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, |
809 | NI_CDIO_SCAN_BEGIN_SRC_AI_CONVERT = 19, | 809 | NI_CDIO_SCAN_BEGIN_SRC_AI_CONVERT = 19, |
810 | NI_CDIO_SCAN_BEGIN_SRC_PXI_STAR_TRIGGER = 20, | 810 | NI_CDIO_SCAN_BEGIN_SRC_PXI_STAR_TRIGGER = 20, |
811 | NI_CDIO_SCAN_BEGIN_SRC_G0_OUT = 28, | 811 | NI_CDIO_SCAN_BEGIN_SRC_G0_OUT = 28, |
812 | NI_CDIO_SCAN_BEGIN_SRC_G1_OUT = 29, | 812 | NI_CDIO_SCAN_BEGIN_SRC_G1_OUT = 29, |
813 | NI_CDIO_SCAN_BEGIN_SRC_ANALOG_TRIGGER = 30, | 813 | NI_CDIO_SCAN_BEGIN_SRC_ANALOG_TRIGGER = 30, |
814 | NI_CDIO_SCAN_BEGIN_SRC_AO_UPDATE = 31, | 814 | NI_CDIO_SCAN_BEGIN_SRC_AO_UPDATE = 31, |
815 | NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32, | 815 | NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32, |
816 | NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33 | 816 | NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33 |
817 | }; | 817 | }; |
818 | static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) | 818 | static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) |
819 | { | 819 | { |
820 | return NI_USUAL_PFI_SELECT(pfi_channel); | 820 | return NI_USUAL_PFI_SELECT(pfi_channel); |
821 | } | 821 | } |
822 | static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) | 822 | static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) |
823 | { | 823 | { |
824 | return NI_USUAL_RTSI_SELECT(rtsi_channel); | 824 | return NI_USUAL_RTSI_SELECT(rtsi_channel); |
825 | } | 825 | } |
826 | 826 | ||
827 | /* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI | 827 | /* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI |
828 | * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to | 828 | * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to |
829 | * change polarity. */ | 829 | * change polarity. */ |
830 | static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) | 830 | static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) |
831 | { | 831 | { |
832 | return NI_USUAL_PFI_SELECT(pfi_channel); | 832 | return NI_USUAL_PFI_SELECT(pfi_channel); |
833 | } | 833 | } |
834 | static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) | 834 | static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) |
835 | { | 835 | { |
836 | return NI_USUAL_RTSI_SELECT(rtsi_channel); | 836 | return NI_USUAL_RTSI_SELECT(rtsi_channel); |
837 | } | 837 | } |
838 | 838 | ||
839 | /* Bits for setting a clock source with | 839 | /* Bits for setting a clock source with |
840 | * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ | 840 | * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ |
841 | enum ni_freq_out_clock_source_bits { | 841 | enum ni_freq_out_clock_source_bits { |
842 | NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ | 842 | NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ |
843 | NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ | 843 | NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ |
844 | }; | 844 | }; |
845 | 845 | ||
846 | /* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for | 846 | /* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for |
847 | * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ | 847 | * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ |
848 | enum amplc_dio_clock_source { | 848 | enum amplc_dio_clock_source { |
849 | AMPLC_DIO_CLK_CLKN, /* per channel external clock | 849 | AMPLC_DIO_CLK_CLKN, /* per channel external clock |
850 | input/output pin (pin is only an | 850 | input/output pin (pin is only an |
851 | input when clock source set to this | 851 | input when clock source set to this |
852 | value, otherwise it is an output) */ | 852 | value, otherwise it is an output) */ |
853 | AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ | 853 | AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ |
854 | AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ | 854 | AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ |
855 | AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ | 855 | AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ |
856 | AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ | 856 | AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ |
857 | AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ | 857 | AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ |
858 | AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel | 858 | AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel |
859 | (for channel 0, preceding counter | 859 | (for channel 0, preceding counter |
860 | channel is channel 2 on preceding | 860 | channel is channel 2 on preceding |
861 | counter subdevice, for first counter | 861 | counter subdevice, for first counter |
862 | subdevice, preceding counter | 862 | subdevice, preceding counter |
863 | subdevice is the last counter | 863 | subdevice is the last counter |
864 | subdevice) */ | 864 | subdevice) */ |
865 | AMPLC_DIO_CLK_EXT /* per chip external input pin */ | 865 | AMPLC_DIO_CLK_EXT /* per chip external input pin */ |
866 | }; | 866 | }; |
867 | 867 | ||
868 | /* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for | 868 | /* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for |
869 | * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ | 869 | * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ |
870 | enum amplc_dio_gate_source { | 870 | enum amplc_dio_gate_source { |
871 | AMPLC_DIO_GAT_VCC, /* internal high logic level */ | 871 | AMPLC_DIO_GAT_VCC, /* internal high logic level */ |
872 | AMPLC_DIO_GAT_GND, /* internal low logic level */ | 872 | AMPLC_DIO_GAT_GND, /* internal low logic level */ |
873 | AMPLC_DIO_GAT_GATN, /* per channel external gate input */ | 873 | AMPLC_DIO_GAT_GATN, /* per channel external gate input */ |
874 | AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel | 874 | AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel |
875 | minus 2 (for channels 0 or 1, | 875 | minus 2 (for channels 0 or 1, |
876 | channel minus 2 is channel 1 or 2 on | 876 | channel minus 2 is channel 1 or 2 on |
877 | the preceding counter subdevice, for | 877 | the preceding counter subdevice, for |
878 | the first counter subdevice the | 878 | the first counter subdevice the |
879 | preceding counter subdevice is the | 879 | preceding counter subdevice is the |
880 | last counter subdevice) */ | 880 | last counter subdevice) */ |
881 | AMPLC_DIO_GAT_RESERVED4, | 881 | AMPLC_DIO_GAT_RESERVED4, |
882 | AMPLC_DIO_GAT_RESERVED5, | 882 | AMPLC_DIO_GAT_RESERVED5, |
883 | AMPLC_DIO_GAT_RESERVED6, | 883 | AMPLC_DIO_GAT_RESERVED6, |
884 | AMPLC_DIO_GAT_RESERVED7 | 884 | AMPLC_DIO_GAT_RESERVED7 |
885 | }; | 885 | }; |
886 | 886 | ||
887 | #endif /* _COMEDI_H */ | 887 | #endif /* _COMEDI_H */ |
888 | 888 |
drivers/staging/comedi/comedi_compat32.c
1 | /* | 1 | /* |
2 | comedi/comedi_compat32.c | 2 | comedi/comedi_compat32.c |
3 | 32-bit ioctl compatibility for 64-bit comedi kernel module. | 3 | 32-bit ioctl compatibility for 64-bit comedi kernel module. |
4 | 4 | ||
5 | Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> | 5 | Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> |
6 | Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> | 6 | Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> |
7 | 7 | ||
8 | COMEDI - Linux Control and Measurement Device Interface | 8 | COMEDI - Linux Control and Measurement Device Interface |
9 | Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> | 9 | Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> |
10 | 10 | ||
11 | This program is free software; you can redistribute it and/or modify | 11 | This program is free software; you can redistribute it and/or modify |
12 | it under the terms of the GNU General Public License as published by | 12 | it under the terms of the GNU General Public License as published by |
13 | the Free Software Foundation; either version 2 of the License, or | 13 | the Free Software Foundation; either version 2 of the License, or |
14 | (at your option) any later version. | 14 | (at your option) any later version. |
15 | 15 | ||
16 | This program is distributed in the hope that it will be useful, | 16 | This program is distributed in the hope that it will be useful, |
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | GNU General Public License for more details. | 19 | GNU General Public License for more details. |
20 | 20 | ||
21 | You should have received a copy of the GNU General Public License | 21 | You should have received a copy of the GNU General Public License |
22 | along with this program; if not, write to the Free Software | 22 | along with this program; if not, write to the Free Software |
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
24 | 24 | ||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define __NO_VERSION__ | 27 | #define __NO_VERSION__ |
28 | #include "comedi.h" | ||
29 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
30 | 29 | #include "comedi.h" | |
31 | #include "comedi_compat32.h" | 30 | #include "comedi_compat32.h" |
32 | 31 | ||
33 | #ifdef CONFIG_COMPAT | 32 | #ifdef CONFIG_COMPAT |
34 | 33 | ||
35 | #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct) | 34 | #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct) |
36 | #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct) | 35 | #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct) |
37 | /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. | 36 | /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. |
38 | * It's too late to change it now, but it only affects the command number. */ | 37 | * It's too late to change it now, but it only affects the command number. */ |
39 | #define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct) | 38 | #define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct) |
40 | /* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. | 39 | /* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. |
41 | * It's too late to change it now, but it only affects the command number. */ | 40 | * It's too late to change it now, but it only affects the command number. */ |
42 | #define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct) | 41 | #define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct) |
43 | #define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct) | 42 | #define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct) |
44 | #define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct) | 43 | #define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct) |
45 | 44 | ||
46 | struct comedi32_chaninfo_struct { | 45 | struct comedi32_chaninfo_struct { |
47 | unsigned int subdev; | 46 | unsigned int subdev; |
48 | compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */ | 47 | compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */ |
49 | compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ | 48 | compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ |
50 | compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */ | 49 | compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */ |
51 | unsigned int unused[4]; | 50 | unsigned int unused[4]; |
52 | }; | 51 | }; |
53 | 52 | ||
54 | struct comedi32_rangeinfo_struct { | 53 | struct comedi32_rangeinfo_struct { |
55 | unsigned int range_type; | 54 | unsigned int range_type; |
56 | compat_uptr_t range_ptr; /* 32-bit 'void *' */ | 55 | compat_uptr_t range_ptr; /* 32-bit 'void *' */ |
57 | }; | 56 | }; |
58 | 57 | ||
59 | struct comedi32_cmd_struct { | 58 | struct comedi32_cmd_struct { |
60 | unsigned int subdev; | 59 | unsigned int subdev; |
61 | unsigned int flags; | 60 | unsigned int flags; |
62 | unsigned int start_src; | 61 | unsigned int start_src; |
63 | unsigned int start_arg; | 62 | unsigned int start_arg; |
64 | unsigned int scan_begin_src; | 63 | unsigned int scan_begin_src; |
65 | unsigned int scan_begin_arg; | 64 | unsigned int scan_begin_arg; |
66 | unsigned int convert_src; | 65 | unsigned int convert_src; |
67 | unsigned int convert_arg; | 66 | unsigned int convert_arg; |
68 | unsigned int scan_end_src; | 67 | unsigned int scan_end_src; |
69 | unsigned int scan_end_arg; | 68 | unsigned int scan_end_arg; |
70 | unsigned int stop_src; | 69 | unsigned int stop_src; |
71 | unsigned int stop_arg; | 70 | unsigned int stop_arg; |
72 | compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ | 71 | compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ |
73 | unsigned int chanlist_len; | 72 | unsigned int chanlist_len; |
74 | compat_uptr_t data; /* 32-bit 'short *' */ | 73 | compat_uptr_t data; /* 32-bit 'short *' */ |
75 | unsigned int data_len; | 74 | unsigned int data_len; |
76 | }; | 75 | }; |
77 | 76 | ||
78 | struct comedi32_insn_struct { | 77 | struct comedi32_insn_struct { |
79 | unsigned int insn; | 78 | unsigned int insn; |
80 | unsigned int n; | 79 | unsigned int n; |
81 | compat_uptr_t data; /* 32-bit 'unsigned int *' */ | 80 | compat_uptr_t data; /* 32-bit 'unsigned int *' */ |
82 | unsigned int subdev; | 81 | unsigned int subdev; |
83 | unsigned int chanspec; | 82 | unsigned int chanspec; |
84 | unsigned int unused[3]; | 83 | unsigned int unused[3]; |
85 | }; | 84 | }; |
86 | 85 | ||
87 | struct comedi32_insnlist_struct { | 86 | struct comedi32_insnlist_struct { |
88 | unsigned int n_insns; | 87 | unsigned int n_insns; |
89 | compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ | 88 | compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ |
90 | }; | 89 | }; |
91 | 90 | ||
92 | /* Handle translated ioctl. */ | 91 | /* Handle translated ioctl. */ |
93 | static int translated_ioctl(struct file *file, unsigned int cmd, | 92 | static int translated_ioctl(struct file *file, unsigned int cmd, |
94 | unsigned long arg) | 93 | unsigned long arg) |
95 | { | 94 | { |
96 | if (!file->f_op) | 95 | if (!file->f_op) |
97 | return -ENOTTY; | 96 | return -ENOTTY; |
98 | 97 | ||
99 | if (file->f_op->unlocked_ioctl) | 98 | if (file->f_op->unlocked_ioctl) |
100 | return file->f_op->unlocked_ioctl(file, cmd, arg); | 99 | return file->f_op->unlocked_ioctl(file, cmd, arg); |
101 | 100 | ||
102 | return -ENOTTY; | 101 | return -ENOTTY; |
103 | } | 102 | } |
104 | 103 | ||
105 | /* Handle 32-bit COMEDI_CHANINFO ioctl. */ | 104 | /* Handle 32-bit COMEDI_CHANINFO ioctl. */ |
106 | static int compat_chaninfo(struct file *file, unsigned long arg) | 105 | static int compat_chaninfo(struct file *file, unsigned long arg) |
107 | { | 106 | { |
108 | struct comedi_chaninfo __user *chaninfo; | 107 | struct comedi_chaninfo __user *chaninfo; |
109 | struct comedi32_chaninfo_struct __user *chaninfo32; | 108 | struct comedi32_chaninfo_struct __user *chaninfo32; |
110 | int err; | 109 | int err; |
111 | union { | 110 | union { |
112 | unsigned int uint; | 111 | unsigned int uint; |
113 | compat_uptr_t uptr; | 112 | compat_uptr_t uptr; |
114 | } temp; | 113 | } temp; |
115 | 114 | ||
116 | chaninfo32 = compat_ptr(arg); | 115 | chaninfo32 = compat_ptr(arg); |
117 | chaninfo = compat_alloc_user_space(sizeof(*chaninfo)); | 116 | chaninfo = compat_alloc_user_space(sizeof(*chaninfo)); |
118 | 117 | ||
119 | /* Copy chaninfo structure. Ignore unused members. */ | 118 | /* Copy chaninfo structure. Ignore unused members. */ |
120 | if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32)) | 119 | if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32)) |
121 | || !access_ok(VERIFY_WRITE, chaninfo, sizeof(*chaninfo))) { | 120 | || !access_ok(VERIFY_WRITE, chaninfo, sizeof(*chaninfo))) { |
122 | return -EFAULT; | 121 | return -EFAULT; |
123 | } | 122 | } |
124 | err = 0; | 123 | err = 0; |
125 | err |= __get_user(temp.uint, &chaninfo32->subdev); | 124 | err |= __get_user(temp.uint, &chaninfo32->subdev); |
126 | err |= __put_user(temp.uint, &chaninfo->subdev); | 125 | err |= __put_user(temp.uint, &chaninfo->subdev); |
127 | err |= __get_user(temp.uptr, &chaninfo32->maxdata_list); | 126 | err |= __get_user(temp.uptr, &chaninfo32->maxdata_list); |
128 | err |= __put_user(compat_ptr(temp.uptr), &chaninfo->maxdata_list); | 127 | err |= __put_user(compat_ptr(temp.uptr), &chaninfo->maxdata_list); |
129 | err |= __get_user(temp.uptr, &chaninfo32->flaglist); | 128 | err |= __get_user(temp.uptr, &chaninfo32->flaglist); |
130 | err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist); | 129 | err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist); |
131 | err |= __get_user(temp.uptr, &chaninfo32->rangelist); | 130 | err |= __get_user(temp.uptr, &chaninfo32->rangelist); |
132 | err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist); | 131 | err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist); |
133 | if (err) | 132 | if (err) |
134 | return -EFAULT; | 133 | return -EFAULT; |
135 | 134 | ||
136 | return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo); | 135 | return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo); |
137 | } | 136 | } |
138 | 137 | ||
139 | /* Handle 32-bit COMEDI_RANGEINFO ioctl. */ | 138 | /* Handle 32-bit COMEDI_RANGEINFO ioctl. */ |
140 | static int compat_rangeinfo(struct file *file, unsigned long arg) | 139 | static int compat_rangeinfo(struct file *file, unsigned long arg) |
141 | { | 140 | { |
142 | struct comedi_rangeinfo __user *rangeinfo; | 141 | struct comedi_rangeinfo __user *rangeinfo; |
143 | struct comedi32_rangeinfo_struct __user *rangeinfo32; | 142 | struct comedi32_rangeinfo_struct __user *rangeinfo32; |
144 | int err; | 143 | int err; |
145 | union { | 144 | union { |
146 | unsigned int uint; | 145 | unsigned int uint; |
147 | compat_uptr_t uptr; | 146 | compat_uptr_t uptr; |
148 | } temp; | 147 | } temp; |
149 | 148 | ||
150 | rangeinfo32 = compat_ptr(arg); | 149 | rangeinfo32 = compat_ptr(arg); |
151 | rangeinfo = compat_alloc_user_space(sizeof(*rangeinfo)); | 150 | rangeinfo = compat_alloc_user_space(sizeof(*rangeinfo)); |
152 | 151 | ||
153 | /* Copy rangeinfo structure. */ | 152 | /* Copy rangeinfo structure. */ |
154 | if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32)) | 153 | if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32)) |
155 | || !access_ok(VERIFY_WRITE, rangeinfo, sizeof(*rangeinfo))) { | 154 | || !access_ok(VERIFY_WRITE, rangeinfo, sizeof(*rangeinfo))) { |
156 | return -EFAULT; | 155 | return -EFAULT; |
157 | } | 156 | } |
158 | err = 0; | 157 | err = 0; |
159 | err |= __get_user(temp.uint, &rangeinfo32->range_type); | 158 | err |= __get_user(temp.uint, &rangeinfo32->range_type); |
160 | err |= __put_user(temp.uint, &rangeinfo->range_type); | 159 | err |= __put_user(temp.uint, &rangeinfo->range_type); |
161 | err |= __get_user(temp.uptr, &rangeinfo32->range_ptr); | 160 | err |= __get_user(temp.uptr, &rangeinfo32->range_ptr); |
162 | err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr); | 161 | err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr); |
163 | if (err) | 162 | if (err) |
164 | return -EFAULT; | 163 | return -EFAULT; |
165 | 164 | ||
166 | return translated_ioctl(file, COMEDI_RANGEINFO, | 165 | return translated_ioctl(file, COMEDI_RANGEINFO, |
167 | (unsigned long)rangeinfo); | 166 | (unsigned long)rangeinfo); |
168 | } | 167 | } |
169 | 168 | ||
170 | /* Copy 32-bit cmd structure to native cmd structure. */ | 169 | /* Copy 32-bit cmd structure to native cmd structure. */ |
171 | static int get_compat_cmd(struct comedi_cmd __user *cmd, | 170 | static int get_compat_cmd(struct comedi_cmd __user *cmd, |
172 | struct comedi32_cmd_struct __user *cmd32) | 171 | struct comedi32_cmd_struct __user *cmd32) |
173 | { | 172 | { |
174 | int err; | 173 | int err; |
175 | union { | 174 | union { |
176 | unsigned int uint; | 175 | unsigned int uint; |
177 | compat_uptr_t uptr; | 176 | compat_uptr_t uptr; |
178 | } temp; | 177 | } temp; |
179 | 178 | ||
180 | /* Copy cmd structure. */ | 179 | /* Copy cmd structure. */ |
181 | if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32)) | 180 | if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32)) |
182 | || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) { | 181 | || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) { |
183 | return -EFAULT; | 182 | return -EFAULT; |
184 | } | 183 | } |
185 | err = 0; | 184 | err = 0; |
186 | err |= __get_user(temp.uint, &cmd32->subdev); | 185 | err |= __get_user(temp.uint, &cmd32->subdev); |
187 | err |= __put_user(temp.uint, &cmd->subdev); | 186 | err |= __put_user(temp.uint, &cmd->subdev); |
188 | err |= __get_user(temp.uint, &cmd32->flags); | 187 | err |= __get_user(temp.uint, &cmd32->flags); |
189 | err |= __put_user(temp.uint, &cmd->flags); | 188 | err |= __put_user(temp.uint, &cmd->flags); |
190 | err |= __get_user(temp.uint, &cmd32->start_src); | 189 | err |= __get_user(temp.uint, &cmd32->start_src); |
191 | err |= __put_user(temp.uint, &cmd->start_src); | 190 | err |= __put_user(temp.uint, &cmd->start_src); |
192 | err |= __get_user(temp.uint, &cmd32->start_arg); | 191 | err |= __get_user(temp.uint, &cmd32->start_arg); |
193 | err |= __put_user(temp.uint, &cmd->start_arg); | 192 | err |= __put_user(temp.uint, &cmd->start_arg); |
194 | err |= __get_user(temp.uint, &cmd32->scan_begin_src); | 193 | err |= __get_user(temp.uint, &cmd32->scan_begin_src); |
195 | err |= __put_user(temp.uint, &cmd->scan_begin_src); | 194 | err |= __put_user(temp.uint, &cmd->scan_begin_src); |
196 | err |= __get_user(temp.uint, &cmd32->scan_begin_arg); | 195 | err |= __get_user(temp.uint, &cmd32->scan_begin_arg); |
197 | err |= __put_user(temp.uint, &cmd->scan_begin_arg); | 196 | err |= __put_user(temp.uint, &cmd->scan_begin_arg); |
198 | err |= __get_user(temp.uint, &cmd32->convert_src); | 197 | err |= __get_user(temp.uint, &cmd32->convert_src); |
199 | err |= __put_user(temp.uint, &cmd->convert_src); | 198 | err |= __put_user(temp.uint, &cmd->convert_src); |
200 | err |= __get_user(temp.uint, &cmd32->convert_arg); | 199 | err |= __get_user(temp.uint, &cmd32->convert_arg); |
201 | err |= __put_user(temp.uint, &cmd->convert_arg); | 200 | err |= __put_user(temp.uint, &cmd->convert_arg); |
202 | err |= __get_user(temp.uint, &cmd32->scan_end_src); | 201 | err |= __get_user(temp.uint, &cmd32->scan_end_src); |
203 | err |= __put_user(temp.uint, &cmd->scan_end_src); | 202 | err |= __put_user(temp.uint, &cmd->scan_end_src); |
204 | err |= __get_user(temp.uint, &cmd32->scan_end_arg); | 203 | err |= __get_user(temp.uint, &cmd32->scan_end_arg); |
205 | err |= __put_user(temp.uint, &cmd->scan_end_arg); | 204 | err |= __put_user(temp.uint, &cmd->scan_end_arg); |
206 | err |= __get_user(temp.uint, &cmd32->stop_src); | 205 | err |= __get_user(temp.uint, &cmd32->stop_src); |
207 | err |= __put_user(temp.uint, &cmd->stop_src); | 206 | err |= __put_user(temp.uint, &cmd->stop_src); |
208 | err |= __get_user(temp.uint, &cmd32->stop_arg); | 207 | err |= __get_user(temp.uint, &cmd32->stop_arg); |
209 | err |= __put_user(temp.uint, &cmd->stop_arg); | 208 | err |= __put_user(temp.uint, &cmd->stop_arg); |
210 | err |= __get_user(temp.uptr, &cmd32->chanlist); | 209 | err |= __get_user(temp.uptr, &cmd32->chanlist); |
211 | err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist); | 210 | err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist); |
212 | err |= __get_user(temp.uint, &cmd32->chanlist_len); | 211 | err |= __get_user(temp.uint, &cmd32->chanlist_len); |
213 | err |= __put_user(temp.uint, &cmd->chanlist_len); | 212 | err |= __put_user(temp.uint, &cmd->chanlist_len); |
214 | err |= __get_user(temp.uptr, &cmd32->data); | 213 | err |= __get_user(temp.uptr, &cmd32->data); |
215 | err |= __put_user(compat_ptr(temp.uptr), &cmd->data); | 214 | err |= __put_user(compat_ptr(temp.uptr), &cmd->data); |
216 | err |= __get_user(temp.uint, &cmd32->data_len); | 215 | err |= __get_user(temp.uint, &cmd32->data_len); |
217 | err |= __put_user(temp.uint, &cmd->data_len); | 216 | err |= __put_user(temp.uint, &cmd->data_len); |
218 | return err ? -EFAULT : 0; | 217 | return err ? -EFAULT : 0; |
219 | } | 218 | } |
220 | 219 | ||
221 | /* Copy native cmd structure to 32-bit cmd structure. */ | 220 | /* Copy native cmd structure to 32-bit cmd structure. */ |
222 | static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, | 221 | static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, |
223 | struct comedi_cmd __user *cmd) | 222 | struct comedi_cmd __user *cmd) |
224 | { | 223 | { |
225 | int err; | 224 | int err; |
226 | unsigned int temp; | 225 | unsigned int temp; |
227 | 226 | ||
228 | /* Copy back most of cmd structure. */ | 227 | /* Copy back most of cmd structure. */ |
229 | /* Assume the pointer values are already valid. */ | 228 | /* Assume the pointer values are already valid. */ |
230 | /* (Could use ptr_to_compat() to set them, but that wasn't implemented | 229 | /* (Could use ptr_to_compat() to set them, but that wasn't implemented |
231 | * until kernel version 2.6.11.) */ | 230 | * until kernel version 2.6.11.) */ |
232 | if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) | 231 | if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) |
233 | || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) { | 232 | || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) { |
234 | return -EFAULT; | 233 | return -EFAULT; |
235 | } | 234 | } |
236 | err = 0; | 235 | err = 0; |
237 | err |= __get_user(temp, &cmd->subdev); | 236 | err |= __get_user(temp, &cmd->subdev); |
238 | err |= __put_user(temp, &cmd32->subdev); | 237 | err |= __put_user(temp, &cmd32->subdev); |
239 | err |= __get_user(temp, &cmd->flags); | 238 | err |= __get_user(temp, &cmd->flags); |
240 | err |= __put_user(temp, &cmd32->flags); | 239 | err |= __put_user(temp, &cmd32->flags); |
241 | err |= __get_user(temp, &cmd->start_src); | 240 | err |= __get_user(temp, &cmd->start_src); |
242 | err |= __put_user(temp, &cmd32->start_src); | 241 | err |= __put_user(temp, &cmd32->start_src); |
243 | err |= __get_user(temp, &cmd->start_arg); | 242 | err |= __get_user(temp, &cmd->start_arg); |
244 | err |= __put_user(temp, &cmd32->start_arg); | 243 | err |= __put_user(temp, &cmd32->start_arg); |
245 | err |= __get_user(temp, &cmd->scan_begin_src); | 244 | err |= __get_user(temp, &cmd->scan_begin_src); |
246 | err |= __put_user(temp, &cmd32->scan_begin_src); | 245 | err |= __put_user(temp, &cmd32->scan_begin_src); |
247 | err |= __get_user(temp, &cmd->scan_begin_arg); | 246 | err |= __get_user(temp, &cmd->scan_begin_arg); |
248 | err |= __put_user(temp, &cmd32->scan_begin_arg); | 247 | err |= __put_user(temp, &cmd32->scan_begin_arg); |
249 | err |= __get_user(temp, &cmd->convert_src); | 248 | err |= __get_user(temp, &cmd->convert_src); |
250 | err |= __put_user(temp, &cmd32->convert_src); | 249 | err |= __put_user(temp, &cmd32->convert_src); |
251 | err |= __get_user(temp, &cmd->convert_arg); | 250 | err |= __get_user(temp, &cmd->convert_arg); |
252 | err |= __put_user(temp, &cmd32->convert_arg); | 251 | err |= __put_user(temp, &cmd32->convert_arg); |
253 | err |= __get_user(temp, &cmd->scan_end_src); | 252 | err |= __get_user(temp, &cmd->scan_end_src); |
254 | err |= __put_user(temp, &cmd32->scan_end_src); | 253 | err |= __put_user(temp, &cmd32->scan_end_src); |
255 | err |= __get_user(temp, &cmd->scan_end_arg); | 254 | err |= __get_user(temp, &cmd->scan_end_arg); |
256 | err |= __put_user(temp, &cmd32->scan_end_arg); | 255 | err |= __put_user(temp, &cmd32->scan_end_arg); |
257 | err |= __get_user(temp, &cmd->stop_src); | 256 | err |= __get_user(temp, &cmd->stop_src); |
258 | err |= __put_user(temp, &cmd32->stop_src); | 257 | err |= __put_user(temp, &cmd32->stop_src); |
259 | err |= __get_user(temp, &cmd->stop_arg); | 258 | err |= __get_user(temp, &cmd->stop_arg); |
260 | err |= __put_user(temp, &cmd32->stop_arg); | 259 | err |= __put_user(temp, &cmd32->stop_arg); |
261 | /* Assume chanlist pointer is unchanged. */ | 260 | /* Assume chanlist pointer is unchanged. */ |
262 | err |= __get_user(temp, &cmd->chanlist_len); | 261 | err |= __get_user(temp, &cmd->chanlist_len); |
263 | err |= __put_user(temp, &cmd32->chanlist_len); | 262 | err |= __put_user(temp, &cmd32->chanlist_len); |
264 | /* Assume data pointer is unchanged. */ | 263 | /* Assume data pointer is unchanged. */ |
265 | err |= __get_user(temp, &cmd->data_len); | 264 | err |= __get_user(temp, &cmd->data_len); |
266 | err |= __put_user(temp, &cmd32->data_len); | 265 | err |= __put_user(temp, &cmd32->data_len); |
267 | return err ? -EFAULT : 0; | 266 | return err ? -EFAULT : 0; |
268 | } | 267 | } |
269 | 268 | ||
270 | /* Handle 32-bit COMEDI_CMD ioctl. */ | 269 | /* Handle 32-bit COMEDI_CMD ioctl. */ |
271 | static int compat_cmd(struct file *file, unsigned long arg) | 270 | static int compat_cmd(struct file *file, unsigned long arg) |
272 | { | 271 | { |
273 | struct comedi_cmd __user *cmd; | 272 | struct comedi_cmd __user *cmd; |
274 | struct comedi32_cmd_struct __user *cmd32; | 273 | struct comedi32_cmd_struct __user *cmd32; |
275 | int rc; | 274 | int rc; |
276 | 275 | ||
277 | cmd32 = compat_ptr(arg); | 276 | cmd32 = compat_ptr(arg); |
278 | cmd = compat_alloc_user_space(sizeof(*cmd)); | 277 | cmd = compat_alloc_user_space(sizeof(*cmd)); |
279 | 278 | ||
280 | rc = get_compat_cmd(cmd, cmd32); | 279 | rc = get_compat_cmd(cmd, cmd32); |
281 | if (rc) | 280 | if (rc) |
282 | return rc; | 281 | return rc; |
283 | 282 | ||
284 | return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); | 283 | return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); |
285 | } | 284 | } |
286 | 285 | ||
287 | /* Handle 32-bit COMEDI_CMDTEST ioctl. */ | 286 | /* Handle 32-bit COMEDI_CMDTEST ioctl. */ |
288 | static int compat_cmdtest(struct file *file, unsigned long arg) | 287 | static int compat_cmdtest(struct file *file, unsigned long arg) |
289 | { | 288 | { |
290 | struct comedi_cmd __user *cmd; | 289 | struct comedi_cmd __user *cmd; |
291 | struct comedi32_cmd_struct __user *cmd32; | 290 | struct comedi32_cmd_struct __user *cmd32; |
292 | int rc, err; | 291 | int rc, err; |
293 | 292 | ||
294 | cmd32 = compat_ptr(arg); | 293 | cmd32 = compat_ptr(arg); |
295 | cmd = compat_alloc_user_space(sizeof(*cmd)); | 294 | cmd = compat_alloc_user_space(sizeof(*cmd)); |
296 | 295 | ||
297 | rc = get_compat_cmd(cmd, cmd32); | 296 | rc = get_compat_cmd(cmd, cmd32); |
298 | if (rc) | 297 | if (rc) |
299 | return rc; | 298 | return rc; |
300 | 299 | ||
301 | rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd); | 300 | rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd); |
302 | if (rc < 0) | 301 | if (rc < 0) |
303 | return rc; | 302 | return rc; |
304 | 303 | ||
305 | err = put_compat_cmd(cmd32, cmd); | 304 | err = put_compat_cmd(cmd32, cmd); |
306 | if (err) | 305 | if (err) |
307 | rc = err; | 306 | rc = err; |
308 | 307 | ||
309 | return rc; | 308 | return rc; |
310 | } | 309 | } |
311 | 310 | ||
312 | /* Copy 32-bit insn structure to native insn structure. */ | 311 | /* Copy 32-bit insn structure to native insn structure. */ |
313 | static int get_compat_insn(struct comedi_insn __user *insn, | 312 | static int get_compat_insn(struct comedi_insn __user *insn, |
314 | struct comedi32_insn_struct __user *insn32) | 313 | struct comedi32_insn_struct __user *insn32) |
315 | { | 314 | { |
316 | int err; | 315 | int err; |
317 | union { | 316 | union { |
318 | unsigned int uint; | 317 | unsigned int uint; |
319 | compat_uptr_t uptr; | 318 | compat_uptr_t uptr; |
320 | } temp; | 319 | } temp; |
321 | 320 | ||
322 | /* Copy insn structure. Ignore the unused members. */ | 321 | /* Copy insn structure. Ignore the unused members. */ |
323 | err = 0; | 322 | err = 0; |
324 | if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32)) | 323 | if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32)) |
325 | || !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) | 324 | || !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) |
326 | return -EFAULT; | 325 | return -EFAULT; |
327 | 326 | ||
328 | err |= __get_user(temp.uint, &insn32->insn); | 327 | err |= __get_user(temp.uint, &insn32->insn); |
329 | err |= __put_user(temp.uint, &insn->insn); | 328 | err |= __put_user(temp.uint, &insn->insn); |
330 | err |= __get_user(temp.uint, &insn32->n); | 329 | err |= __get_user(temp.uint, &insn32->n); |
331 | err |= __put_user(temp.uint, &insn->n); | 330 | err |= __put_user(temp.uint, &insn->n); |
332 | err |= __get_user(temp.uptr, &insn32->data); | 331 | err |= __get_user(temp.uptr, &insn32->data); |
333 | err |= __put_user(compat_ptr(temp.uptr), &insn->data); | 332 | err |= __put_user(compat_ptr(temp.uptr), &insn->data); |
334 | err |= __get_user(temp.uint, &insn32->subdev); | 333 | err |= __get_user(temp.uint, &insn32->subdev); |
335 | err |= __put_user(temp.uint, &insn->subdev); | 334 | err |= __put_user(temp.uint, &insn->subdev); |
336 | err |= __get_user(temp.uint, &insn32->chanspec); | 335 | err |= __get_user(temp.uint, &insn32->chanspec); |
337 | err |= __put_user(temp.uint, &insn->chanspec); | 336 | err |= __put_user(temp.uint, &insn->chanspec); |
338 | return err ? -EFAULT : 0; | 337 | return err ? -EFAULT : 0; |
339 | } | 338 | } |
340 | 339 | ||
341 | /* Handle 32-bit COMEDI_INSNLIST ioctl. */ | 340 | /* Handle 32-bit COMEDI_INSNLIST ioctl. */ |
342 | static int compat_insnlist(struct file *file, unsigned long arg) | 341 | static int compat_insnlist(struct file *file, unsigned long arg) |
343 | { | 342 | { |
344 | struct combined_insnlist { | 343 | struct combined_insnlist { |
345 | struct comedi_insnlist insnlist; | 344 | struct comedi_insnlist insnlist; |
346 | struct comedi_insn insn[1]; | 345 | struct comedi_insn insn[1]; |
347 | } __user *s; | 346 | } __user *s; |
348 | struct comedi32_insnlist_struct __user *insnlist32; | 347 | struct comedi32_insnlist_struct __user *insnlist32; |
349 | struct comedi32_insn_struct __user *insn32; | 348 | struct comedi32_insn_struct __user *insn32; |
350 | compat_uptr_t uptr; | 349 | compat_uptr_t uptr; |
351 | unsigned int n_insns, n; | 350 | unsigned int n_insns, n; |
352 | int err, rc; | 351 | int err, rc; |
353 | 352 | ||
354 | insnlist32 = compat_ptr(arg); | 353 | insnlist32 = compat_ptr(arg); |
355 | 354 | ||
356 | /* Get 32-bit insnlist structure. */ | 355 | /* Get 32-bit insnlist structure. */ |
357 | if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) | 356 | if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) |
358 | return -EFAULT; | 357 | return -EFAULT; |
359 | 358 | ||
360 | err = 0; | 359 | err = 0; |
361 | err |= __get_user(n_insns, &insnlist32->n_insns); | 360 | err |= __get_user(n_insns, &insnlist32->n_insns); |
362 | err |= __get_user(uptr, &insnlist32->insns); | 361 | err |= __get_user(uptr, &insnlist32->insns); |
363 | insn32 = compat_ptr(uptr); | 362 | insn32 = compat_ptr(uptr); |
364 | if (err) | 363 | if (err) |
365 | return -EFAULT; | 364 | return -EFAULT; |
366 | 365 | ||
367 | /* Allocate user memory to copy insnlist and insns into. */ | 366 | /* Allocate user memory to copy insnlist and insns into. */ |
368 | s = compat_alloc_user_space(offsetof(struct combined_insnlist, | 367 | s = compat_alloc_user_space(offsetof(struct combined_insnlist, |
369 | insn[n_insns])); | 368 | insn[n_insns])); |
370 | 369 | ||
371 | /* Set native insnlist structure. */ | 370 | /* Set native insnlist structure. */ |
372 | if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) | 371 | if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) |
373 | return -EFAULT; | 372 | return -EFAULT; |
374 | 373 | ||
375 | err |= __put_user(n_insns, &s->insnlist.n_insns); | 374 | err |= __put_user(n_insns, &s->insnlist.n_insns); |
376 | err |= __put_user(&s->insn[0], &s->insnlist.insns); | 375 | err |= __put_user(&s->insn[0], &s->insnlist.insns); |
377 | if (err) | 376 | if (err) |
378 | return -EFAULT; | 377 | return -EFAULT; |
379 | 378 | ||
380 | /* Copy insn structures. */ | 379 | /* Copy insn structures. */ |
381 | for (n = 0; n < n_insns; n++) { | 380 | for (n = 0; n < n_insns; n++) { |
382 | rc = get_compat_insn(&s->insn[n], &insn32[n]); | 381 | rc = get_compat_insn(&s->insn[n], &insn32[n]); |
383 | if (rc) | 382 | if (rc) |
384 | return rc; | 383 | return rc; |
385 | } | 384 | } |
386 | 385 | ||
387 | return translated_ioctl(file, COMEDI_INSNLIST, | 386 | return translated_ioctl(file, COMEDI_INSNLIST, |
388 | (unsigned long)&s->insnlist); | 387 | (unsigned long)&s->insnlist); |
389 | } | 388 | } |
390 | 389 | ||
391 | /* Handle 32-bit COMEDI_INSN ioctl. */ | 390 | /* Handle 32-bit COMEDI_INSN ioctl. */ |
392 | static int compat_insn(struct file *file, unsigned long arg) | 391 | static int compat_insn(struct file *file, unsigned long arg) |
393 | { | 392 | { |
394 | struct comedi_insn __user *insn; | 393 | struct comedi_insn __user *insn; |
395 | struct comedi32_insn_struct __user *insn32; | 394 | struct comedi32_insn_struct __user *insn32; |
396 | int rc; | 395 | int rc; |
397 | 396 | ||
398 | insn32 = compat_ptr(arg); | 397 | insn32 = compat_ptr(arg); |
399 | insn = compat_alloc_user_space(sizeof(*insn)); | 398 | insn = compat_alloc_user_space(sizeof(*insn)); |
400 | 399 | ||
401 | rc = get_compat_insn(insn, insn32); | 400 | rc = get_compat_insn(insn, insn32); |
402 | if (rc) | 401 | if (rc) |
403 | return rc; | 402 | return rc; |
404 | 403 | ||
405 | return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn); | 404 | return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn); |
406 | } | 405 | } |
407 | 406 | ||
408 | /* Process untranslated ioctl. */ | 407 | /* Process untranslated ioctl. */ |
409 | /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ | 408 | /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ |
410 | static inline int raw_ioctl(struct file *file, unsigned int cmd, | 409 | static inline int raw_ioctl(struct file *file, unsigned int cmd, |
411 | unsigned long arg) | 410 | unsigned long arg) |
412 | { | 411 | { |
413 | int rc; | 412 | int rc; |
414 | 413 | ||
415 | switch (cmd) { | 414 | switch (cmd) { |
416 | case COMEDI_DEVCONFIG: | 415 | case COMEDI_DEVCONFIG: |
417 | case COMEDI_DEVINFO: | 416 | case COMEDI_DEVINFO: |
418 | case COMEDI_SUBDINFO: | 417 | case COMEDI_SUBDINFO: |
419 | case COMEDI_BUFCONFIG: | 418 | case COMEDI_BUFCONFIG: |
420 | case COMEDI_BUFINFO: | 419 | case COMEDI_BUFINFO: |
421 | /* Just need to translate the pointer argument. */ | 420 | /* Just need to translate the pointer argument. */ |
422 | arg = (unsigned long)compat_ptr(arg); | 421 | arg = (unsigned long)compat_ptr(arg); |
423 | rc = translated_ioctl(file, cmd, arg); | 422 | rc = translated_ioctl(file, cmd, arg); |
424 | break; | 423 | break; |
425 | case COMEDI_LOCK: | 424 | case COMEDI_LOCK: |
426 | case COMEDI_UNLOCK: | 425 | case COMEDI_UNLOCK: |
427 | case COMEDI_CANCEL: | 426 | case COMEDI_CANCEL: |
428 | case COMEDI_POLL: | 427 | case COMEDI_POLL: |
429 | /* No translation needed. */ | 428 | /* No translation needed. */ |
430 | rc = translated_ioctl(file, cmd, arg); | 429 | rc = translated_ioctl(file, cmd, arg); |
431 | break; | 430 | break; |
432 | case COMEDI32_CHANINFO: | 431 | case COMEDI32_CHANINFO: |
433 | rc = compat_chaninfo(file, arg); | 432 | rc = compat_chaninfo(file, arg); |
434 | break; | 433 | break; |
435 | case COMEDI32_RANGEINFO: | 434 | case COMEDI32_RANGEINFO: |
436 | rc = compat_rangeinfo(file, arg); | 435 | rc = compat_rangeinfo(file, arg); |
437 | break; | 436 | break; |
438 | case COMEDI32_CMD: | 437 | case COMEDI32_CMD: |
439 | rc = compat_cmd(file, arg); | 438 | rc = compat_cmd(file, arg); |
440 | break; | 439 | break; |
441 | case COMEDI32_CMDTEST: | 440 | case COMEDI32_CMDTEST: |
442 | rc = compat_cmdtest(file, arg); | 441 | rc = compat_cmdtest(file, arg); |
443 | break; | 442 | break; |
444 | case COMEDI32_INSNLIST: | 443 | case COMEDI32_INSNLIST: |
445 | rc = compat_insnlist(file, arg); | 444 | rc = compat_insnlist(file, arg); |
446 | break; | 445 | break; |
447 | case COMEDI32_INSN: | 446 | case COMEDI32_INSN: |
448 | rc = compat_insn(file, arg); | 447 | rc = compat_insn(file, arg); |
449 | break; | 448 | break; |
450 | default: | 449 | default: |
451 | rc = -ENOIOCTLCMD; | 450 | rc = -ENOIOCTLCMD; |
452 | break; | 451 | break; |
453 | } | 452 | } |
454 | return rc; | 453 | return rc; |
455 | } | 454 | } |
456 | 455 | ||
457 | /* compat_ioctl file operation. */ | 456 | /* compat_ioctl file operation. */ |
458 | /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ | 457 | /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ |
459 | long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 458 | long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
460 | { | 459 | { |
461 | return raw_ioctl(file, cmd, arg); | 460 | return raw_ioctl(file, cmd, arg); |
462 | } | 461 | } |
463 | 462 | ||
464 | #endif /* CONFIG_COMPAT */ | 463 | #endif /* CONFIG_COMPAT */ |
465 | 464 |
drivers/staging/comedi/drivers/comedi_bond.c
1 | /* | 1 | /* |
2 | comedi/drivers/comedi_bond.c | 2 | comedi/drivers/comedi_bond.c |
3 | A Comedi driver to 'bond' or merge multiple drivers and devices as one. | 3 | A Comedi driver to 'bond' or merge multiple drivers and devices as one. |
4 | 4 | ||
5 | COMEDI - Linux Control and Measurement Device Interface | 5 | COMEDI - Linux Control and Measurement Device Interface |
6 | Copyright (C) 2000 David A. Schleef <ds@schleef.org> | 6 | Copyright (C) 2000 David A. Schleef <ds@schleef.org> |
7 | Copyright (C) 2005 Calin A. Culianu <calin@ajvar.org> | 7 | Copyright (C) 2005 Calin A. Culianu <calin@ajvar.org> |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
10 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
11 | the Free Software Foundation; either version 2 of the License, or | 11 | the Free Software Foundation; either version 2 of the License, or |
12 | (at your option) any later version. | 12 | (at your option) any later version. |
13 | 13 | ||
14 | This program is distributed in the hope that it will be useful, | 14 | This program is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | GNU General Public License for more details. | 17 | GNU General Public License for more details. |
18 | 18 | ||
19 | You should have received a copy of the GNU General Public License | 19 | You should have received a copy of the GNU General Public License |
20 | along with this program; if not, write to the Free Software | 20 | along with this program; if not, write to the Free Software |
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
22 | 22 | ||
23 | */ | 23 | */ |
24 | /* | 24 | /* |
25 | Driver: comedi_bond | 25 | Driver: comedi_bond |
26 | Description: A driver to 'bond' (merge) multiple subdevices from multiple | 26 | Description: A driver to 'bond' (merge) multiple subdevices from multiple |
27 | devices together as one. | 27 | devices together as one. |
28 | Devices: | 28 | Devices: |
29 | Author: ds | 29 | Author: ds |
30 | Updated: Mon, 10 Oct 00:18:25 -0500 | 30 | Updated: Mon, 10 Oct 00:18:25 -0500 |
31 | Status: works | 31 | Status: works |
32 | 32 | ||
33 | This driver allows you to 'bond' (merge) multiple comedi subdevices | 33 | This driver allows you to 'bond' (merge) multiple comedi subdevices |
34 | (coming from possibly difference boards and/or drivers) together. For | 34 | (coming from possibly difference boards and/or drivers) together. For |
35 | example, if you had a board with 2 different DIO subdevices, and | 35 | example, if you had a board with 2 different DIO subdevices, and |
36 | another with 1 DIO subdevice, you could 'bond' them with this driver | 36 | another with 1 DIO subdevice, you could 'bond' them with this driver |
37 | so that they look like one big fat DIO subdevice. This makes writing | 37 | so that they look like one big fat DIO subdevice. This makes writing |
38 | applications slightly easier as you don't have to worry about managing | 38 | applications slightly easier as you don't have to worry about managing |
39 | different subdevices in the application -- you just worry about | 39 | different subdevices in the application -- you just worry about |
40 | indexing one linear array of channel id's. | 40 | indexing one linear array of channel id's. |
41 | 41 | ||
42 | Right now only DIO subdevices are supported as that's the personal itch | 42 | Right now only DIO subdevices are supported as that's the personal itch |
43 | I am scratching with this driver. If you want to add support for AI and AO | 43 | I am scratching with this driver. If you want to add support for AI and AO |
44 | subdevs, go right on ahead and do so! | 44 | subdevs, go right on ahead and do so! |
45 | 45 | ||
46 | Commands aren't supported -- although it would be cool if they were. | 46 | Commands aren't supported -- although it would be cool if they were. |
47 | 47 | ||
48 | Configuration Options: | 48 | Configuration Options: |
49 | List of comedi-minors to bond. All subdevices of the same type | 49 | List of comedi-minors to bond. All subdevices of the same type |
50 | within each minor will be concatenated together in the order given here. | 50 | within each minor will be concatenated together in the order given here. |
51 | */ | 51 | */ |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * The previous block comment is used to automatically generate | 54 | * The previous block comment is used to automatically generate |
55 | * documentation in Comedi and Comedilib. The fields: | 55 | * documentation in Comedi and Comedilib. The fields: |
56 | * | 56 | * |
57 | * Driver: the name of the driver | 57 | * Driver: the name of the driver |
58 | * Description: a short phrase describing the driver. Don't list boards. | 58 | * Description: a short phrase describing the driver. Don't list boards. |
59 | * Devices: a full list of the boards that attempt to be supported by | 59 | * Devices: a full list of the boards that attempt to be supported by |
60 | * the driver. Format is "(manufacturer) board name [comedi name]", | 60 | * the driver. Format is "(manufacturer) board name [comedi name]", |
61 | * where comedi_name is the name that is used to configure the board. | 61 | * where comedi_name is the name that is used to configure the board. |
62 | * See the comment near board_name: in the struct comedi_driver structure | 62 | * See the comment near board_name: in the struct comedi_driver structure |
63 | * below. If (manufacturer) or [comedi name] is missing, the previous | 63 | * below. If (manufacturer) or [comedi name] is missing, the previous |
64 | * value is used. | 64 | * value is used. |
65 | * Author: you | 65 | * Author: you |
66 | * Updated: date when the _documentation_ was last updated. Use 'date -R' | 66 | * Updated: date when the _documentation_ was last updated. Use 'date -R' |
67 | * to get a value for this. | 67 | * to get a value for this. |
68 | * Status: a one-word description of the status. Valid values are: | 68 | * Status: a one-word description of the status. Valid values are: |
69 | * works - driver works correctly on most boards supported, and | 69 | * works - driver works correctly on most boards supported, and |
70 | * passes comedi_test. | 70 | * passes comedi_test. |
71 | * unknown - unknown. Usually put there by ds. | 71 | * unknown - unknown. Usually put there by ds. |
72 | * experimental - may not work in any particular release. Author | 72 | * experimental - may not work in any particular release. Author |
73 | * probably wants assistance testing it. | 73 | * probably wants assistance testing it. |
74 | * bitrotten - driver has not been update in a long time, probably | 74 | * bitrotten - driver has not been update in a long time, probably |
75 | * doesn't work, and probably is missing support for significant | 75 | * doesn't work, and probably is missing support for significant |
76 | * Comedi interface features. | 76 | * Comedi interface features. |
77 | * untested - author probably wrote it "blind", and is believed to | 77 | * untested - author probably wrote it "blind", and is believed to |
78 | * work, but no confirmation. | 78 | * work, but no confirmation. |
79 | * | 79 | * |
80 | * These headers should be followed by a blank line, and any comments | 80 | * These headers should be followed by a blank line, and any comments |
81 | * you wish to say about the driver. The comment area is the place | 81 | * you wish to say about the driver. The comment area is the place |
82 | * to put any known bugs, limitations, unsupported features, supported | 82 | * to put any known bugs, limitations, unsupported features, supported |
83 | * command triggers, whether or not commands are supported on particular | 83 | * command triggers, whether or not commands are supported on particular |
84 | * subdevices, etc. | 84 | * subdevices, etc. |
85 | * | 85 | * |
86 | * Somewhere in the comment should be information about configuration | 86 | * Somewhere in the comment should be information about configuration |
87 | * options that are used with comedi_config. | 87 | * options that are used with comedi_config. |
88 | */ | 88 | */ |
89 | 89 | ||
90 | #include <linux/string.h> | ||
91 | #include <linux/slab.h> | ||
90 | #include "../comedi.h" | 92 | #include "../comedi.h" |
91 | #include "../comedilib.h" | 93 | #include "../comedilib.h" |
92 | #include "../comedidev.h" | 94 | #include "../comedidev.h" |
93 | #include <linux/string.h> | ||
94 | #include <linux/slab.h> | ||
95 | 95 | ||
96 | /* The maxiumum number of channels per subdevice. */ | 96 | /* The maxiumum number of channels per subdevice. */ |
97 | #define MAX_CHANS 256 | 97 | #define MAX_CHANS 256 |
98 | 98 | ||
99 | #define MODULE_NAME "comedi_bond" | 99 | #define MODULE_NAME "comedi_bond" |
100 | MODULE_LICENSE("GPL"); | 100 | MODULE_LICENSE("GPL"); |
101 | #ifndef STR | 101 | #ifndef STR |
102 | # define STR1(x) #x | 102 | # define STR1(x) #x |
103 | # define STR(x) STR1(x) | 103 | # define STR(x) STR1(x) |
104 | #endif | 104 | #endif |
105 | 105 | ||
106 | static int debug; | 106 | static int debug; |
107 | module_param(debug, int, 0644); | 107 | module_param(debug, int, 0644); |
108 | MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful" | 108 | MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful" |
109 | "only to developers."); | 109 | "only to developers."); |
110 | 110 | ||
111 | #define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x) | 111 | #define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x) |
112 | #define DEBUG(x...) \ | 112 | #define DEBUG(x...) \ |
113 | do { \ | 113 | do { \ |
114 | if (debug) \ | 114 | if (debug) \ |
115 | printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \ | 115 | printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \ |
116 | } while (0) | 116 | } while (0) |
117 | #define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x) | 117 | #define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x) |
118 | #define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x) | 118 | #define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x) |
119 | MODULE_AUTHOR("Calin A. Culianu"); | 119 | MODULE_AUTHOR("Calin A. Culianu"); |
120 | MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI " | 120 | MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI " |
121 | "devices together as one. In the words of John Lennon: " | 121 | "devices together as one. In the words of John Lennon: " |
122 | "'And the world will live as one...'"); | 122 | "'And the world will live as one...'"); |
123 | 123 | ||
124 | /* | 124 | /* |
125 | * Board descriptions for two imaginary boards. Describing the | 125 | * Board descriptions for two imaginary boards. Describing the |
126 | * boards in this way is optional, and completely driver-dependent. | 126 | * boards in this way is optional, and completely driver-dependent. |
127 | * Some drivers use arrays such as this, other do not. | 127 | * Some drivers use arrays such as this, other do not. |
128 | */ | 128 | */ |
129 | struct BondingBoard { | 129 | struct BondingBoard { |
130 | const char *name; | 130 | const char *name; |
131 | }; | 131 | }; |
132 | 132 | ||
133 | static const struct BondingBoard bondingBoards[] = { | 133 | static const struct BondingBoard bondingBoards[] = { |
134 | { | 134 | { |
135 | .name = MODULE_NAME, | 135 | .name = MODULE_NAME, |
136 | }, | 136 | }, |
137 | }; | 137 | }; |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * Useful for shorthand access to the particular board structure | 140 | * Useful for shorthand access to the particular board structure |
141 | */ | 141 | */ |
142 | #define thisboard ((const struct BondingBoard *)dev->board_ptr) | 142 | #define thisboard ((const struct BondingBoard *)dev->board_ptr) |
143 | 143 | ||
144 | struct BondedDevice { | 144 | struct BondedDevice { |
145 | struct comedi_device *dev; | 145 | struct comedi_device *dev; |
146 | unsigned minor; | 146 | unsigned minor; |
147 | unsigned subdev; | 147 | unsigned subdev; |
148 | unsigned subdev_type; | 148 | unsigned subdev_type; |
149 | unsigned nchans; | 149 | unsigned nchans; |
150 | unsigned chanid_offset; /* The offset into our unified linear | 150 | unsigned chanid_offset; /* The offset into our unified linear |
151 | channel-id's of chanid 0 on this | 151 | channel-id's of chanid 0 on this |
152 | subdevice. */ | 152 | subdevice. */ |
153 | }; | 153 | }; |
154 | 154 | ||
155 | /* this structure is for data unique to this hardware driver. If | 155 | /* this structure is for data unique to this hardware driver. If |
156 | several hardware drivers keep similar information in this structure, | 156 | several hardware drivers keep similar information in this structure, |
157 | feel free to suggest moving the variable to the struct comedi_device struct. */ | 157 | feel free to suggest moving the variable to the struct comedi_device struct. */ |
158 | struct Private { | 158 | struct Private { |
159 | # define MAX_BOARD_NAME 256 | 159 | # define MAX_BOARD_NAME 256 |
160 | char name[MAX_BOARD_NAME]; | 160 | char name[MAX_BOARD_NAME]; |
161 | struct BondedDevice **devs; | 161 | struct BondedDevice **devs; |
162 | unsigned ndevs; | 162 | unsigned ndevs; |
163 | struct BondedDevice *chanIdDevMap[MAX_CHANS]; | 163 | struct BondedDevice *chanIdDevMap[MAX_CHANS]; |
164 | unsigned nchans; | 164 | unsigned nchans; |
165 | }; | 165 | }; |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * most drivers define the following macro to make it easy to | 168 | * most drivers define the following macro to make it easy to |
169 | * access the private structure. | 169 | * access the private structure. |
170 | */ | 170 | */ |
171 | #define devpriv ((struct Private *)dev->private) | 171 | #define devpriv ((struct Private *)dev->private) |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * The struct comedi_driver structure tells the Comedi core module | 174 | * The struct comedi_driver structure tells the Comedi core module |
175 | * which functions to call to configure/deconfigure (attach/detach) | 175 | * which functions to call to configure/deconfigure (attach/detach) |
176 | * the board, and also about the kernel module that contains | 176 | * the board, and also about the kernel module that contains |
177 | * the device code. | 177 | * the device code. |
178 | */ | 178 | */ |
179 | static int bonding_attach(struct comedi_device *dev, | 179 | static int bonding_attach(struct comedi_device *dev, |
180 | struct comedi_devconfig *it); | 180 | struct comedi_devconfig *it); |
181 | static int bonding_detach(struct comedi_device *dev); | 181 | static int bonding_detach(struct comedi_device *dev); |
182 | /** Build Private array of all devices.. */ | 182 | /** Build Private array of all devices.. */ |
183 | static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it); | 183 | static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it); |
184 | static void doDevUnconfig(struct comedi_device *dev); | 184 | static void doDevUnconfig(struct comedi_device *dev); |
185 | /* Ugly implementation of realloc that always copies memory around -- I'm lazy, | 185 | /* Ugly implementation of realloc that always copies memory around -- I'm lazy, |
186 | * what can I say? I like to do wasteful memcopies.. :) */ | 186 | * what can I say? I like to do wasteful memcopies.. :) */ |
187 | static void *Realloc(const void *ptr, size_t len, size_t old_len); | 187 | static void *Realloc(const void *ptr, size_t len, size_t old_len); |
188 | 188 | ||
189 | static struct comedi_driver driver_bonding = { | 189 | static struct comedi_driver driver_bonding = { |
190 | .driver_name = MODULE_NAME, | 190 | .driver_name = MODULE_NAME, |
191 | .module = THIS_MODULE, | 191 | .module = THIS_MODULE, |
192 | .attach = bonding_attach, | 192 | .attach = bonding_attach, |
193 | .detach = bonding_detach, | 193 | .detach = bonding_detach, |
194 | /* It is not necessary to implement the following members if you are | 194 | /* It is not necessary to implement the following members if you are |
195 | * writing a driver for a ISA PnP or PCI card */ | 195 | * writing a driver for a ISA PnP or PCI card */ |
196 | /* Most drivers will support multiple types of boards by | 196 | /* Most drivers will support multiple types of boards by |
197 | * having an array of board structures. These were defined | 197 | * having an array of board structures. These were defined |
198 | * in skel_boards[] above. Note that the element 'name' | 198 | * in skel_boards[] above. Note that the element 'name' |
199 | * was first in the structure -- Comedi uses this fact to | 199 | * was first in the structure -- Comedi uses this fact to |
200 | * extract the name of the board without knowing any details | 200 | * extract the name of the board without knowing any details |
201 | * about the structure except for its length. | 201 | * about the structure except for its length. |
202 | * When a device is attached (by comedi_config), the name | 202 | * When a device is attached (by comedi_config), the name |
203 | * of the device is given to Comedi, and Comedi tries to | 203 | * of the device is given to Comedi, and Comedi tries to |
204 | * match it by going through the list of board names. If | 204 | * match it by going through the list of board names. If |
205 | * there is a match, the address of the pointer is put | 205 | * there is a match, the address of the pointer is put |
206 | * into dev->board_ptr and driver->attach() is called. | 206 | * into dev->board_ptr and driver->attach() is called. |
207 | * | 207 | * |
208 | * Note that these are not necessary if you can determine | 208 | * Note that these are not necessary if you can determine |
209 | * the type of board in software. ISA PnP, PCI, and PCMCIA | 209 | * the type of board in software. ISA PnP, PCI, and PCMCIA |
210 | * devices are such boards. | 210 | * devices are such boards. |
211 | */ | 211 | */ |
212 | .board_name = &bondingBoards[0].name, | 212 | .board_name = &bondingBoards[0].name, |
213 | .offset = sizeof(struct BondingBoard), | 213 | .offset = sizeof(struct BondingBoard), |
214 | .num_names = ARRAY_SIZE(bondingBoards), | 214 | .num_names = ARRAY_SIZE(bondingBoards), |
215 | }; | 215 | }; |
216 | 216 | ||
217 | static int bonding_dio_insn_bits(struct comedi_device *dev, | 217 | static int bonding_dio_insn_bits(struct comedi_device *dev, |
218 | struct comedi_subdevice *s, | 218 | struct comedi_subdevice *s, |
219 | struct comedi_insn *insn, unsigned int *data); | 219 | struct comedi_insn *insn, unsigned int *data); |
220 | static int bonding_dio_insn_config(struct comedi_device *dev, | 220 | static int bonding_dio_insn_config(struct comedi_device *dev, |
221 | struct comedi_subdevice *s, | 221 | struct comedi_subdevice *s, |
222 | struct comedi_insn *insn, | 222 | struct comedi_insn *insn, |
223 | unsigned int *data); | 223 | unsigned int *data); |
224 | 224 | ||
225 | /* | 225 | /* |
226 | * Attach is called by the Comedi core to configure the driver | 226 | * Attach is called by the Comedi core to configure the driver |
227 | * for a particular board. If you specified a board_name array | 227 | * for a particular board. If you specified a board_name array |
228 | * in the driver structure, dev->board_ptr contains that | 228 | * in the driver structure, dev->board_ptr contains that |
229 | * address. | 229 | * address. |
230 | */ | 230 | */ |
231 | static int bonding_attach(struct comedi_device *dev, | 231 | static int bonding_attach(struct comedi_device *dev, |
232 | struct comedi_devconfig *it) | 232 | struct comedi_devconfig *it) |
233 | { | 233 | { |
234 | struct comedi_subdevice *s; | 234 | struct comedi_subdevice *s; |
235 | 235 | ||
236 | LOG_MSG("comedi%d\n", dev->minor); | 236 | LOG_MSG("comedi%d\n", dev->minor); |
237 | 237 | ||
238 | /* | 238 | /* |
239 | * Allocate the private structure area. alloc_private() is a | 239 | * Allocate the private structure area. alloc_private() is a |
240 | * convenient macro defined in comedidev.h. | 240 | * convenient macro defined in comedidev.h. |
241 | */ | 241 | */ |
242 | if (alloc_private(dev, sizeof(struct Private)) < 0) | 242 | if (alloc_private(dev, sizeof(struct Private)) < 0) |
243 | return -ENOMEM; | 243 | return -ENOMEM; |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * Setup our bonding from config params.. sets up our Private struct.. | 246 | * Setup our bonding from config params.. sets up our Private struct.. |
247 | */ | 247 | */ |
248 | if (!doDevConfig(dev, it)) | 248 | if (!doDevConfig(dev, it)) |
249 | return -EINVAL; | 249 | return -EINVAL; |
250 | 250 | ||
251 | /* | 251 | /* |
252 | * Initialize dev->board_name. Note that we can use the "thisboard" | 252 | * Initialize dev->board_name. Note that we can use the "thisboard" |
253 | * macro now, since we just initialized it in the last line. | 253 | * macro now, since we just initialized it in the last line. |
254 | */ | 254 | */ |
255 | dev->board_name = devpriv->name; | 255 | dev->board_name = devpriv->name; |
256 | 256 | ||
257 | /* | 257 | /* |
258 | * Allocate the subdevice structures. alloc_subdevice() is a | 258 | * Allocate the subdevice structures. alloc_subdevice() is a |
259 | * convenient macro defined in comedidev.h. | 259 | * convenient macro defined in comedidev.h. |
260 | */ | 260 | */ |
261 | if (alloc_subdevices(dev, 1) < 0) | 261 | if (alloc_subdevices(dev, 1) < 0) |
262 | return -ENOMEM; | 262 | return -ENOMEM; |
263 | 263 | ||
264 | s = dev->subdevices + 0; | 264 | s = dev->subdevices + 0; |
265 | s->type = COMEDI_SUBD_DIO; | 265 | s->type = COMEDI_SUBD_DIO; |
266 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | 266 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; |
267 | s->n_chan = devpriv->nchans; | 267 | s->n_chan = devpriv->nchans; |
268 | s->maxdata = 1; | 268 | s->maxdata = 1; |
269 | s->range_table = &range_digital; | 269 | s->range_table = &range_digital; |
270 | s->insn_bits = bonding_dio_insn_bits; | 270 | s->insn_bits = bonding_dio_insn_bits; |
271 | s->insn_config = bonding_dio_insn_config; | 271 | s->insn_config = bonding_dio_insn_config; |
272 | 272 | ||
273 | LOG_MSG("attached with %u DIO channels coming from %u different " | 273 | LOG_MSG("attached with %u DIO channels coming from %u different " |
274 | "subdevices all bonded together. " | 274 | "subdevices all bonded together. " |
275 | "John Lennon would be proud!\n", | 275 | "John Lennon would be proud!\n", |
276 | devpriv->nchans, devpriv->ndevs); | 276 | devpriv->nchans, devpriv->ndevs); |
277 | 277 | ||
278 | return 1; | 278 | return 1; |
279 | } | 279 | } |
280 | 280 | ||
281 | /* | 281 | /* |
282 | * _detach is called to deconfigure a device. It should deallocate | 282 | * _detach is called to deconfigure a device. It should deallocate |
283 | * resources. | 283 | * resources. |
284 | * This function is also called when _attach() fails, so it should be | 284 | * This function is also called when _attach() fails, so it should be |
285 | * careful not to release resources that were not necessarily | 285 | * careful not to release resources that were not necessarily |
286 | * allocated by _attach(). dev->private and dev->subdevices are | 286 | * allocated by _attach(). dev->private and dev->subdevices are |
287 | * deallocated automatically by the core. | 287 | * deallocated automatically by the core. |
288 | */ | 288 | */ |
289 | static int bonding_detach(struct comedi_device *dev) | 289 | static int bonding_detach(struct comedi_device *dev) |
290 | { | 290 | { |
291 | LOG_MSG("comedi%d: remove\n", dev->minor); | 291 | LOG_MSG("comedi%d: remove\n", dev->minor); |
292 | doDevUnconfig(dev); | 292 | doDevUnconfig(dev); |
293 | return 0; | 293 | return 0; |
294 | } | 294 | } |
295 | 295 | ||
296 | /* DIO devices are slightly special. Although it is possible to | 296 | /* DIO devices are slightly special. Although it is possible to |
297 | * implement the insn_read/insn_write interface, it is much more | 297 | * implement the insn_read/insn_write interface, it is much more |
298 | * useful to applications if you implement the insn_bits interface. | 298 | * useful to applications if you implement the insn_bits interface. |
299 | * This allows packed reading/writing of the DIO channels. The | 299 | * This allows packed reading/writing of the DIO channels. The |
300 | * comedi core can convert between insn_bits and insn_read/write */ | 300 | * comedi core can convert between insn_bits and insn_read/write */ |
301 | static int bonding_dio_insn_bits(struct comedi_device *dev, | 301 | static int bonding_dio_insn_bits(struct comedi_device *dev, |
302 | struct comedi_subdevice *s, | 302 | struct comedi_subdevice *s, |
303 | struct comedi_insn *insn, unsigned int *data) | 303 | struct comedi_insn *insn, unsigned int *data) |
304 | { | 304 | { |
305 | #define LSAMPL_BITS (sizeof(unsigned int)*8) | 305 | #define LSAMPL_BITS (sizeof(unsigned int)*8) |
306 | unsigned nchans = LSAMPL_BITS, num_done = 0, i; | 306 | unsigned nchans = LSAMPL_BITS, num_done = 0, i; |
307 | if (insn->n != 2) | 307 | if (insn->n != 2) |
308 | return -EINVAL; | 308 | return -EINVAL; |
309 | 309 | ||
310 | if (devpriv->nchans < nchans) | 310 | if (devpriv->nchans < nchans) |
311 | nchans = devpriv->nchans; | 311 | nchans = devpriv->nchans; |
312 | 312 | ||
313 | /* The insn data is a mask in data[0] and the new data | 313 | /* The insn data is a mask in data[0] and the new data |
314 | * in data[1], each channel cooresponding to a bit. */ | 314 | * in data[1], each channel cooresponding to a bit. */ |
315 | for (i = 0; num_done < nchans && i < devpriv->ndevs; ++i) { | 315 | for (i = 0; num_done < nchans && i < devpriv->ndevs; ++i) { |
316 | struct BondedDevice *bdev = devpriv->devs[i]; | 316 | struct BondedDevice *bdev = devpriv->devs[i]; |
317 | /* Grab the channel mask and data of only the bits corresponding | 317 | /* Grab the channel mask and data of only the bits corresponding |
318 | to this subdevice.. need to shift them to zero position of | 318 | to this subdevice.. need to shift them to zero position of |
319 | course. */ | 319 | course. */ |
320 | /* Bits corresponding to this subdev. */ | 320 | /* Bits corresponding to this subdev. */ |
321 | unsigned int subdevMask = ((1 << bdev->nchans) - 1); | 321 | unsigned int subdevMask = ((1 << bdev->nchans) - 1); |
322 | unsigned int writeMask, dataBits; | 322 | unsigned int writeMask, dataBits; |
323 | 323 | ||
324 | /* Argh, we have >= LSAMPL_BITS chans.. take all bits */ | 324 | /* Argh, we have >= LSAMPL_BITS chans.. take all bits */ |
325 | if (bdev->nchans >= LSAMPL_BITS) | 325 | if (bdev->nchans >= LSAMPL_BITS) |
326 | subdevMask = (unsigned int)(-1); | 326 | subdevMask = (unsigned int)(-1); |
327 | 327 | ||
328 | writeMask = (data[0] >> num_done) & subdevMask; | 328 | writeMask = (data[0] >> num_done) & subdevMask; |
329 | dataBits = (data[1] >> num_done) & subdevMask; | 329 | dataBits = (data[1] >> num_done) & subdevMask; |
330 | 330 | ||
331 | /* Read/Write the new digital lines */ | 331 | /* Read/Write the new digital lines */ |
332 | if (comedi_dio_bitfield(bdev->dev, bdev->subdev, writeMask, | 332 | if (comedi_dio_bitfield(bdev->dev, bdev->subdev, writeMask, |
333 | &dataBits) != 2) | 333 | &dataBits) != 2) |
334 | return -EINVAL; | 334 | return -EINVAL; |
335 | 335 | ||
336 | /* Make room for the new bits in data[1], the return value */ | 336 | /* Make room for the new bits in data[1], the return value */ |
337 | data[1] &= ~(subdevMask << num_done); | 337 | data[1] &= ~(subdevMask << num_done); |
338 | /* Put the bits in the return value */ | 338 | /* Put the bits in the return value */ |
339 | data[1] |= (dataBits & subdevMask) << num_done; | 339 | data[1] |= (dataBits & subdevMask) << num_done; |
340 | /* Save the new bits to the saved state.. */ | 340 | /* Save the new bits to the saved state.. */ |
341 | s->state = data[1]; | 341 | s->state = data[1]; |
342 | 342 | ||
343 | num_done += bdev->nchans; | 343 | num_done += bdev->nchans; |
344 | } | 344 | } |
345 | 345 | ||
346 | return insn->n; | 346 | return insn->n; |
347 | } | 347 | } |
348 | 348 | ||
349 | static int bonding_dio_insn_config(struct comedi_device *dev, | 349 | static int bonding_dio_insn_config(struct comedi_device *dev, |
350 | struct comedi_subdevice *s, | 350 | struct comedi_subdevice *s, |
351 | struct comedi_insn *insn, unsigned int *data) | 351 | struct comedi_insn *insn, unsigned int *data) |
352 | { | 352 | { |
353 | int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits; | 353 | int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits; |
354 | unsigned int io; | 354 | unsigned int io; |
355 | struct BondedDevice *bdev; | 355 | struct BondedDevice *bdev; |
356 | 356 | ||
357 | if (chan < 0 || chan >= devpriv->nchans) | 357 | if (chan < 0 || chan >= devpriv->nchans) |
358 | return -EINVAL; | 358 | return -EINVAL; |
359 | bdev = devpriv->chanIdDevMap[chan]; | 359 | bdev = devpriv->chanIdDevMap[chan]; |
360 | 360 | ||
361 | /* The input or output configuration of each digital line is | 361 | /* The input or output configuration of each digital line is |
362 | * configured by a special insn_config instruction. chanspec | 362 | * configured by a special insn_config instruction. chanspec |
363 | * contains the channel to be changed, and data[0] contains the | 363 | * contains the channel to be changed, and data[0] contains the |
364 | * value COMEDI_INPUT or COMEDI_OUTPUT. */ | 364 | * value COMEDI_INPUT or COMEDI_OUTPUT. */ |
365 | switch (data[0]) { | 365 | switch (data[0]) { |
366 | case INSN_CONFIG_DIO_OUTPUT: | 366 | case INSN_CONFIG_DIO_OUTPUT: |
367 | io = COMEDI_OUTPUT; /* is this really necessary? */ | 367 | io = COMEDI_OUTPUT; /* is this really necessary? */ |
368 | io_bits |= 1 << chan; | 368 | io_bits |= 1 << chan; |
369 | break; | 369 | break; |
370 | case INSN_CONFIG_DIO_INPUT: | 370 | case INSN_CONFIG_DIO_INPUT: |
371 | io = COMEDI_INPUT; /* is this really necessary? */ | 371 | io = COMEDI_INPUT; /* is this really necessary? */ |
372 | io_bits &= ~(1 << chan); | 372 | io_bits &= ~(1 << chan); |
373 | break; | 373 | break; |
374 | case INSN_CONFIG_DIO_QUERY: | 374 | case INSN_CONFIG_DIO_QUERY: |
375 | data[1] = | 375 | data[1] = |
376 | (io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; | 376 | (io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; |
377 | return insn->n; | 377 | return insn->n; |
378 | break; | 378 | break; |
379 | default: | 379 | default: |
380 | return -EINVAL; | 380 | return -EINVAL; |
381 | break; | 381 | break; |
382 | } | 382 | } |
383 | /* 'real' channel id for this subdev.. */ | 383 | /* 'real' channel id for this subdev.. */ |
384 | chan -= bdev->chanid_offset; | 384 | chan -= bdev->chanid_offset; |
385 | ret = comedi_dio_config(bdev->dev, bdev->subdev, chan, io); | 385 | ret = comedi_dio_config(bdev->dev, bdev->subdev, chan, io); |
386 | if (ret != 1) | 386 | if (ret != 1) |
387 | return -EINVAL; | 387 | return -EINVAL; |
388 | /* Finally, save the new io_bits values since we didn't get | 388 | /* Finally, save the new io_bits values since we didn't get |
389 | an error above. */ | 389 | an error above. */ |
390 | s->io_bits = io_bits; | 390 | s->io_bits = io_bits; |
391 | return insn->n; | 391 | return insn->n; |
392 | } | 392 | } |
393 | 393 | ||
394 | static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen) | 394 | static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen) |
395 | { | 395 | { |
396 | void *newmem = kmalloc(newlen, GFP_KERNEL); | 396 | void *newmem = kmalloc(newlen, GFP_KERNEL); |
397 | 397 | ||
398 | if (newmem && oldmem) | 398 | if (newmem && oldmem) |
399 | memcpy(newmem, oldmem, min(oldlen, newlen)); | 399 | memcpy(newmem, oldmem, min(oldlen, newlen)); |
400 | kfree(oldmem); | 400 | kfree(oldmem); |
401 | return newmem; | 401 | return newmem; |
402 | } | 402 | } |
403 | 403 | ||
404 | static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) | 404 | static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) |
405 | { | 405 | { |
406 | int i; | 406 | int i; |
407 | struct comedi_device *devs_opened[COMEDI_NUM_BOARD_MINORS]; | 407 | struct comedi_device *devs_opened[COMEDI_NUM_BOARD_MINORS]; |
408 | 408 | ||
409 | memset(devs_opened, 0, sizeof(devs_opened)); | 409 | memset(devs_opened, 0, sizeof(devs_opened)); |
410 | devpriv->name[0] = 0;; | 410 | devpriv->name[0] = 0;; |
411 | /* Loop through all comedi devices specified on the command-line, | 411 | /* Loop through all comedi devices specified on the command-line, |
412 | building our device list */ | 412 | building our device list */ |
413 | for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) { | 413 | for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) { |
414 | char file[] = "/dev/comediXXXXXX"; | 414 | char file[] = "/dev/comediXXXXXX"; |
415 | int minor = it->options[i]; | 415 | int minor = it->options[i]; |
416 | struct comedi_device *d; | 416 | struct comedi_device *d; |
417 | int sdev = -1, nchans, tmp; | 417 | int sdev = -1, nchans, tmp; |
418 | struct BondedDevice *bdev = NULL; | 418 | struct BondedDevice *bdev = NULL; |
419 | 419 | ||
420 | if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) { | 420 | if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) { |
421 | ERROR("Minor %d is invalid!\n", minor); | 421 | ERROR("Minor %d is invalid!\n", minor); |
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | if (minor == dev->minor) { | 424 | if (minor == dev->minor) { |
425 | ERROR("Cannot bond this driver to itself!\n"); | 425 | ERROR("Cannot bond this driver to itself!\n"); |
426 | return 0; | 426 | return 0; |
427 | } | 427 | } |
428 | if (devs_opened[minor]) { | 428 | if (devs_opened[minor]) { |
429 | ERROR("Minor %d specified more than once!\n", minor); | 429 | ERROR("Minor %d specified more than once!\n", minor); |
430 | return 0; | 430 | return 0; |
431 | } | 431 | } |
432 | 432 | ||
433 | snprintf(file, sizeof(file), "/dev/comedi%u", minor); | 433 | snprintf(file, sizeof(file), "/dev/comedi%u", minor); |
434 | file[sizeof(file) - 1] = 0; | 434 | file[sizeof(file) - 1] = 0; |
435 | 435 | ||
436 | d = devs_opened[minor] = comedi_open(file); | 436 | d = devs_opened[minor] = comedi_open(file); |
437 | 437 | ||
438 | if (!d) { | 438 | if (!d) { |
439 | ERROR("Minor %u could not be opened\n", minor); | 439 | ERROR("Minor %u could not be opened\n", minor); |
440 | return 0; | 440 | return 0; |
441 | } | 441 | } |
442 | 442 | ||
443 | /* Do DIO, as that's all we support now.. */ | 443 | /* Do DIO, as that's all we support now.. */ |
444 | while ((sdev = comedi_find_subdevice_by_type(d, COMEDI_SUBD_DIO, | 444 | while ((sdev = comedi_find_subdevice_by_type(d, COMEDI_SUBD_DIO, |
445 | sdev + 1)) > -1) { | 445 | sdev + 1)) > -1) { |
446 | nchans = comedi_get_n_channels(d, sdev); | 446 | nchans = comedi_get_n_channels(d, sdev); |
447 | if (nchans <= 0) { | 447 | if (nchans <= 0) { |
448 | ERROR("comedi_get_n_channels() returned %d " | 448 | ERROR("comedi_get_n_channels() returned %d " |
449 | "on minor %u subdev %d!\n", | 449 | "on minor %u subdev %d!\n", |
450 | nchans, minor, sdev); | 450 | nchans, minor, sdev); |
451 | return 0; | 451 | return 0; |
452 | } | 452 | } |
453 | bdev = kmalloc(sizeof(*bdev), GFP_KERNEL); | 453 | bdev = kmalloc(sizeof(*bdev), GFP_KERNEL); |
454 | if (!bdev) { | 454 | if (!bdev) { |
455 | ERROR("Out of memory.\n"); | 455 | ERROR("Out of memory.\n"); |
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | bdev->dev = d; | 458 | bdev->dev = d; |
459 | bdev->minor = minor; | 459 | bdev->minor = minor; |
460 | bdev->subdev = sdev; | 460 | bdev->subdev = sdev; |
461 | bdev->subdev_type = COMEDI_SUBD_DIO; | 461 | bdev->subdev_type = COMEDI_SUBD_DIO; |
462 | bdev->nchans = nchans; | 462 | bdev->nchans = nchans; |
463 | bdev->chanid_offset = devpriv->nchans; | 463 | bdev->chanid_offset = devpriv->nchans; |
464 | 464 | ||
465 | /* map channel id's to BondedDevice * pointer.. */ | 465 | /* map channel id's to BondedDevice * pointer.. */ |
466 | while (nchans--) | 466 | while (nchans--) |
467 | devpriv->chanIdDevMap[devpriv->nchans++] = bdev; | 467 | devpriv->chanIdDevMap[devpriv->nchans++] = bdev; |
468 | 468 | ||
469 | /* Now put bdev pointer at end of devpriv->devs array | 469 | /* Now put bdev pointer at end of devpriv->devs array |
470 | * list.. */ | 470 | * list.. */ |
471 | 471 | ||
472 | /* ergh.. ugly.. we need to realloc :( */ | 472 | /* ergh.. ugly.. we need to realloc :( */ |
473 | tmp = devpriv->ndevs * sizeof(bdev); | 473 | tmp = devpriv->ndevs * sizeof(bdev); |
474 | devpriv->devs = | 474 | devpriv->devs = |
475 | Realloc(devpriv->devs, | 475 | Realloc(devpriv->devs, |
476 | ++devpriv->ndevs * sizeof(bdev), tmp); | 476 | ++devpriv->ndevs * sizeof(bdev), tmp); |
477 | if (!devpriv->devs) { | 477 | if (!devpriv->devs) { |
478 | ERROR("Could not allocate memory. " | 478 | ERROR("Could not allocate memory. " |
479 | "Out of memory?"); | 479 | "Out of memory?"); |
480 | return 0; | 480 | return 0; |
481 | } | 481 | } |
482 | 482 | ||
483 | devpriv->devs[devpriv->ndevs - 1] = bdev; | 483 | devpriv->devs[devpriv->ndevs - 1] = bdev; |
484 | { | 484 | { |
485 | /** Append dev:subdev to devpriv->name */ | 485 | /** Append dev:subdev to devpriv->name */ |
486 | char buf[20]; | 486 | char buf[20]; |
487 | int left = | 487 | int left = |
488 | MAX_BOARD_NAME - strlen(devpriv->name) - 1; | 488 | MAX_BOARD_NAME - strlen(devpriv->name) - 1; |
489 | snprintf(buf, sizeof(buf), "%d:%d ", dev->minor, | 489 | snprintf(buf, sizeof(buf), "%d:%d ", dev->minor, |
490 | bdev->subdev); | 490 | bdev->subdev); |
491 | buf[sizeof(buf) - 1] = 0; | 491 | buf[sizeof(buf) - 1] = 0; |
492 | strncat(devpriv->name, buf, left); | 492 | strncat(devpriv->name, buf, left); |
493 | } | 493 | } |
494 | 494 | ||
495 | } | 495 | } |
496 | } | 496 | } |
497 | 497 | ||
498 | if (!devpriv->nchans) { | 498 | if (!devpriv->nchans) { |
499 | ERROR("No channels found!\n"); | 499 | ERROR("No channels found!\n"); |
500 | return 0; | 500 | return 0; |
501 | } | 501 | } |
502 | 502 | ||
503 | return 1; | 503 | return 1; |
504 | } | 504 | } |
505 | 505 | ||
506 | static void doDevUnconfig(struct comedi_device *dev) | 506 | static void doDevUnconfig(struct comedi_device *dev) |
507 | { | 507 | { |
508 | unsigned long devs_closed = 0; | 508 | unsigned long devs_closed = 0; |
509 | 509 | ||
510 | if (devpriv) { | 510 | if (devpriv) { |
511 | while (devpriv->ndevs-- && devpriv->devs) { | 511 | while (devpriv->ndevs-- && devpriv->devs) { |
512 | struct BondedDevice *bdev; | 512 | struct BondedDevice *bdev; |
513 | 513 | ||
514 | bdev = devpriv->devs[devpriv->ndevs]; | 514 | bdev = devpriv->devs[devpriv->ndevs]; |
515 | if (!bdev) | 515 | if (!bdev) |
516 | continue; | 516 | continue; |
517 | if (!(devs_closed & (0x1 << bdev->minor))) { | 517 | if (!(devs_closed & (0x1 << bdev->minor))) { |
518 | comedi_close(bdev->dev); | 518 | comedi_close(bdev->dev); |
519 | devs_closed |= (0x1 << bdev->minor); | 519 | devs_closed |= (0x1 << bdev->minor); |
520 | } | 520 | } |
521 | kfree(bdev); | 521 | kfree(bdev); |
522 | } | 522 | } |
523 | kfree(devpriv->devs); | 523 | kfree(devpriv->devs); |
524 | devpriv->devs = NULL; | 524 | devpriv->devs = NULL; |
525 | kfree(devpriv); | 525 | kfree(devpriv); |
526 | dev->private = NULL; | 526 | dev->private = NULL; |
527 | } | 527 | } |
528 | } | 528 | } |
529 | 529 | ||
530 | static int __init init(void) | 530 | static int __init init(void) |
531 | { | 531 | { |
532 | return comedi_driver_register(&driver_bonding); | 532 | return comedi_driver_register(&driver_bonding); |
533 | } | 533 | } |
534 | 534 | ||
535 | static void __exit cleanup(void) | 535 | static void __exit cleanup(void) |
536 | { | 536 | { |
537 | comedi_driver_unregister(&driver_bonding); | 537 | comedi_driver_unregister(&driver_bonding); |
538 | } | 538 | } |
539 | 539 | ||
540 | module_init(init); | 540 | module_init(init); |
drivers/staging/comedi/internal.h
1 | /* | 1 | /* |
2 | * various internal comedi functions | 2 | * various internal comedi functions |
3 | */ | 3 | */ |
4 | int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg); | 4 | int do_rangeinfo_ioctl(struct comedi_device *dev, |
5 | struct comedi_rangeinfo __user *arg); | ||
5 | int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, | 6 | int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, |
6 | struct comedi_insn *insn, unsigned int *data); | 7 | struct comedi_insn *insn, unsigned int *data); |
7 | int comedi_alloc_board_minor(struct device *hardware_device); | 8 | int comedi_alloc_board_minor(struct device *hardware_device); |
8 | void comedi_free_board_minor(unsigned minor); | 9 | void comedi_free_board_minor(unsigned minor); |
9 | void comedi_reset_async_buf(struct comedi_async *async); | 10 | void comedi_reset_async_buf(struct comedi_async *async); |
10 | 11 |
drivers/staging/comedi/range.c
1 | /* | 1 | /* |
2 | module/range.c | 2 | module/range.c |
3 | comedi routines for voltage ranges | 3 | comedi routines for voltage ranges |
4 | 4 | ||
5 | COMEDI - Linux Control and Measurement Device Interface | 5 | COMEDI - Linux Control and Measurement Device Interface |
6 | Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> | 6 | Copyright (C) 1997-8 David A. Schleef <ds@schleef.org> |
7 | 7 | ||
8 | This program is free software; you can redistribute it and/or modify | 8 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | 9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or | 10 | the Free Software Foundation; either version 2 of the License, or |
11 | (at your option) any later version. | 11 | (at your option) any later version. |
12 | 12 | ||
13 | This program is distributed in the hope that it will be useful, | 13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. | 16 | GNU General Public License for more details. |
17 | 17 | ||
18 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software | 19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | 21 | ||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "comedidev.h" | ||
25 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
25 | #include "comedidev.h" | ||
26 | #include "internal.h" | ||
26 | 27 | ||
27 | const struct comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} }; | 28 | const struct comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} }; |
28 | EXPORT_SYMBOL(range_bipolar10); | 29 | EXPORT_SYMBOL(range_bipolar10); |
29 | const struct comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} }; | 30 | const struct comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} }; |
30 | EXPORT_SYMBOL(range_bipolar5); | 31 | EXPORT_SYMBOL(range_bipolar5); |
31 | const struct comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} }; | 32 | const struct comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} }; |
32 | EXPORT_SYMBOL(range_bipolar2_5); | 33 | EXPORT_SYMBOL(range_bipolar2_5); |
33 | const struct comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} }; | 34 | const struct comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} }; |
34 | EXPORT_SYMBOL(range_unipolar10); | 35 | EXPORT_SYMBOL(range_unipolar10); |
35 | const struct comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} }; | 36 | const struct comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} }; |
36 | EXPORT_SYMBOL(range_unipolar5); | 37 | EXPORT_SYMBOL(range_unipolar5); |
37 | const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none} } }; | 38 | const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none} } }; |
38 | EXPORT_SYMBOL(range_unknown); | 39 | EXPORT_SYMBOL(range_unknown); |
39 | 40 | ||
40 | /* | 41 | /* |
41 | COMEDI_RANGEINFO | 42 | COMEDI_RANGEINFO |
42 | range information ioctl | 43 | range information ioctl |
43 | 44 | ||
44 | arg: | 45 | arg: |
45 | pointer to rangeinfo structure | 46 | pointer to rangeinfo structure |
46 | 47 | ||
47 | reads: | 48 | reads: |
48 | range info structure | 49 | range info structure |
49 | 50 | ||
50 | writes: | 51 | writes: |
51 | n struct comedi_krange structures to rangeinfo->range_ptr | 52 | n struct comedi_krange structures to rangeinfo->range_ptr |
52 | */ | 53 | */ |
53 | int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg) | 54 | int do_rangeinfo_ioctl(struct comedi_device *dev, |
55 | struct comedi_rangeinfo __user *arg) | ||
54 | { | 56 | { |
55 | struct comedi_rangeinfo it; | 57 | struct comedi_rangeinfo it; |
56 | int subd, chan; | 58 | int subd, chan; |
57 | const struct comedi_lrange *lr; | 59 | const struct comedi_lrange *lr; |
58 | struct comedi_subdevice *s; | 60 | struct comedi_subdevice *s; |
59 | 61 | ||
60 | if (copy_from_user(&it, arg, sizeof(struct comedi_rangeinfo))) | 62 | if (copy_from_user(&it, arg, sizeof(struct comedi_rangeinfo))) |
61 | return -EFAULT; | 63 | return -EFAULT; |
62 | subd = (it.range_type >> 24) & 0xf; | 64 | subd = (it.range_type >> 24) & 0xf; |
63 | chan = (it.range_type >> 16) & 0xff; | 65 | chan = (it.range_type >> 16) & 0xff; |
64 | 66 | ||
65 | if (!dev->attached) | 67 | if (!dev->attached) |
66 | return -EINVAL; | 68 | return -EINVAL; |
67 | if (subd >= dev->n_subdevices) | 69 | if (subd >= dev->n_subdevices) |
68 | return -EINVAL; | 70 | return -EINVAL; |
69 | s = dev->subdevices + subd; | 71 | s = dev->subdevices + subd; |
70 | if (s->range_table) { | 72 | if (s->range_table) { |
71 | lr = s->range_table; | 73 | lr = s->range_table; |
72 | } else if (s->range_table_list) { | 74 | } else if (s->range_table_list) { |
73 | if (chan >= s->n_chan) | 75 | if (chan >= s->n_chan) |
74 | return -EINVAL; | 76 | return -EINVAL; |
75 | lr = s->range_table_list[chan]; | 77 | lr = s->range_table_list[chan]; |
76 | } else { | 78 | } else { |
77 | return -EINVAL; | 79 | return -EINVAL; |
78 | } | 80 | } |
79 | 81 | ||
80 | if (RANGE_LENGTH(it.range_type) != lr->length) { | 82 | if (RANGE_LENGTH(it.range_type) != lr->length) { |
81 | DPRINTK("wrong length %d should be %d (0x%08x)\n", | 83 | DPRINTK("wrong length %d should be %d (0x%08x)\n", |
82 | RANGE_LENGTH(it.range_type), lr->length, it.range_type); | 84 | RANGE_LENGTH(it.range_type), lr->length, it.range_type); |
83 | return -EINVAL; | 85 | return -EINVAL; |
84 | } | 86 | } |
85 | 87 | ||
86 | if (copy_to_user(it.range_ptr, lr->range, | 88 | if (copy_to_user(it.range_ptr, lr->range, |
87 | sizeof(struct comedi_krange) * lr->length)) | 89 | sizeof(struct comedi_krange) * lr->length)) |
88 | return -EFAULT; | 90 | return -EFAULT; |
89 | 91 | ||
90 | return 0; | 92 | return 0; |
91 | } | 93 | } |
92 | 94 | ||
93 | static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec) | 95 | static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec) |
94 | { | 96 | { |
95 | unsigned int aref; | 97 | unsigned int aref; |
96 | 98 | ||
97 | /* disable reporting invalid arefs... maybe someday */ | 99 | /* disable reporting invalid arefs... maybe someday */ |
98 | return 0; | 100 | return 0; |
99 | 101 | ||
100 | aref = CR_AREF(chanspec); | 102 | aref = CR_AREF(chanspec); |
101 | switch (aref) { | 103 | switch (aref) { |
102 | case AREF_DIFF: | 104 | case AREF_DIFF: |
103 | if (s->subdev_flags & SDF_DIFF) | 105 | if (s->subdev_flags & SDF_DIFF) |
104 | return 0; | 106 | return 0; |
105 | break; | 107 | break; |
106 | case AREF_COMMON: | 108 | case AREF_COMMON: |
107 | if (s->subdev_flags & SDF_COMMON) | 109 | if (s->subdev_flags & SDF_COMMON) |
108 | return 0; | 110 | return 0; |
109 | break; | 111 | break; |
110 | case AREF_GROUND: | 112 | case AREF_GROUND: |
111 | if (s->subdev_flags & SDF_GROUND) | 113 | if (s->subdev_flags & SDF_GROUND) |
112 | return 0; | 114 | return 0; |
113 | break; | 115 | break; |
114 | case AREF_OTHER: | 116 | case AREF_OTHER: |
115 | if (s->subdev_flags & SDF_OTHER) | 117 | if (s->subdev_flags & SDF_OTHER) |
116 | return 0; | 118 | return 0; |
117 | break; | 119 | break; |
118 | default: | 120 | default: |
119 | break; | 121 | break; |
120 | } | 122 | } |
121 | DPRINTK("subdevice does not support aref %i", aref); | 123 | DPRINTK("subdevice does not support aref %i", aref); |
122 | return 1; | 124 | return 1; |
123 | } | 125 | } |
124 | 126 | ||
125 | /* | 127 | /* |
126 | This function checks each element in a channel/gain list to make | 128 | This function checks each element in a channel/gain list to make |
127 | make sure it is valid. | 129 | make sure it is valid. |
128 | */ | 130 | */ |
129 | int comedi_check_chanlist(struct comedi_subdevice *s, int n, | 131 | int comedi_check_chanlist(struct comedi_subdevice *s, int n, |
130 | unsigned int *chanlist) | 132 | unsigned int *chanlist) |
131 | { | 133 | { |
132 | int i; | 134 | int i; |
133 | int chan; | 135 | int chan; |
134 | 136 | ||
135 | if (s->range_table) { | 137 | if (s->range_table) { |
136 | for (i = 0; i < n; i++) | 138 | for (i = 0; i < n; i++) |
137 | if (CR_CHAN(chanlist[i]) >= s->n_chan || | 139 | if (CR_CHAN(chanlist[i]) >= s->n_chan || |
138 | CR_RANGE(chanlist[i]) >= s->range_table->length | 140 | CR_RANGE(chanlist[i]) >= s->range_table->length |
139 | || aref_invalid(s, chanlist[i])) { | 141 | || aref_invalid(s, chanlist[i])) { |
140 | printk(KERN_ERR "bad chanlist[%d]=0x%08x " | 142 | printk(KERN_ERR "bad chanlist[%d]=0x%08x " |
141 | "in_chan=%d range length=%d\n", i, | 143 | "in_chan=%d range length=%d\n", i, |
142 | chanlist[i], s->n_chan, | 144 | chanlist[i], s->n_chan, |
143 | s->range_table->length); | 145 | s->range_table->length); |
144 | return -EINVAL; | 146 | return -EINVAL; |
145 | } | 147 | } |
146 | } else if (s->range_table_list) { | 148 | } else if (s->range_table_list) { |
147 | for (i = 0; i < n; i++) { | 149 | for (i = 0; i < n; i++) { |
148 | chan = CR_CHAN(chanlist[i]); | 150 | chan = CR_CHAN(chanlist[i]); |
149 | if (chan >= s->n_chan || | 151 | if (chan >= s->n_chan || |
150 | CR_RANGE(chanlist[i]) >= | 152 | CR_RANGE(chanlist[i]) >= |
151 | s->range_table_list[chan]->length | 153 | s->range_table_list[chan]->length |
152 | || aref_invalid(s, chanlist[i])) { | 154 | || aref_invalid(s, chanlist[i])) { |
153 | printk(KERN_ERR "bad chanlist[%d]=0x%08x\n", | 155 | printk(KERN_ERR "bad chanlist[%d]=0x%08x\n", |
154 | i, chanlist[i]); | 156 | i, chanlist[i]); |
155 | return -EINVAL; | 157 | return -EINVAL; |
156 | } | 158 | } |
157 | } | 159 | } |
158 | } else { | 160 | } else { |
159 | printk(KERN_ERR "comedi: (bug) no range type list!\n"); | 161 | printk(KERN_ERR "comedi: (bug) no range type list!\n"); |
160 | return -EINVAL; | 162 | return -EINVAL; |
161 | } | 163 | } |
162 | return 0; | 164 | return 0; |
163 | } | 165 | } |
164 | EXPORT_SYMBOL(comedi_check_chanlist); | 166 | EXPORT_SYMBOL(comedi_check_chanlist); |