1 /*
2 comedi/drivers/amplc_pci230.c
3 Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
4
5 Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
6
7 COMEDI - Linux Control and Measurement Device Interface
8 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24 /*
25 Driver: amplc_pci230
26 Description: Amplicon PCI230, PCI260 Multifunction I/O boards
27 Author: Allan Willcox <allanwillcox@ozemail.com.au>,
28 Steve D Sharples <steve.sharples@nottingham.ac.uk>,
29 Ian Abbott <abbotti@mev.co.uk>
30 Updated: Wed, 22 Oct 2008 12:34:49 +0100
31 Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
32 PCI230+ (pci230+ or amplc_pci230),
33 PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
34 Status: works
35
36 Configuration options:
37 [0] - PCI bus of device (optional).
38 [1] - PCI slot of device (optional).
39 If bus/slot is not specified, the first available PCI device
40 will be used.
41
42 Configuring a "amplc_pci230" will match any supported card and it will
43 choose the best match, picking the "+" models if possible. Configuring
44 a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
45 a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card
46 and it will be treated as a PCI260. Configuring a "pci230+" will match
47 a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card.
48
49 Subdevices:
50
51 PCI230(+) PCI260(+)
52 --------- ---------
53 Subdevices 3 1
54 0 AI AI
55 1 AO
56 2 DIO
57
58 AI Subdevice:
59
60 The AI subdevice has 16 single-ended channels or 8 differential
61 channels.
62
63 The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and
64 PCI260+ cards have 16-bit resolution.
65
66 For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
67 inputs 14 and 15 for channel 7). If the card is physically a PCI230
68 or PCI260 then it actually uses a "pseudo-differential" mode where the
69 inputs are sampled a few microseconds apart. The PCI230+ and PCI260+
70 use true differential sampling. Another difference is that if the
71 card is physically a PCI230 or PCI260, the inverting input is 2N,
72 whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a
73 PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
74 PCI260+) and differential mode is used, the differential inputs need
75 to be physically swapped on the connector.
76
77 The following input ranges are supported:
78
79 0 => [-10, +10] V
80 1 => [-5, +5] V
81 2 => [-2.5, +2.5] V
82 3 => [-1.25, +1.25] V
83 4 => [0, 10] V
84 5 => [0, 5] V
85 6 => [0, 2.5] V
86
87 AI Commands:
88
89 +=========+==============+===========+============+==========+
90 |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
91 +=========+==============+===========+============+==========+
92 |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
93 |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT|
94 | | |TRIG_INT | | |
95 | |--------------|-----------| | |
96 | | TRIG_TIMER(1)|TRIG_TIMER | | |
97 | | TRIG_EXT(2) | | | |
98 | | TRIG_INT | | | |
99 +---------+--------------+-----------+------------+----------+
100
101 Note 1: If AI command and AO command are used simultaneously, only
102 one may have scan_begin_src == TRIG_TIMER.
103
104 Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
105 DIO channel 16 (pin 49) which will need to be configured as
106 a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input
107 (pin 17) is used instead. For PCI230, scan_begin_src ==
108 TRIG_EXT is not supported. The trigger is a rising edge
109 on the input.
110
111 Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
112 (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The
113 convert_arg value is interpreted as follows:
114
115 convert_arg == (CR_EDGE | 0) => rising edge
116 convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
117 convert_arg == 0 => falling edge (backwards compatibility)
118 convert_arg == 1 => rising edge (backwards compatibility)
119
120 All entries in the channel list must use the same analogue reference.
121 If the analogue reference is not AREF_DIFF (not differential) each
122 pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
123 input range. The input ranges used in the sequence must be all
124 bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel
125 sequence must consist of 1 or more identical subsequences. Within the
126 subsequence, channels must be in ascending order with no repeated
127 channels. For example, the following sequences are valid: 0 1 2 3
128 (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
129 subsequence), 1 1 1 1 (repeated valid subsequence). The following
130 sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
131 (incompletely repeated subsequence). Some versions of the PCI230+ and
132 PCI260+ have a bug that requires a subsequence longer than one entry
133 long to include channel 0.
134
135 AO Subdevice:
136
137 The AO subdevice has 2 channels with 12-bit resolution.
138
139 The following output ranges are supported:
140
141 0 => [0, 10] V
142 1 => [-10, +10] V
143
144 AO Commands:
145
146 +=========+==============+===========+============+==========+
147 |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
148 +=========+==============+===========+============+==========+
149 |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE |
150 | | TRIG_EXT(2) | | |TRIG_COUNT|
151 | | TRIG_INT | | | |
152 +---------+--------------+-----------+------------+----------+
153
154 Note 1: If AI command and AO command are used simultaneously, only
155 one may have scan_begin_src == TRIG_TIMER.
156
157 Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
158 configured as a PCI230+ and is only supported on later
159 versions of the card. As a card configured as a PCI230+ is
160 not guaranteed to support external triggering, please consider
161 this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK
162 input (PCI230+ pin 25). Triggering will be on the rising edge
163 unless the CR_INVERT flag is set in scan_begin_arg.
164
165 The channels in the channel sequence must be in ascending order with
166 no repeats. All entries in the channel sequence must use the same
167 output range.
168
169 DIO Subdevice:
170
171 The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO
172 channels are configurable as inputs or outputs in four groups:
173
174 Port A - channels 0 to 7
175 Port B - channels 8 to 15
176 Port CL - channels 16 to 19
177 Port CH - channels 20 to 23
178
179 Only mode 0 of the 8255 chip is supported.
180
181 Bit 0 of port C (DIO channel 16) is also used as an external scan
182 trigger input for AI commands on PCI230 and PCI230+, so would need to
183 be configured as an input to use it for that purpose.
184 */
185 /*
186 Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples.
187 Support for PCI230+/260+, more triggered scan functionality, and workarounds
188 for (or detection of) various hardware problems added by Ian Abbott.
189 */
190
191 #include "../comedidev.h"
192
193 #include <linux/delay.h>
194 #include <linux/interrupt.h>
195
196 #include "comedi_pci.h"
197 #include "8253.h"
198 #include "8255.h"
199
200 /* PCI230 PCI configuration register information */
201 #define PCI_VENDOR_ID_AMPLICON 0x14dc
202 #define PCI_DEVICE_ID_PCI230 0x0000
203 #define PCI_DEVICE_ID_PCI260 0x0006
204 #define PCI_DEVICE_ID_INVALID 0xffff
205
206 #define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */
207 #define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */
208
209 /* PCI230 i/o space 1 registers. */
210 #define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */
211 #define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */
212 #define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */
213 #define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */
214 #define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */
215 #define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */
216 #define PCI230_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
217 #define PCI230_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
218 #define PCI230_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
219 #define PCI230_Z2_CTC 0x17 /* 82C54 counter/timer control word */
220 #define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */
221 #define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */
222 #define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */
223 #define PCI230_INT_STAT 0x1E /* Interrupt status (r) */
224
225 /* PCI230 i/o space 2 registers. */
226 #define PCI230_DACCON 0x00 /* DAC control */
227 #define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */
228 #define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */
229 #define PCI230_ADCDATA 0x08 /* ADC data (r) */
230 #define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */
231 #define PCI230_ADCCON 0x0A /* ADC control */
232 #define PCI230_ADCEN 0x0C /* ADC channel enable bits */
233 #define PCI230_ADCG 0x0E /* ADC gain control bits */
234 /* PCI230+ i/o space 2 additional registers. */
235 #define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */
236 #define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */
237 #define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */
238 #define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */
239 #define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */
240 #define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */
241 #define PCI230P_EXTFUNC 0x1C /* Extended functions */
242 #define PCI230P_HWVER 0x1E /* Hardware version (r) */
243 /* PCI230+ hardware version 2 onwards. */
244 #define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */
245 #define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */
246 #define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */
247
248 /* Convertor related constants. */
249 #define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs */
250 /* (DAC itself is 1µs nominally). */
251 #define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs */
252 /* (ADC itself is 1.6µs nominally but we poll
253 * anyway). */
254 #define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS */
255 /* - 10µs for se, 20µs de. */
256
257 /* DACCON read-write values. */
258 #define PCI230_DAC_OR_UNI (0<<0) /* Output range unipolar */
259 #define PCI230_DAC_OR_BIP (1<<0) /* Output range bipolar */
260 #define PCI230_DAC_OR_MASK (1<<0)
261 /* The following applies only if DAC FIFO support is enabled in the EXTFUNC
262 * register (and only for PCI230+ hardware version 2 onwards). */
263 #define PCI230P2_DAC_FIFO_EN (1<<8) /* FIFO enable */
264 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
265 * hardware version 2 onwards). */
266 #define PCI230P2_DAC_TRIG_NONE (0<<2) /* No trigger */
267 #define PCI230P2_DAC_TRIG_SW (1<<2) /* Software trigger trigger */
268 #define PCI230P2_DAC_TRIG_EXTP (2<<2) /* EXTTRIG +ve edge trigger */
269 #define PCI230P2_DAC_TRIG_EXTN (3<<2) /* EXTTRIG -ve edge trigger */
270 #define PCI230P2_DAC_TRIG_Z2CT0 (4<<2) /* CT0-OUT +ve edge trigger */
271 #define PCI230P2_DAC_TRIG_Z2CT1 (5<<2) /* CT1-OUT +ve edge trigger */
272 #define PCI230P2_DAC_TRIG_Z2CT2 (6<<2) /* CT2-OUT +ve edge trigger */
273 #define PCI230P2_DAC_TRIG_MASK (7<<2)
274 #define PCI230P2_DAC_FIFO_WRAP (1<<7) /* FIFO wraparound mode */
275 #define PCI230P2_DAC_INT_FIFO_EMPTY (0<<9) /* FIFO interrupt empty */
276 #define PCI230P2_DAC_INT_FIFO_NEMPTY (1<<9)
277 #define PCI230P2_DAC_INT_FIFO_NHALF (2<<9) /* FIFO intr not half full */
278 #define PCI230P2_DAC_INT_FIFO_HALF (3<<9)
279 #define PCI230P2_DAC_INT_FIFO_NFULL (4<<9) /* FIFO interrupt not full */
280 #define PCI230P2_DAC_INT_FIFO_FULL (5<<9)
281 #define PCI230P2_DAC_INT_FIFO_MASK (7<<9)
282
283 /* DACCON read-only values. */
284 #define PCI230_DAC_BUSY (1<<1) /* DAC busy. */
285 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
286 * hardware version 2 onwards). */
287 #define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1<<5) /* Underrun error */
288 #define PCI230P2_DAC_FIFO_EMPTY (1<<13) /* FIFO empty */
289 #define PCI230P2_DAC_FIFO_FULL (1<<14) /* FIFO full */
290 #define PCI230P2_DAC_FIFO_HALF (1<<15) /* FIFO half full */
291
292 /* DACCON write-only, transient values. */
293 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
294 * hardware version 2 onwards). */
295 #define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1<<5) /* Clear underrun */
296 #define PCI230P2_DAC_FIFO_RESET (1<<12) /* FIFO reset */
297
298 /* PCI230+ hardware version 2 DAC FIFO levels. */
299 #define PCI230P2_DAC_FIFOLEVEL_HALF 512
300 #define PCI230P2_DAC_FIFOLEVEL_FULL 1024
301 /* Free space in DAC FIFO. */
302 #define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL
303 #define PCI230P2_DAC_FIFOROOM_ONETOHALF \
304 (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
305 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1
306 #define PCI230P2_DAC_FIFOROOM_FULL 0
307
308 /* ADCCON read/write values. */
309 #define PCI230_ADC_TRIG_NONE (0<<0) /* No trigger */
310 #define PCI230_ADC_TRIG_SW (1<<0) /* Software trigger trigger */
311 #define PCI230_ADC_TRIG_EXTP (2<<0) /* EXTTRIG +ve edge trigger */
312 #define PCI230_ADC_TRIG_EXTN (3<<0) /* EXTTRIG -ve edge trigger */
313 #define PCI230_ADC_TRIG_Z2CT0 (4<<0) /* CT0-OUT +ve edge trigger */
314 #define PCI230_ADC_TRIG_Z2CT1 (5<<0) /* CT1-OUT +ve edge trigger */
315 #define PCI230_ADC_TRIG_Z2CT2 (6<<0) /* CT2-OUT +ve edge trigger */
316 #define PCI230_ADC_TRIG_MASK (7<<0)
317 #define PCI230_ADC_IR_UNI (0<<3) /* Input range unipolar */
318 #define PCI230_ADC_IR_BIP (1<<3) /* Input range bipolar */
319 #define PCI230_ADC_IR_MASK (1<<3)
320 #define PCI230_ADC_IM_SE (0<<4) /* Input mode single ended */
321 #define PCI230_ADC_IM_DIF (1<<4) /* Input mode differential */
322 #define PCI230_ADC_IM_MASK (1<<4)
323 #define PCI230_ADC_FIFO_EN (1<<8) /* FIFO enable */
324 #define PCI230_ADC_INT_FIFO_EMPTY (0<<9)
325 #define PCI230_ADC_INT_FIFO_NEMPTY (1<<9) /* FIFO interrupt not empty */
326 #define PCI230_ADC_INT_FIFO_NHALF (2<<9)
327 #define PCI230_ADC_INT_FIFO_HALF (3<<9) /* FIFO interrupt half full */
328 #define PCI230_ADC_INT_FIFO_NFULL (4<<9)
329 #define PCI230_ADC_INT_FIFO_FULL (5<<9) /* FIFO interrupt full */
330 #define PCI230P_ADC_INT_FIFO_THRESH (7<<9) /* FIFO interrupt threshold */
331 #define PCI230_ADC_INT_FIFO_MASK (7<<9)
332
333 /* ADCCON write-only, transient values. */
334 #define PCI230_ADC_FIFO_RESET (1<<12) /* FIFO reset */
335 #define PCI230_ADC_GLOB_RESET (1<<13) /* Global reset */
336
337 /* ADCCON read-only values. */
338 #define PCI230_ADC_BUSY (1<<15) /* ADC busy */
339 #define PCI230_ADC_FIFO_EMPTY (1<<12) /* FIFO empty */
340 #define PCI230_ADC_FIFO_FULL (1<<13) /* FIFO full */
341 #define PCI230_ADC_FIFO_HALF (1<<14) /* FIFO half full */
342 #define PCI230_ADC_FIFO_FULL_LATCHED (1<<5) /* Indicates overrun occurred */
343
344 /* PCI230 ADC FIFO levels. */
345 #define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */
346 #define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */
347
348 /* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
349 * mode. Can be anything. */
350 #define PCI230_ADC_CONV 0xffff
351
352 /* PCI230+ EXTFUNC values. */
353 #define PCI230P_EXTFUNC_GAT_EXTTRIG (1<<0)
354 /* Route EXTTRIG pin to external gate inputs. */
355 /* PCI230+ hardware version 2 values. */
356 #define PCI230P2_EXTFUNC_DACFIFO (1<<1)
357 /* Allow DAC FIFO to be enabled. */
358
359 /*
360 * Counter/timer clock input configuration sources.
361 */
362 #define CLK_CLK 0 /* reserved (channel-specific clock) */
363 #define CLK_10MHZ 1 /* internal 10 MHz clock */
364 #define CLK_1MHZ 2 /* internal 1 MHz clock */
365 #define CLK_100KHZ 3 /* internal 100 kHz clock */
366 #define CLK_10KHZ 4 /* internal 10 kHz clock */
367 #define CLK_1KHZ 5 /* internal 1 kHz clock */
368 #define CLK_OUTNM1 6 /* output of channel-1 modulo total */
369 #define CLK_EXT 7 /* external clock */
370 /* Macro to construct clock input configuration register value. */
371 #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
372 /* Timebases in ns. */
373 #define TIMEBASE_10MHZ 100
374 #define TIMEBASE_1MHZ 1000
375 #define TIMEBASE_100KHZ 10000
376 #define TIMEBASE_10KHZ 100000
377 #define TIMEBASE_1KHZ 1000000
378
379 /*
380 * Counter/timer gate input configuration sources.
381 */
382 #define GAT_VCC 0 /* VCC (i.e. enabled) */
383 #define GAT_GND 1 /* GND (i.e. disabled) */
384 #define GAT_EXT 2 /* external gate input (PPCn on PCI230) */
385 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
386 /* Macro to construct gate input configuration register value. */
387 #define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
388
389 /*
390 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
391 *
392 * Channel's Channel's
393 * clock input gate input
394 * Channel CLK_OUTNM1 GAT_NOUTNM2
395 * ------- ---------- -----------
396 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
397 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
398 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
399 */
400
401 /* Interrupt enables/status register values. */
402 #define PCI230_INT_DISABLE 0
403 #define PCI230_INT_PPI_C0 (1<<0)
404 #define PCI230_INT_PPI_C3 (1<<1)
405 #define PCI230_INT_ADC (1<<2)
406 #define PCI230_INT_ZCLK_CT1 (1<<5)
407 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
408 #define PCI230P2_INT_DAC (1<<4)
409
410 #define PCI230_TEST_BIT(val, n) ((val>>n)&1)
411 /* Assumes bits numbered with zero offset, ie. 0-15 */
412
413 /* (Potentially) shared resources and their owners */
414 enum {
415 RES_Z2CT0, /* Z2-CT0 */
416 RES_Z2CT1, /* Z2-CT1 */
417 RES_Z2CT2, /* Z2-CT2 */
418 NUM_RESOURCES /* Number of (potentially) shared resources. */
419 };
420
421 enum {
422 OWNER_NONE, /* Not owned */
423 OWNER_AICMD, /* Owned by AI command */
424 OWNER_AOCMD /* Owned by AO command */
425 };
426
427 /*
428 * Handy macros.
429 */
430
431 /* Combine old and new bits. */
432 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
433
434 /* A generic null function pointer value. */
435 #define NULLFUNC 0
436
437 /* Current CPU. XXX should this be hard_smp_processor_id()? */
438 #define THISCPU smp_processor_id()
439
440 /* State flags for atomic bit operations */
441 #define AI_CMD_STARTED 0
442 #define AO_CMD_STARTED 1
443
444 /*
445 * Board descriptions for the two boards supported.
446 */
447
448 struct pci230_board {
449 const char *name;
450 unsigned short id;
451 int ai_chans;
452 int ai_bits;
453 int ao_chans;
454 int ao_bits;
455 int have_dio;
456 unsigned int min_hwver; /* Minimum hardware version supported. */
457 };
458 static const struct pci230_board pci230_boards[] = {
459 {
460 .name = "pci230+",
461 .id = PCI_DEVICE_ID_PCI230,
462 .ai_chans = 16,
463 .ai_bits = 16,
464 .ao_chans = 2,
465 .ao_bits = 12,
466 .have_dio = 1,
467 .min_hwver = 1,
468 },
469 {
470 .name = "pci260+",
471 .id = PCI_DEVICE_ID_PCI260,
472 .ai_chans = 16,
473 .ai_bits = 16,
474 .ao_chans = 0,
475 .ao_bits = 0,
476 .have_dio = 0,
477 .min_hwver = 1,
478 },
479 {
480 .name = "pci230",
481 .id = PCI_DEVICE_ID_PCI230,
482 .ai_chans = 16,
483 .ai_bits = 12,
484 .ao_chans = 2,
485 .ao_bits = 12,
486 .have_dio = 1,
487 },
488 {
489 .name = "pci260",
490 .id = PCI_DEVICE_ID_PCI260,
491 .ai_chans = 16,
492 .ai_bits = 12,
493 .ao_chans = 0,
494 .ao_bits = 0,
495 .have_dio = 0,
496 },
497 {
498 .name = "amplc_pci230", /* Wildcard matches any above */
499 .id = PCI_DEVICE_ID_INVALID,
500 },
501 };
502
503 static DEFINE_PCI_DEVICE_TABLE(pci230_pci_table) = {
504 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
505 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
506 {0}
507 };
508
509 MODULE_DEVICE_TABLE(pci, pci230_pci_table);
510 /*
511 * Useful for shorthand access to the particular board structure
512 */
513 #define n_pci230_boards ARRAY_SIZE(pci230_boards)
514 #define thisboard ((const struct pci230_board *)dev->board_ptr)
515
516 /* this structure is for data unique to this hardware driver. If
517 several hardware drivers keep similar information in this structure,
518 feel free to suggest moving the variable to the struct comedi_device struct. */
519 struct pci230_private {
520 struct pci_dev *pci_dev;
521 spinlock_t isr_spinlock; /* Interrupt spin lock */
522 spinlock_t res_spinlock; /* Shared resources spin lock */
523 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
524 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
525 unsigned long state; /* State flags */
526 unsigned long iobase1; /* PCI230's I/O space 1 */
527 unsigned int ao_readback[2]; /* Used for AO readback */
528 unsigned int ai_scan_count; /* Number of analogue input scans
529 * remaining. */
530 unsigned int ai_scan_pos; /* Current position within analogue
531 * input scan */
532 unsigned int ao_scan_count; /* Number of analogue output scans
533 * remaining. */
534 int intr_cpuid; /* ID of CPU running interrupt routine. */
535 unsigned short hwver; /* Hardware version (for '+' models). */
536 unsigned short adccon; /* ADCCON register value. */
537 unsigned short daccon; /* DACCON register value. */
538 unsigned short adcfifothresh; /* ADC FIFO programmable interrupt
539 * level threshold (PCI230+/260+). */
540 unsigned short adcg; /* ADCG register value. */
541 unsigned char int_en; /* Interrupt enables bits. */
542 unsigned char ai_continuous; /* Flag set when cmd->stop_src ==
543 * TRIG_NONE - user chooses to stop
544 * continuous conversion by
545 * cancelation. */
546 unsigned char ao_continuous; /* Flag set when cmd->stop_src ==
547 * TRIG_NONE - user chooses to stop
548 * continuous conversion by
549 * cancelation. */
550 unsigned char ai_bipolar; /* Set if bipolar input range so we
551 * know to mangle it. */
552 unsigned char ao_bipolar; /* Set if bipolar output range so we
553 * know to mangle it. */
554 unsigned char ier; /* Copy of interrupt enables/status register. */
555 unsigned char intr_running; /* Flag set in interrupt routine. */
556 unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */
557 };
558
559 #define devpriv ((struct pci230_private *)dev->private)
560
561 /* PCI230 clock source periods in ns */
562 static const unsigned int pci230_timebase[8] = {
563 [CLK_10MHZ] = TIMEBASE_10MHZ,
564 [CLK_1MHZ] = TIMEBASE_1MHZ,
565 [CLK_100KHZ] = TIMEBASE_100KHZ,
566 [CLK_10KHZ] = TIMEBASE_10KHZ,
567 [CLK_1KHZ] = TIMEBASE_1KHZ,
568 };
569
570 /* PCI230 analogue input range table */
571 static const struct comedi_lrange pci230_ai_range = { 7, {
572 BIP_RANGE(10),
573 BIP_RANGE(5),
574 BIP_RANGE(2.5),
575 BIP_RANGE(1.25),
576 UNI_RANGE(10),
577 UNI_RANGE(5),
578 UNI_RANGE(2.5)
579 }
580 };
581
582 /* PCI230 analogue gain bits for each input range. */
583 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
584
585 /* PCI230 adccon bipolar flag for each analogue input range. */
586 static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
587
588 /* PCI230 analogue output range table */
589 static const struct comedi_lrange pci230_ao_range = { 2, {
590 UNI_RANGE(10),
591 BIP_RANGE(10)
592 }
593 };
594
595 /* PCI230 daccon bipolar flag for each analogue output range. */
596 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
597
598 /*
599 * The struct comedi_driver structure tells the Comedi core module
600 * which functions to call to configure/deconfigure (attach/detach)
601 * the board, and also about the kernel module that contains
602 * the device code.
603 */
604 static int pci230_attach(struct comedi_device *dev,
605 struct comedi_devconfig *it);
606 static int pci230_detach(struct comedi_device *dev);
607 static struct comedi_driver driver_amplc_pci230 = {
608 .driver_name = "amplc_pci230",
609 .module = THIS_MODULE,
610 .attach = pci230_attach,
611 .detach = pci230_detach,
612 .board_name = &pci230_boards[0].name,
613 .offset = sizeof(pci230_boards[0]),
614 .num_names = ARRAY_SIZE(pci230_boards),
615 };
616
driver_amplc_pci230_pci_probe(struct pci_dev * dev,const struct pci_device_id * ent)617 static int __devinit driver_amplc_pci230_pci_probe(struct pci_dev *dev,
618 const struct pci_device_id
619 *ent)
620 {
621 return comedi_pci_auto_config(dev, driver_amplc_pci230.driver_name);
622 }
623
driver_amplc_pci230_pci_remove(struct pci_dev * dev)624 static void __devexit driver_amplc_pci230_pci_remove(struct pci_dev *dev)
625 {
626 comedi_pci_auto_unconfig(dev);
627 }
628
629 static struct pci_driver driver_amplc_pci230_pci_driver = {
630 .id_table = pci230_pci_table,
631 .probe = &driver_amplc_pci230_pci_probe,
632 .remove = __devexit_p(&driver_amplc_pci230_pci_remove)
633 };
634
driver_amplc_pci230_init_module(void)635 static int __init driver_amplc_pci230_init_module(void)
636 {
637 int retval;
638
639 retval = comedi_driver_register(&driver_amplc_pci230);
640 if (retval < 0)
641 return retval;
642
643 driver_amplc_pci230_pci_driver.name =
644 (char *)driver_amplc_pci230.driver_name;
645 return pci_register_driver(&driver_amplc_pci230_pci_driver);
646 }
647
driver_amplc_pci230_cleanup_module(void)648 static void __exit driver_amplc_pci230_cleanup_module(void)
649 {
650 pci_unregister_driver(&driver_amplc_pci230_pci_driver);
651 comedi_driver_unregister(&driver_amplc_pci230);
652 }
653
654 module_init(driver_amplc_pci230_init_module);
655 module_exit(driver_amplc_pci230_cleanup_module);
656
657 static int pci230_ai_rinsn(struct comedi_device *dev,
658 struct comedi_subdevice *s, struct comedi_insn *insn,
659 unsigned int *data);
660 static int pci230_ao_winsn(struct comedi_device *dev,
661 struct comedi_subdevice *s, struct comedi_insn *insn,
662 unsigned int *data);
663 static int pci230_ao_rinsn(struct comedi_device *dev,
664 struct comedi_subdevice *s, struct comedi_insn *insn,
665 unsigned int *data);
666 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
667 unsigned int mode, uint64_t ns,
668 unsigned int round);
669 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
670 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct);
671 static irqreturn_t pci230_interrupt(int irq, void *d);
672 static int pci230_ao_cmdtest(struct comedi_device *dev,
673 struct comedi_subdevice *s,
674 struct comedi_cmd *cmd);
675 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
676 static int pci230_ao_cancel(struct comedi_device *dev,
677 struct comedi_subdevice *s);
678 static void pci230_ao_stop(struct comedi_device *dev,
679 struct comedi_subdevice *s);
680 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
681 struct comedi_subdevice *s);
682 static int pci230_handle_ao_fifo(struct comedi_device *dev,
683 struct comedi_subdevice *s);
684 static int pci230_ai_cmdtest(struct comedi_device *dev,
685 struct comedi_subdevice *s,
686 struct comedi_cmd *cmd);
687 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
688 static int pci230_ai_cancel(struct comedi_device *dev,
689 struct comedi_subdevice *s);
690 static void pci230_ai_stop(struct comedi_device *dev,
691 struct comedi_subdevice *s);
692 static void pci230_handle_ai(struct comedi_device *dev,
693 struct comedi_subdevice *s);
694
pci230_ai_read(struct comedi_device * dev)695 static short pci230_ai_read(struct comedi_device *dev)
696 {
697 /* Read sample. */
698 short data = (short)inw(dev->iobase + PCI230_ADCDATA);
699
700 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
701 * four bits reserved for expansion). */
702 /* PCI230+ is 16 bit AI. */
703 data = data >> (16 - thisboard->ai_bits);
704
705 /* If a bipolar range was specified, mangle it (twos
706 * complement->straight binary). */
707 if (devpriv->ai_bipolar)
708 data ^= 1 << (thisboard->ai_bits - 1);
709
710 return data;
711 }
712
pci230_ao_mangle_datum(struct comedi_device * dev,short datum)713 static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
714 short datum)
715 {
716 /* If a bipolar range was specified, mangle it (straight binary->twos
717 * complement). */
718 if (devpriv->ao_bipolar)
719 datum ^= 1 << (thisboard->ao_bits - 1);
720
721
722 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
723 * four bits reserved for expansion). */
724 /* PCI230+ is also 12 bit AO. */
725 datum <<= (16 - thisboard->ao_bits);
726 return (unsigned short)datum;
727 }
728
pci230_ao_write_nofifo(struct comedi_device * dev,short datum,unsigned int chan)729 static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
730 short datum, unsigned int chan)
731 {
732 /* Store unmangled datum to be read back later. */
733 devpriv->ao_readback[chan] = datum;
734
735 /* Write mangled datum to appropriate DACOUT register. */
736 outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
737 ? PCI230_DACOUT1
738 :
739 PCI230_DACOUT2));
740 }
741
pci230_ao_write_fifo(struct comedi_device * dev,short datum,unsigned int chan)742 static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
743 unsigned int chan)
744 {
745 /* Store unmangled datum to be read back later. */
746 devpriv->ao_readback[chan] = datum;
747
748 /* Write mangled datum to appropriate DACDATA register. */
749 outw(pci230_ao_mangle_datum(dev, datum),
750 dev->iobase + PCI230P2_DACDATA);
751 }
752
753 /*
754 * Attach is called by the Comedi core to configure the driver
755 * for a particular board. If you specified a board_name array
756 * in the driver structure, dev->board_ptr contains that
757 * address.
758 */
pci230_attach(struct comedi_device * dev,struct comedi_devconfig * it)759 static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
760 {
761 struct comedi_subdevice *s;
762 unsigned long iobase1, iobase2;
763 /* PCI230's I/O spaces 1 and 2 respectively. */
764 struct pci_dev *pci_dev = NULL;
765 int i = 0, irq_hdl, rc;
766
767 printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
768 thisboard->name, it->options[0], it->options[1]);
769
770 /* Allocate the private structure area using alloc_private().
771 * Macro defined in comedidev.h - memsets struct fields to 0. */
772 if ((alloc_private(dev, sizeof(struct pci230_private))) < 0)
773 return -ENOMEM;
774
775 spin_lock_init(&devpriv->isr_spinlock);
776 spin_lock_init(&devpriv->res_spinlock);
777 spin_lock_init(&devpriv->ai_stop_spinlock);
778 spin_lock_init(&devpriv->ao_stop_spinlock);
779 /* Find card */
780 for_each_pci_dev(pci_dev) {
781 if (it->options[0] || it->options[1]) {
782 /* Match against bus/slot options. */
783 if (it->options[0] != pci_dev->bus->number ||
784 it->options[1] != PCI_SLOT(pci_dev->devfn))
785 continue;
786 }
787 if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
788 continue;
789 if (thisboard->id == PCI_DEVICE_ID_INVALID) {
790 /* The name was specified as "amplc_pci230" which is
791 * used to match any supported device. Replace the
792 * current dev->board_ptr with one that matches the
793 * PCI device ID. */
794 for (i = 0; i < n_pci230_boards; i++) {
795 if (pci_dev->device == pci230_boards[i].id) {
796 if (pci230_boards[i].min_hwver > 0) {
797 /* Check for a '+' model.
798 * First check length of
799 * registers. */
800 if (pci_resource_len(pci_dev, 3)
801 < 32) {
802 /* Not a '+' model. */
803 continue;
804 }
805 /* TODO: temporarily enable the
806 * PCI device and read the
807 * hardware version register.
808 * For now assume it's okay. */
809 }
810 /* Change board_ptr to matched board */
811 dev->board_ptr = &pci230_boards[i];
812 break;
813 }
814 }
815 if (i < n_pci230_boards)
816 break;
817 } else {
818 /* The name was specified as a specific device name.
819 * The current dev->board_ptr is correct. Check
820 * whether it matches the PCI device ID. */
821 if (thisboard->id == pci_dev->device) {
822 /* Check minimum hardware version. */
823 if (thisboard->min_hwver > 0) {
824 /* Looking for a '+' model. First
825 * check length of registers. */
826 if (pci_resource_len(pci_dev, 3) < 32) {
827 /* Not a '+' model. */
828 continue;
829 }
830 /* TODO: temporarily enable the PCI
831 * device and read the hardware version
832 * register. For now, assume it's
833 * okay. */
834 break;
835 } else {
836 break;
837 }
838 }
839 }
840 }
841 if (!pci_dev) {
842 printk("comedi%d: No %s card found\n", dev->minor,
843 thisboard->name);
844 return -EIO;
845 }
846 devpriv->pci_dev = pci_dev;
847
848 /*
849 * Initialize dev->board_name.
850 */
851 dev->board_name = thisboard->name;
852
853 /* Enable PCI device and reserve I/O spaces. */
854 if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) {
855 printk("comedi%d: failed to enable PCI device "
856 "and request regions\n", dev->minor);
857 return -EIO;
858 }
859
860 /* Read base addresses of the PCI230's two I/O regions from PCI
861 * configuration register. */
862 iobase1 = pci_resource_start(pci_dev, 2);
863 iobase2 = pci_resource_start(pci_dev, 3);
864
865 printk("comedi%d: %s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
866 dev->minor, dev->board_name, iobase1, iobase2);
867
868 devpriv->iobase1 = iobase1;
869 dev->iobase = iobase2;
870
871 /* Read bits of DACCON register - only the output range. */
872 devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
873
874 /* Read hardware version register and set extended function register
875 * if they exist. */
876 if (pci_resource_len(pci_dev, 3) >= 32) {
877 unsigned short extfunc = 0;
878
879 devpriv->hwver = inw(dev->iobase + PCI230P_HWVER);
880 if (devpriv->hwver < thisboard->min_hwver) {
881 printk("comedi%d: %s - bad hardware version "
882 "- got %u, need %u\n", dev->minor,
883 dev->board_name, devpriv->hwver,
884 thisboard->min_hwver);
885 return -EIO;
886 }
887 if (devpriv->hwver > 0) {
888 if (!thisboard->have_dio) {
889 /* No DIO ports. Route counters' external gates
890 * to the EXTTRIG signal (PCI260+ pin 17).
891 * (Otherwise, they would be routed to DIO
892 * inputs PC0, PC1 and PC2 which don't exist
893 * on PCI260[+].) */
894 extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
895 }
896 if ((thisboard->ao_chans > 0)
897 && (devpriv->hwver >= 2)) {
898 /* Enable DAC FIFO functionality. */
899 extfunc |= PCI230P2_EXTFUNC_DACFIFO;
900 }
901 }
902 outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
903 if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) {
904 /* Temporarily enable DAC FIFO, reset it and disable
905 * FIFO wraparound. */
906 outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN
907 | PCI230P2_DAC_FIFO_RESET,
908 dev->iobase + PCI230_DACCON);
909 /* Clear DAC FIFO channel enable register. */
910 outw(0, dev->iobase + PCI230P2_DACEN);
911 /* Disable DAC FIFO. */
912 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
913 }
914 }
915
916 /* Disable board's interrupts. */
917 outb(0, devpriv->iobase1 + PCI230_INT_SCE);
918
919 /* Set ADC to a reasonable state. */
920 devpriv->adcg = 0;
921 devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE
922 | PCI230_ADC_IR_BIP;
923 outw(1 << 0, dev->iobase + PCI230_ADCEN);
924 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
925 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
926 dev->iobase + PCI230_ADCCON);
927
928 /* Register the interrupt handler. */
929 irq_hdl = request_irq(devpriv->pci_dev->irq, pci230_interrupt,
930 IRQF_SHARED, "amplc_pci230", dev);
931 if (irq_hdl < 0) {
932 printk("comedi%d: unable to register irq, "
933 "commands will not be available %d\n", dev->minor,
934 devpriv->pci_dev->irq);
935 } else {
936 dev->irq = devpriv->pci_dev->irq;
937 printk("comedi%d: registered irq %u\n", dev->minor,
938 devpriv->pci_dev->irq);
939 }
940
941 /*
942 * Allocate the subdevice structures. alloc_subdevice() is a
943 * convenient macro defined in comedidev.h.
944 */
945 if (alloc_subdevices(dev, 3) < 0)
946 return -ENOMEM;
947
948 s = dev->subdevices + 0;
949 /* analog input subdevice */
950 s->type = COMEDI_SUBD_AI;
951 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
952 s->n_chan = thisboard->ai_chans;
953 s->maxdata = (1 << thisboard->ai_bits) - 1;
954 s->range_table = &pci230_ai_range;
955 s->insn_read = &pci230_ai_rinsn;
956 s->len_chanlist = 256; /* but there are restrictions. */
957 /* Only register commands if the interrupt handler is installed. */
958 if (irq_hdl == 0) {
959 dev->read_subdev = s;
960 s->subdev_flags |= SDF_CMD_READ;
961 s->do_cmd = &pci230_ai_cmd;
962 s->do_cmdtest = &pci230_ai_cmdtest;
963 s->cancel = pci230_ai_cancel;
964 }
965
966 s = dev->subdevices + 1;
967 /* analog output subdevice */
968 if (thisboard->ao_chans > 0) {
969 s->type = COMEDI_SUBD_AO;
970 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
971 s->n_chan = thisboard->ao_chans;
972 s->maxdata = (1 << thisboard->ao_bits) - 1;
973 s->range_table = &pci230_ao_range;
974 s->insn_write = &pci230_ao_winsn;
975 s->insn_read = &pci230_ao_rinsn;
976 s->len_chanlist = thisboard->ao_chans;
977 /* Only register commands if the interrupt handler is
978 * installed. */
979 if (irq_hdl == 0) {
980 dev->write_subdev = s;
981 s->subdev_flags |= SDF_CMD_WRITE;
982 s->do_cmd = &pci230_ao_cmd;
983 s->do_cmdtest = &pci230_ao_cmdtest;
984 s->cancel = pci230_ao_cancel;
985 }
986 } else {
987 s->type = COMEDI_SUBD_UNUSED;
988 }
989
990 s = dev->subdevices + 2;
991 /* digital i/o subdevice */
992 if (thisboard->have_dio) {
993 rc = subdev_8255_init(dev, s, NULL,
994 (devpriv->iobase1 + PCI230_PPI_X_BASE));
995 if (rc < 0)
996 return rc;
997 } else {
998 s->type = COMEDI_SUBD_UNUSED;
999 }
1000
1001 printk("comedi%d: attached\n", dev->minor);
1002
1003 return 1;
1004 }
1005
1006 /*
1007 * _detach is called to deconfigure a device. It should deallocate
1008 * resources.
1009 * This function is also called when _attach() fails, so it should be
1010 * careful not to release resources that were not necessarily
1011 * allocated by _attach(). dev->private and dev->subdevices are
1012 * deallocated automatically by the core.
1013 */
pci230_detach(struct comedi_device * dev)1014 static int pci230_detach(struct comedi_device *dev)
1015 {
1016 printk("comedi%d: amplc_pci230: remove\n", dev->minor);
1017
1018 if (dev->subdevices && thisboard->have_dio)
1019 /* Clean up dio subdevice. */
1020 subdev_8255_cleanup(dev, dev->subdevices + 2);
1021
1022 if (dev->irq)
1023 free_irq(dev->irq, dev);
1024
1025 if (devpriv) {
1026 if (devpriv->pci_dev) {
1027 if (dev->iobase)
1028 comedi_pci_disable(devpriv->pci_dev);
1029
1030 pci_dev_put(devpriv->pci_dev);
1031 }
1032 }
1033
1034 return 0;
1035 }
1036
get_resources(struct comedi_device * dev,unsigned int res_mask,unsigned char owner)1037 static int get_resources(struct comedi_device *dev, unsigned int res_mask,
1038 unsigned char owner)
1039 {
1040 int ok;
1041 unsigned int i;
1042 unsigned int b;
1043 unsigned int claimed;
1044 unsigned long irqflags;
1045
1046 ok = 1;
1047 claimed = 0;
1048 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
1049 for (b = 1, i = 0; (i < NUM_RESOURCES)
1050 && (res_mask != 0); b <<= 1, i++) {
1051 if ((res_mask & b) != 0) {
1052 res_mask &= ~b;
1053 if (devpriv->res_owner[i] == OWNER_NONE) {
1054 devpriv->res_owner[i] = owner;
1055 claimed |= b;
1056 } else if (devpriv->res_owner[i] != owner) {
1057 for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
1058 if ((claimed & b) != 0) {
1059 devpriv->res_owner[i]
1060 = OWNER_NONE;
1061 claimed &= ~b;
1062 }
1063 }
1064 ok = 0;
1065 break;
1066 }
1067 }
1068 }
1069 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
1070 return ok;
1071 }
1072
get_one_resource(struct comedi_device * dev,unsigned int resource,unsigned char owner)1073 static inline int get_one_resource(struct comedi_device *dev,
1074 unsigned int resource, unsigned char owner)
1075 {
1076 return get_resources(dev, (1U << resource), owner);
1077 }
1078
put_resources(struct comedi_device * dev,unsigned int res_mask,unsigned char owner)1079 static void put_resources(struct comedi_device *dev, unsigned int res_mask,
1080 unsigned char owner)
1081 {
1082 unsigned int i;
1083 unsigned int b;
1084 unsigned long irqflags;
1085
1086 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
1087 for (b = 1, i = 0; (i < NUM_RESOURCES)
1088 && (res_mask != 0); b <<= 1, i++) {
1089 if ((res_mask & b) != 0) {
1090 res_mask &= ~b;
1091 if (devpriv->res_owner[i] == owner)
1092 devpriv->res_owner[i] = OWNER_NONE;
1093
1094 }
1095 }
1096 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
1097 }
1098
put_one_resource(struct comedi_device * dev,unsigned int resource,unsigned char owner)1099 static inline void put_one_resource(struct comedi_device *dev,
1100 unsigned int resource, unsigned char owner)
1101 {
1102 put_resources(dev, (1U << resource), owner);
1103 }
1104
put_all_resources(struct comedi_device * dev,unsigned char owner)1105 static inline void put_all_resources(struct comedi_device *dev,
1106 unsigned char owner)
1107 {
1108 put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
1109 }
1110
1111 /*
1112 * COMEDI_SUBD_AI instruction;
1113 */
pci230_ai_rinsn(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1114 static int pci230_ai_rinsn(struct comedi_device *dev,
1115 struct comedi_subdevice *s, struct comedi_insn *insn,
1116 unsigned int *data)
1117 {
1118 unsigned int n, i;
1119 unsigned int chan, range, aref;
1120 unsigned int gainshift;
1121 unsigned int status;
1122 unsigned short adccon, adcen;
1123
1124 /* Unpack channel and range. */
1125 chan = CR_CHAN(insn->chanspec);
1126 range = CR_RANGE(insn->chanspec);
1127 aref = CR_AREF(insn->chanspec);
1128 if (aref == AREF_DIFF) {
1129 /* Differential. */
1130 if (chan >= s->n_chan / 2) {
1131 DPRINTK("comedi%d: amplc_pci230: ai_rinsn: "
1132 "differential channel number out of range "
1133 "0 to %u\n", dev->minor, (s->n_chan / 2) - 1);
1134 return -EINVAL;
1135 }
1136 }
1137
1138 /* Use Z2-CT2 as a conversion trigger instead of the built-in
1139 * software trigger, as otherwise triggering of differential channels
1140 * doesn't work properly for some versions of PCI230/260. Also set
1141 * FIFO mode because the ADC busy bit only works for software triggers.
1142 */
1143 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
1144 /* Set Z2-CT2 output low to avoid any false triggers. */
1145 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
1146 devpriv->ai_bipolar = pci230_ai_bipolar[range];
1147 if (aref == AREF_DIFF) {
1148 /* Differential. */
1149 gainshift = chan * 2;
1150 if (devpriv->hwver == 0) {
1151 /* Original PCI230/260 expects both inputs of the
1152 * differential channel to be enabled. */
1153 adcen = 3 << gainshift;
1154 } else {
1155 /* PCI230+/260+ expects only one input of the
1156 * differential channel to be enabled. */
1157 adcen = 1 << gainshift;
1158 }
1159 adccon |= PCI230_ADC_IM_DIF;
1160 } else {
1161 /* Single ended. */
1162 adcen = 1 << chan;
1163 gainshift = chan & ~1;
1164 adccon |= PCI230_ADC_IM_SE;
1165 }
1166 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
1167 | (pci230_ai_gain[range] << gainshift);
1168 if (devpriv->ai_bipolar)
1169 adccon |= PCI230_ADC_IR_BIP;
1170 else
1171 adccon |= PCI230_ADC_IR_UNI;
1172
1173
1174 /* Enable only this channel in the scan list - otherwise by default
1175 * we'll get one sample from each channel. */
1176 outw(adcen, dev->iobase + PCI230_ADCEN);
1177
1178 /* Set gain for channel. */
1179 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
1180
1181 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
1182 devpriv->adccon = adccon;
1183 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
1184
1185 /* Convert n samples */
1186 for (n = 0; n < insn->n; n++) {
1187 /* Trigger conversion by toggling Z2-CT2 output (finish with
1188 * output high). */
1189 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1190 I8254_MODE0);
1191 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1192 I8254_MODE1);
1193
1194 #define TIMEOUT 100
1195 /* wait for conversion to end */
1196 for (i = 0; i < TIMEOUT; i++) {
1197 status = inw(dev->iobase + PCI230_ADCCON);
1198 if (!(status & PCI230_ADC_FIFO_EMPTY))
1199 break;
1200 udelay(1);
1201 }
1202 if (i == TIMEOUT) {
1203 /* printk() should be used instead of printk()
1204 * whenever the code can be called from real-time. */
1205 printk("timeout\n");
1206 return -ETIMEDOUT;
1207 }
1208
1209 /* read data */
1210 data[n] = pci230_ai_read(dev);
1211 }
1212
1213 /* return the number of samples read/written */
1214 return n;
1215 }
1216
1217 /*
1218 * COMEDI_SUBD_AO instructions;
1219 */
pci230_ao_winsn(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1220 static int pci230_ao_winsn(struct comedi_device *dev,
1221 struct comedi_subdevice *s, struct comedi_insn *insn,
1222 unsigned int *data)
1223 {
1224 int i;
1225 int chan, range;
1226
1227 /* Unpack channel and range. */
1228 chan = CR_CHAN(insn->chanspec);
1229 range = CR_RANGE(insn->chanspec);
1230
1231 /* Set range - see analogue output range table; 0 => unipolar 10V,
1232 * 1 => bipolar +/-10V range scale */
1233 devpriv->ao_bipolar = pci230_ao_bipolar[range];
1234 outw(range, dev->iobase + PCI230_DACCON);
1235
1236 /* Writing a list of values to an AO channel is probably not
1237 * very useful, but that's how the interface is defined. */
1238 for (i = 0; i < insn->n; i++) {
1239 /* Write value to DAC and store it. */
1240 pci230_ao_write_nofifo(dev, data[i], chan);
1241 }
1242
1243 /* return the number of samples read/written */
1244 return i;
1245 }
1246
1247 /* AO subdevices should have a read insn as well as a write insn.
1248 * Usually this means copying a value stored in devpriv. */
pci230_ao_rinsn(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1249 static int pci230_ao_rinsn(struct comedi_device *dev,
1250 struct comedi_subdevice *s, struct comedi_insn *insn,
1251 unsigned int *data)
1252 {
1253 int i;
1254 int chan = CR_CHAN(insn->chanspec);
1255
1256 for (i = 0; i < insn->n; i++)
1257 data[i] = devpriv->ao_readback[chan];
1258
1259 return i;
1260 }
1261
pci230_ao_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)1262 static int pci230_ao_cmdtest(struct comedi_device *dev,
1263 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1264 {
1265 int err = 0;
1266 unsigned int tmp;
1267
1268 /* cmdtest tests a particular command to see if it is valid.
1269 * Using the cmdtest ioctl, a user can create a valid cmd
1270 * and then have it executes by the cmd ioctl.
1271 *
1272 * cmdtest returns 1,2,3,4 or 0, depending on which tests
1273 * the command passes. */
1274
1275 /* Step 1: make sure trigger sources are trivially valid.
1276 * "invalid source" returned by comedilib to user mode process
1277 * if this fails. */
1278
1279 tmp = cmd->start_src;
1280 cmd->start_src &= TRIG_INT;
1281 if (!cmd->start_src || tmp != cmd->start_src)
1282 err++;
1283
1284 tmp = cmd->scan_begin_src;
1285 if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
1286 /*
1287 * For PCI230+ hardware version 2 onwards, allow external
1288 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
1289 *
1290 * FIXME: The permitted scan_begin_src values shouldn't depend
1291 * on devpriv->hwver (the detected card's actual hardware
1292 * version). They should only depend on thisboard->min_hwver
1293 * (the static capabilities of the configured card). To fix
1294 * it, a new card model, e.g. "pci230+2" would have to be
1295 * defined with min_hwver set to 2. It doesn't seem worth it
1296 * for this alone. At the moment, please consider
1297 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
1298 * guarantee!
1299 */
1300 cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1301 } else {
1302 cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT;
1303 }
1304 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1305 err++;
1306
1307 tmp = cmd->convert_src;
1308 cmd->convert_src &= TRIG_NOW;
1309 if (!cmd->convert_src || tmp != cmd->convert_src)
1310 err++;
1311
1312 tmp = cmd->scan_end_src;
1313 cmd->scan_end_src &= TRIG_COUNT;
1314 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1315 err++;
1316
1317 tmp = cmd->stop_src;
1318 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1319 if (!cmd->stop_src || tmp != cmd->stop_src)
1320 err++;
1321
1322 if (err)
1323 return 1;
1324
1325 /* Step 2: make sure trigger sources are unique and mutually compatible
1326 * "source conflict" returned by comedilib to user mode process
1327 * if this fails. */
1328
1329 /* these tests are true if more than one _src bit is set */
1330 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1331 err++;
1332 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1333 err++;
1334 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1335 err++;
1336 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1337 err++;
1338 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1339 err++;
1340
1341 if (err)
1342 return 2;
1343
1344 /* Step 3: make sure arguments are trivially compatible.
1345 * "invalid argument" returned by comedilib to user mode process
1346 * if this fails. */
1347
1348 if (cmd->start_arg != 0) {
1349 cmd->start_arg = 0;
1350 err++;
1351 }
1352 #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */
1353 #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */
1354 /*- Comedi limit due to unsigned int cmd. Driver limit
1355 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1356 * clock) = 65.536s */
1357
1358 switch (cmd->scan_begin_src) {
1359 case TRIG_TIMER:
1360 if (cmd->scan_begin_arg < MAX_SPEED_AO) {
1361 cmd->scan_begin_arg = MAX_SPEED_AO;
1362 err++;
1363 }
1364 if (cmd->scan_begin_arg > MIN_SPEED_AO) {
1365 cmd->scan_begin_arg = MIN_SPEED_AO;
1366 err++;
1367 }
1368 break;
1369 case TRIG_EXT:
1370 /* External trigger - for PCI230+ hardware version 2 onwards. */
1371 /* Trigger number must be 0. */
1372 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1373 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1374 ~CR_FLAGS_MASK);
1375 err++;
1376 }
1377 /* The only flags allowed are CR_EDGE and CR_INVERT. The
1378 * CR_EDGE flag is ignored. */
1379 if ((cmd->scan_begin_arg
1380 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1381 cmd->scan_begin_arg =
1382 COMBINE(cmd->scan_begin_arg, 0,
1383 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
1384 err++;
1385 }
1386 break;
1387 default:
1388 if (cmd->scan_begin_arg != 0) {
1389 cmd->scan_begin_arg = 0;
1390 err++;
1391 }
1392 break;
1393 }
1394
1395 if (cmd->scan_end_arg != cmd->chanlist_len) {
1396 cmd->scan_end_arg = cmd->chanlist_len;
1397 err++;
1398 }
1399 if (cmd->stop_src == TRIG_NONE) {
1400 /* TRIG_NONE */
1401 if (cmd->stop_arg != 0) {
1402 cmd->stop_arg = 0;
1403 err++;
1404 }
1405 }
1406
1407 if (err)
1408 return 3;
1409
1410 /* Step 4: fix up any arguments.
1411 * "argument conflict" returned by comedilib to user mode process
1412 * if this fails. */
1413
1414 if (cmd->scan_begin_src == TRIG_TIMER) {
1415 tmp = cmd->scan_begin_arg;
1416 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1417 cmd->flags & TRIG_ROUND_MASK);
1418 if (tmp != cmd->scan_begin_arg)
1419 err++;
1420 }
1421
1422 if (err)
1423 return 4;
1424
1425 /* Step 5: check channel list if it exists. */
1426
1427 if (cmd->chanlist && cmd->chanlist_len > 0) {
1428 enum {
1429 seq_err = (1 << 0),
1430 range_err = (1 << 1)
1431 };
1432 unsigned int errors;
1433 unsigned int n;
1434 unsigned int chan, prev_chan;
1435 unsigned int range, first_range;
1436
1437 prev_chan = CR_CHAN(cmd->chanlist[0]);
1438 first_range = CR_RANGE(cmd->chanlist[0]);
1439 errors = 0;
1440 for (n = 1; n < cmd->chanlist_len; n++) {
1441 chan = CR_CHAN(cmd->chanlist[n]);
1442 range = CR_RANGE(cmd->chanlist[n]);
1443 /* Channel numbers must strictly increase. */
1444 if (chan < prev_chan)
1445 errors |= seq_err;
1446
1447 /* Ranges must be the same. */
1448 if (range != first_range)
1449 errors |= range_err;
1450
1451 prev_chan = chan;
1452 }
1453 if (errors != 0) {
1454 err++;
1455 if ((errors & seq_err) != 0) {
1456 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1457 "channel numbers must increase\n",
1458 dev->minor);
1459 }
1460 if ((errors & range_err) != 0) {
1461 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1462 "channels must have the same range\n",
1463 dev->minor);
1464 }
1465 }
1466 }
1467
1468 if (err)
1469 return 5;
1470
1471 return 0;
1472 }
1473
pci230_ao_inttrig_scan_begin(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1474 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1475 struct comedi_subdevice *s,
1476 unsigned int trig_num)
1477 {
1478 unsigned long irqflags;
1479
1480 if (trig_num != 0)
1481 return -EINVAL;
1482
1483 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1484 if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
1485 /* Perform scan. */
1486 if (devpriv->hwver < 2) {
1487 /* Not using DAC FIFO. */
1488 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1489 irqflags);
1490 pci230_handle_ao_nofifo(dev, s);
1491 comedi_event(dev, s);
1492 } else {
1493 /* Using DAC FIFO. */
1494 /* Read DACSWTRIG register to trigger conversion. */
1495 inw(dev->iobase + PCI230P2_DACSWTRIG);
1496 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1497 irqflags);
1498 }
1499 /* Delay. Should driver be responsible for this? */
1500 /* XXX TODO: See if DAC busy bit can be used. */
1501 udelay(8);
1502 }
1503
1504 return 1;
1505 }
1506
pci230_ao_start(struct comedi_device * dev,struct comedi_subdevice * s)1507 static void pci230_ao_start(struct comedi_device *dev,
1508 struct comedi_subdevice *s)
1509 {
1510 struct comedi_async *async = s->async;
1511 struct comedi_cmd *cmd = &async->cmd;
1512 unsigned long irqflags;
1513
1514 set_bit(AO_CMD_STARTED, &devpriv->state);
1515 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1516 /* An empty acquisition! */
1517 async->events |= COMEDI_CB_EOA;
1518 pci230_ao_stop(dev, s);
1519 comedi_event(dev, s);
1520 } else {
1521 if (devpriv->hwver >= 2) {
1522 /* Using DAC FIFO. */
1523 unsigned short scantrig;
1524 int run;
1525
1526 /* Preload FIFO data. */
1527 run = pci230_handle_ao_fifo(dev, s);
1528 comedi_event(dev, s);
1529 if (!run) {
1530 /* Stopped. */
1531 return;
1532 }
1533 /* Set scan trigger source. */
1534 switch (cmd->scan_begin_src) {
1535 case TRIG_TIMER:
1536 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1537 break;
1538 case TRIG_EXT:
1539 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1540 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1541 /* +ve edge */
1542 scantrig = PCI230P2_DAC_TRIG_EXTP;
1543 } else {
1544 /* -ve edge */
1545 scantrig = PCI230P2_DAC_TRIG_EXTN;
1546 }
1547 break;
1548 case TRIG_INT:
1549 scantrig = PCI230P2_DAC_TRIG_SW;
1550 break;
1551 default:
1552 /* Shouldn't get here. */
1553 scantrig = PCI230P2_DAC_TRIG_NONE;
1554 break;
1555 }
1556 devpriv->daccon = (devpriv->daccon
1557 & ~PCI230P2_DAC_TRIG_MASK) |
1558 scantrig;
1559 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1560
1561 }
1562 switch (cmd->scan_begin_src) {
1563 case TRIG_TIMER:
1564 if (devpriv->hwver < 2) {
1565 /* Not using DAC FIFO. */
1566 /* Enable CT1 timer interrupt. */
1567 spin_lock_irqsave(&devpriv->isr_spinlock,
1568 irqflags);
1569 devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1570 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1571 outb(devpriv->ier,
1572 devpriv->iobase1 + PCI230_INT_SCE);
1573 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1574 irqflags);
1575 }
1576 /* Set CT1 gate high to start counting. */
1577 outb(GAT_CONFIG(1, GAT_VCC),
1578 devpriv->iobase1 + PCI230_ZGAT_SCE);
1579 break;
1580 case TRIG_INT:
1581 async->inttrig = pci230_ao_inttrig_scan_begin;
1582 break;
1583 }
1584 if (devpriv->hwver >= 2) {
1585 /* Using DAC FIFO. Enable DAC FIFO interrupt. */
1586 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1587 devpriv->int_en |= PCI230P2_INT_DAC;
1588 devpriv->ier |= PCI230P2_INT_DAC;
1589 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1590 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1591 irqflags);
1592 }
1593 }
1594 }
1595
pci230_ao_inttrig_start(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1596 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1597 struct comedi_subdevice *s,
1598 unsigned int trig_num)
1599 {
1600 if (trig_num != 0)
1601 return -EINVAL;
1602
1603 s->async->inttrig = NULLFUNC;
1604 pci230_ao_start(dev, s);
1605
1606 return 1;
1607 }
1608
pci230_ao_cmd(struct comedi_device * dev,struct comedi_subdevice * s)1609 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1610 {
1611 unsigned short daccon;
1612 unsigned int range;
1613
1614 /* Get the command. */
1615 struct comedi_cmd *cmd = &s->async->cmd;
1616
1617 if (cmd->scan_begin_src == TRIG_TIMER) {
1618 /* Claim Z2-CT1. */
1619 if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
1620 return -EBUSY;
1621
1622 }
1623
1624 /* Get number of scans required. */
1625 if (cmd->stop_src == TRIG_COUNT) {
1626 devpriv->ao_scan_count = cmd->stop_arg;
1627 devpriv->ao_continuous = 0;
1628 } else {
1629 /* TRIG_NONE, user calls cancel. */
1630 devpriv->ao_scan_count = 0;
1631 devpriv->ao_continuous = 1;
1632 }
1633
1634 /* Set range - see analogue output range table; 0 => unipolar 10V,
1635 * 1 => bipolar +/-10V range scale */
1636 range = CR_RANGE(cmd->chanlist[0]);
1637 devpriv->ao_bipolar = pci230_ao_bipolar[range];
1638 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1639 /* Use DAC FIFO for hardware version 2 onwards. */
1640 if (devpriv->hwver >= 2) {
1641 unsigned short dacen;
1642 unsigned int i;
1643
1644 dacen = 0;
1645 for (i = 0; i < cmd->chanlist_len; i++)
1646 dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1647
1648 /* Set channel scan list. */
1649 outw(dacen, dev->iobase + PCI230P2_DACEN);
1650 /*
1651 * Enable DAC FIFO.
1652 * Set DAC scan source to 'none'.
1653 * Set DAC FIFO interrupt trigger level to 'not half full'.
1654 * Reset DAC FIFO and clear underrun.
1655 *
1656 * N.B. DAC FIFO interrupts are currently disabled.
1657 */
1658 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1659 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1660 | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1661 }
1662
1663 /* Set DACCON. */
1664 outw(daccon, dev->iobase + PCI230_DACCON);
1665 /* Preserve most of DACCON apart from write-only, transient bits. */
1666 devpriv->daccon = daccon
1667 & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1668
1669 if (cmd->scan_begin_src == TRIG_TIMER) {
1670 /* Set the counter timer 1 to the specified scan frequency. */
1671 /* cmd->scan_begin_arg is sampling period in ns */
1672 /* gate it off for now. */
1673 outb(GAT_CONFIG(1, GAT_GND),
1674 devpriv->iobase1 + PCI230_ZGAT_SCE);
1675 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1676 cmd->scan_begin_arg,
1677 cmd->flags & TRIG_ROUND_MASK);
1678 }
1679
1680 /* N.B. cmd->start_src == TRIG_INT */
1681 s->async->inttrig = pci230_ao_inttrig_start;
1682
1683 return 0;
1684 }
1685
pci230_ai_check_scan_period(struct comedi_cmd * cmd)1686 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1687 {
1688 unsigned int min_scan_period, chanlist_len;
1689 int err = 0;
1690
1691 chanlist_len = cmd->chanlist_len;
1692 if (cmd->chanlist_len == 0)
1693 chanlist_len = 1;
1694
1695 min_scan_period = chanlist_len * cmd->convert_arg;
1696 if ((min_scan_period < chanlist_len)
1697 || (min_scan_period < cmd->convert_arg)) {
1698 /* Arithmetic overflow. */
1699 min_scan_period = UINT_MAX;
1700 err++;
1701 }
1702 if (cmd->scan_begin_arg < min_scan_period) {
1703 cmd->scan_begin_arg = min_scan_period;
1704 err++;
1705 }
1706
1707 return !err;
1708 }
1709
pci230_ai_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)1710 static int pci230_ai_cmdtest(struct comedi_device *dev,
1711 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1712 {
1713 int err = 0;
1714 unsigned int tmp;
1715
1716 /* cmdtest tests a particular command to see if it is valid.
1717 * Using the cmdtest ioctl, a user can create a valid cmd
1718 * and then have it executes by the cmd ioctl.
1719 *
1720 * cmdtest returns 1,2,3,4,5 or 0, depending on which tests
1721 * the command passes. */
1722
1723 /* Step 1: make sure trigger sources are trivially valid.
1724 * "invalid source" returned by comedilib to user mode process
1725 * if this fails. */
1726
1727 tmp = cmd->start_src;
1728 cmd->start_src &= TRIG_NOW | TRIG_INT;
1729 if (!cmd->start_src || tmp != cmd->start_src)
1730 err++;
1731
1732 tmp = cmd->scan_begin_src;
1733 /* Unfortunately, we cannot trigger a scan off an external source
1734 * on the PCI260 board, since it uses the PPIC0 (DIO) input, which
1735 * isn't present on the PCI260. For PCI260+ we can use the
1736 * EXTTRIG/EXTCONVCLK input on pin 17 instead. */
1737 if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1738 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT
1739 | TRIG_EXT;
1740 } else {
1741 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1742 }
1743 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1744 err++;
1745
1746 tmp = cmd->convert_src;
1747 cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1748 if (!cmd->convert_src || tmp != cmd->convert_src)
1749 err++;
1750
1751 tmp = cmd->scan_end_src;
1752 cmd->scan_end_src &= TRIG_COUNT;
1753 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1754 err++;
1755
1756 tmp = cmd->stop_src;
1757 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1758 if (!cmd->stop_src || tmp != cmd->stop_src)
1759 err++;
1760
1761 if (err)
1762 return 1;
1763
1764 /* Step 2: make sure trigger sources are unique and mutually compatible
1765 * "source conflict" returned by comedilib to user mode process
1766 * if this fails. */
1767
1768 /* these tests are true if more than one _src bit is set */
1769 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1770 err++;
1771 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1772 err++;
1773 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1774 err++;
1775 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1776 err++;
1777 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1778 err++;
1779
1780 /* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1781 * set up to generate a fixed number of timed conversion pulses. */
1782 if ((cmd->scan_begin_src != TRIG_FOLLOW)
1783 && (cmd->convert_src != TRIG_TIMER))
1784 err++;
1785
1786 if (err)
1787 return 2;
1788
1789 /* Step 3: make sure arguments are trivially compatible.
1790 * "invalid argument" returned by comedilib to user mode process
1791 * if this fails. */
1792
1793 if (cmd->start_arg != 0) {
1794 cmd->start_arg = 0;
1795 err++;
1796 }
1797 #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */
1798 #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */
1799 #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */
1800 #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */
1801 /*- Comedi limit due to unsigned int cmd. Driver limit
1802 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1803 * clock) = 65.536s */
1804
1805 if (cmd->convert_src == TRIG_TIMER) {
1806 unsigned int max_speed_ai;
1807
1808 if (devpriv->hwver == 0) {
1809 /* PCI230 or PCI260. Max speed depends whether
1810 * single-ended or pseudo-differential. */
1811 if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1812 /* Peek analogue reference of first channel. */
1813 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1814 max_speed_ai = MAX_SPEED_AI_DIFF;
1815 else
1816 max_speed_ai = MAX_SPEED_AI_SE;
1817
1818 } else {
1819 /* No channel list. Assume single-ended. */
1820 max_speed_ai = MAX_SPEED_AI_SE;
1821 }
1822 } else {
1823 /* PCI230+ or PCI260+. */
1824 max_speed_ai = MAX_SPEED_AI_PLUS;
1825 }
1826
1827 if (cmd->convert_arg < max_speed_ai) {
1828 cmd->convert_arg = max_speed_ai;
1829 err++;
1830 }
1831 if (cmd->convert_arg > MIN_SPEED_AI) {
1832 cmd->convert_arg = MIN_SPEED_AI;
1833 err++;
1834 }
1835 } else if (cmd->convert_src == TRIG_EXT) {
1836 /*
1837 * external trigger
1838 *
1839 * convert_arg == (CR_EDGE | 0)
1840 * => trigger on +ve edge.
1841 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1842 * => trigger on -ve edge.
1843 */
1844 if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1845 /* Trigger number must be 0. */
1846 if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1847 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1848 ~CR_FLAGS_MASK);
1849 err++;
1850 }
1851 /* The only flags allowed are CR_INVERT and CR_EDGE.
1852 * CR_EDGE is required. */
1853 if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1854 != CR_EDGE) {
1855 /* Set CR_EDGE, preserve CR_INVERT. */
1856 cmd->convert_arg =
1857 COMBINE(cmd->start_arg, (CR_EDGE | 0),
1858 CR_FLAGS_MASK & ~CR_INVERT);
1859 err++;
1860 }
1861 } else {
1862 /* Backwards compatibility with previous versions. */
1863 /* convert_arg == 0 => trigger on -ve edge. */
1864 /* convert_arg == 1 => trigger on +ve edge. */
1865 if (cmd->convert_arg > 1) {
1866 /* Default to trigger on +ve edge. */
1867 cmd->convert_arg = 1;
1868 err++;
1869 }
1870 }
1871 } else {
1872 if (cmd->convert_arg != 0) {
1873 cmd->convert_arg = 0;
1874 err++;
1875 }
1876 }
1877
1878 if (cmd->scan_end_arg != cmd->chanlist_len) {
1879 cmd->scan_end_arg = cmd->chanlist_len;
1880 err++;
1881 }
1882
1883 if (cmd->stop_src == TRIG_NONE) {
1884 if (cmd->stop_arg != 0) {
1885 cmd->stop_arg = 0;
1886 err++;
1887 }
1888 }
1889
1890 if (cmd->scan_begin_src == TRIG_EXT) {
1891 /* external "trigger" to begin each scan
1892 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1893 * of CT2 (sample convert trigger is CT2) */
1894 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1895 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1896 ~CR_FLAGS_MASK);
1897 err++;
1898 }
1899 /* The only flag allowed is CR_EDGE, which is ignored. */
1900 if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1901 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1902 CR_FLAGS_MASK & ~CR_EDGE);
1903 err++;
1904 }
1905 } else if (cmd->scan_begin_src == TRIG_TIMER) {
1906 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1907 if (!pci230_ai_check_scan_period(cmd))
1908 err++;
1909
1910 } else {
1911 if (cmd->scan_begin_arg != 0) {
1912 cmd->scan_begin_arg = 0;
1913 err++;
1914 }
1915 }
1916
1917 if (err)
1918 return 3;
1919
1920 /* Step 4: fix up any arguments.
1921 * "argument conflict" returned by comedilib to user mode process
1922 * if this fails. */
1923
1924 if (cmd->convert_src == TRIG_TIMER) {
1925 tmp = cmd->convert_arg;
1926 pci230_ns_to_single_timer(&cmd->convert_arg,
1927 cmd->flags & TRIG_ROUND_MASK);
1928 if (tmp != cmd->convert_arg)
1929 err++;
1930 }
1931
1932 if (cmd->scan_begin_src == TRIG_TIMER) {
1933 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1934 tmp = cmd->scan_begin_arg;
1935 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1936 cmd->flags & TRIG_ROUND_MASK);
1937 if (!pci230_ai_check_scan_period(cmd)) {
1938 /* Was below minimum required. Round up. */
1939 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1940 TRIG_ROUND_UP);
1941 pci230_ai_check_scan_period(cmd);
1942 }
1943 if (tmp != cmd->scan_begin_arg)
1944 err++;
1945 }
1946
1947 if (err)
1948 return 4;
1949
1950 /* Step 5: check channel list if it exists. */
1951
1952 if (cmd->chanlist && cmd->chanlist_len > 0) {
1953 enum {
1954 seq_err = 1 << 0,
1955 rangepair_err = 1 << 1,
1956 polarity_err = 1 << 2,
1957 aref_err = 1 << 3,
1958 diffchan_err = 1 << 4,
1959 buggy_chan0_err = 1 << 5
1960 };
1961 unsigned int errors;
1962 unsigned int chan, prev_chan;
1963 unsigned int range, prev_range;
1964 unsigned int polarity, prev_polarity;
1965 unsigned int aref, prev_aref;
1966 unsigned int subseq_len;
1967 unsigned int n;
1968
1969 subseq_len = 0;
1970 errors = 0;
1971 prev_chan = prev_aref = prev_range = prev_polarity = 0;
1972 for (n = 0; n < cmd->chanlist_len; n++) {
1973 chan = CR_CHAN(cmd->chanlist[n]);
1974 range = CR_RANGE(cmd->chanlist[n]);
1975 aref = CR_AREF(cmd->chanlist[n]);
1976 polarity = pci230_ai_bipolar[range];
1977 /* Only the first half of the channels are available if
1978 * differential. (These are remapped in software. In
1979 * hardware, only the even channels are available.) */
1980 if ((aref == AREF_DIFF)
1981 && (chan >= (s->n_chan / 2))) {
1982 errors |= diffchan_err;
1983 }
1984 if (n > 0) {
1985 /* Channel numbers must strictly increase or
1986 * subsequence must repeat exactly. */
1987 if ((chan <= prev_chan)
1988 && (subseq_len == 0)) {
1989 subseq_len = n;
1990 }
1991 if ((subseq_len > 0)
1992 && (cmd->chanlist[n] !=
1993 cmd->chanlist[n % subseq_len])) {
1994 errors |= seq_err;
1995 }
1996 /* Channels must have same AREF. */
1997 if (aref != prev_aref)
1998 errors |= aref_err;
1999
2000 /* Channel ranges must have same polarity. */
2001 if (polarity != prev_polarity)
2002 errors |= polarity_err;
2003
2004 /* Single-ended channel pairs must have same
2005 * range. */
2006 if ((aref != AREF_DIFF)
2007 && (((chan ^ prev_chan) & ~1) == 0)
2008 && (range != prev_range)) {
2009 errors |= rangepair_err;
2010 }
2011 }
2012 prev_chan = chan;
2013 prev_range = range;
2014 prev_aref = aref;
2015 prev_polarity = polarity;
2016 }
2017 if (subseq_len == 0) {
2018 /* Subsequence is whole sequence. */
2019 subseq_len = n;
2020 }
2021 /* If channel list is a repeating subsequence, need a whole
2022 * number of repeats. */
2023 if ((n % subseq_len) != 0)
2024 errors |= seq_err;
2025
2026 if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
2027 /*
2028 * Buggy PCI230+ or PCI260+ requires channel 0 to be
2029 * (first) in the sequence if the sequence contains
2030 * more than one channel. Hardware versions 1 and 2
2031 * have the bug. There is no hardware version 3.
2032 *
2033 * Actually, there are two firmwares that report
2034 * themselves as hardware version 1 (the boards
2035 * have different ADC chips with slightly different
2036 * timing requirements, which was supposed to be
2037 * invisible to software). The first one doesn't
2038 * seem to have the bug, but the second one
2039 * does, and we can't tell them apart!
2040 */
2041 if ((subseq_len > 1)
2042 && (CR_CHAN(cmd->chanlist[0]) != 0)) {
2043 errors |= buggy_chan0_err;
2044 }
2045 }
2046 if (errors != 0) {
2047 err++;
2048 if ((errors & seq_err) != 0) {
2049 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2050 "channel numbers must increase or "
2051 "sequence must repeat exactly\n",
2052 dev->minor);
2053 }
2054 if ((errors & rangepair_err) != 0) {
2055 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2056 "single-ended channel pairs must "
2057 "have the same range\n", dev->minor);
2058 }
2059 if ((errors & polarity_err) != 0) {
2060 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2061 "channel sequence ranges must be all "
2062 "bipolar or all unipolar\n",
2063 dev->minor);
2064 }
2065 if ((errors & aref_err) != 0) {
2066 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2067 "channel sequence analogue references "
2068 "must be all the same (single-ended "
2069 "or differential)\n", dev->minor);
2070 }
2071 if ((errors & diffchan_err) != 0) {
2072 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2073 "differential channel number out of "
2074 "range 0 to %u\n", dev->minor,
2075 (s->n_chan / 2) - 1);
2076 }
2077 if ((errors & buggy_chan0_err) != 0) {
2078 /* Use printk instead of DPRINTK here. */
2079 printk("comedi: comedi%d: amplc_pci230: "
2080 "ai_cmdtest: Buggy PCI230+/260+ "
2081 "h/w version %u requires first channel "
2082 "of multi-channel sequence to be 0 "
2083 "(corrected in h/w version 4)\n",
2084 dev->minor, devpriv->hwver);
2085 }
2086 }
2087 }
2088
2089 if (err)
2090 return 5;
2091
2092 return 0;
2093 }
2094
pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,struct comedi_subdevice * s)2095 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
2096 struct comedi_subdevice *s)
2097 {
2098 struct comedi_cmd *cmd = &s->async->cmd;
2099 unsigned int scanlen = cmd->scan_end_arg;
2100 unsigned int wake;
2101 unsigned short triglev;
2102 unsigned short adccon;
2103
2104 if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
2105 /* Wake at end of scan. */
2106 wake = scanlen - devpriv->ai_scan_pos;
2107 } else {
2108 if (devpriv->ai_continuous
2109 || (devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL)
2110 || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2111 wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
2112 } else {
2113 wake = (devpriv->ai_scan_count * scanlen)
2114 - devpriv->ai_scan_pos;
2115 }
2116 }
2117 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
2118 triglev = PCI230_ADC_INT_FIFO_HALF;
2119 } else {
2120 if ((wake > 1) && (devpriv->hwver > 0)) {
2121 /* PCI230+/260+ programmable FIFO interrupt level. */
2122 if (devpriv->adcfifothresh != wake) {
2123 devpriv->adcfifothresh = wake;
2124 outw(wake, dev->iobase + PCI230P_ADCFFTH);
2125 }
2126 triglev = PCI230P_ADC_INT_FIFO_THRESH;
2127 } else {
2128 triglev = PCI230_ADC_INT_FIFO_NEMPTY;
2129 }
2130 }
2131 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
2132 if (adccon != devpriv->adccon) {
2133 devpriv->adccon = adccon;
2134 outw(adccon, dev->iobase + PCI230_ADCCON);
2135 }
2136 }
2137
pci230_ai_inttrig_convert(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)2138 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
2139 struct comedi_subdevice *s,
2140 unsigned int trig_num)
2141 {
2142 unsigned long irqflags;
2143
2144 if (trig_num != 0)
2145 return -EINVAL;
2146
2147 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2148 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2149 unsigned int delayus;
2150
2151 /* Trigger conversion by toggling Z2-CT2 output. Finish
2152 * with output high. */
2153 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2154 I8254_MODE0);
2155 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2156 I8254_MODE1);
2157 /* Delay. Should driver be responsible for this? An
2158 * alternative would be to wait until conversion is complete,
2159 * but we can't tell when it's complete because the ADC busy
2160 * bit has a different meaning when FIFO enabled (and when
2161 * FIFO not enabled, it only works for software triggers). */
2162 if (((devpriv->adccon & PCI230_ADC_IM_MASK)
2163 == PCI230_ADC_IM_DIF)
2164 && (devpriv->hwver == 0)) {
2165 /* PCI230/260 in differential mode */
2166 delayus = 8;
2167 } else {
2168 /* single-ended or PCI230+/260+ */
2169 delayus = 4;
2170 }
2171 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2172 udelay(delayus);
2173 } else {
2174 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2175 }
2176
2177 return 1;
2178 }
2179
pci230_ai_inttrig_scan_begin(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)2180 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
2181 struct comedi_subdevice *s,
2182 unsigned int trig_num)
2183 {
2184 unsigned long irqflags;
2185 unsigned char zgat;
2186
2187 if (trig_num != 0)
2188 return -EINVAL;
2189
2190 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2191 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2192 /* Trigger scan by waggling CT0 gate source. */
2193 zgat = GAT_CONFIG(0, GAT_GND);
2194 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2195 zgat = GAT_CONFIG(0, GAT_VCC);
2196 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2197 }
2198 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2199
2200 return 1;
2201 }
2202
pci230_ai_start(struct comedi_device * dev,struct comedi_subdevice * s)2203 static void pci230_ai_start(struct comedi_device *dev,
2204 struct comedi_subdevice *s)
2205 {
2206 unsigned long irqflags;
2207 unsigned short conv;
2208 struct comedi_async *async = s->async;
2209 struct comedi_cmd *cmd = &async->cmd;
2210
2211 set_bit(AI_CMD_STARTED, &devpriv->state);
2212 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2213 /* An empty acquisition! */
2214 async->events |= COMEDI_CB_EOA;
2215 pci230_ai_stop(dev, s);
2216 comedi_event(dev, s);
2217 } else {
2218 /* Enable ADC FIFO trigger level interrupt. */
2219 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2220 devpriv->int_en |= PCI230_INT_ADC;
2221 devpriv->ier |= PCI230_INT_ADC;
2222 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2223 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2224
2225 /* Update conversion trigger source which is currently set
2226 * to CT2 output, which is currently stuck high. */
2227 switch (cmd->convert_src) {
2228 default:
2229 conv = PCI230_ADC_TRIG_NONE;
2230 break;
2231 case TRIG_TIMER:
2232 /* Using CT2 output. */
2233 conv = PCI230_ADC_TRIG_Z2CT2;
2234 break;
2235 case TRIG_EXT:
2236 if ((cmd->convert_arg & CR_EDGE) != 0) {
2237 if ((cmd->convert_arg & CR_INVERT) == 0) {
2238 /* Trigger on +ve edge. */
2239 conv = PCI230_ADC_TRIG_EXTP;
2240 } else {
2241 /* Trigger on -ve edge. */
2242 conv = PCI230_ADC_TRIG_EXTN;
2243 }
2244 } else {
2245 /* Backwards compatibility. */
2246 if (cmd->convert_arg != 0) {
2247 /* Trigger on +ve edge. */
2248 conv = PCI230_ADC_TRIG_EXTP;
2249 } else {
2250 /* Trigger on -ve edge. */
2251 conv = PCI230_ADC_TRIG_EXTN;
2252 }
2253 }
2254 break;
2255 case TRIG_INT:
2256 /* Use CT2 output for software trigger due to problems
2257 * in differential mode on PCI230/260. */
2258 conv = PCI230_ADC_TRIG_Z2CT2;
2259 break;
2260 }
2261 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
2262 | conv;
2263 outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
2264 if (cmd->convert_src == TRIG_INT)
2265 async->inttrig = pci230_ai_inttrig_convert;
2266
2267 /* Update FIFO interrupt trigger level, which is currently
2268 * set to "full". */
2269 pci230_ai_update_fifo_trigger_level(dev, s);
2270 if (cmd->convert_src == TRIG_TIMER) {
2271 /* Update timer gates. */
2272 unsigned char zgat;
2273
2274 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2275 /* Conversion timer CT2 needs to be gated by
2276 * inverted output of monostable CT2. */
2277 zgat = GAT_CONFIG(2, GAT_NOUTNM2);
2278 } else {
2279 /* Conversion timer CT2 needs to be gated on
2280 * continuously. */
2281 zgat = GAT_CONFIG(2, GAT_VCC);
2282 }
2283 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2284 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2285 /* Set monostable CT0 trigger source. */
2286 switch (cmd->scan_begin_src) {
2287 default:
2288 zgat = GAT_CONFIG(0, GAT_VCC);
2289 break;
2290 case TRIG_EXT:
2291 /*
2292 * For CT0 on PCI230, the external
2293 * trigger (gate) signal comes from
2294 * PPC0, which is channel 16 of the DIO
2295 * subdevice. The application needs to
2296 * configure this as an input in order
2297 * to use it as an external scan
2298 * trigger.
2299 */
2300 zgat = GAT_CONFIG(0, GAT_EXT);
2301 break;
2302 case TRIG_TIMER:
2303 /*
2304 * Monostable CT0 triggered by rising
2305 * edge on inverted output of CT1
2306 * (falling edge on CT1).
2307 */
2308 zgat = GAT_CONFIG(0, GAT_NOUTNM2);
2309 break;
2310 case TRIG_INT:
2311 /*
2312 * Monostable CT0 is triggered by
2313 * inttrig function waggling the CT0
2314 * gate source.
2315 */
2316 zgat = GAT_CONFIG(0, GAT_VCC);
2317 break;
2318 }
2319 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2320 switch (cmd->scan_begin_src) {
2321 case TRIG_TIMER:
2322 /* Scan period timer CT1 needs to be
2323 * gated on to start counting. */
2324 zgat = GAT_CONFIG(1, GAT_VCC);
2325 outb(zgat, devpriv->iobase1
2326 + PCI230_ZGAT_SCE);
2327 break;
2328 case TRIG_INT:
2329 async->inttrig =
2330 pci230_ai_inttrig_scan_begin;
2331 break;
2332 }
2333 }
2334 } else if (cmd->convert_src != TRIG_INT) {
2335 /* No longer need Z2-CT2. */
2336 put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
2337 }
2338 }
2339 }
2340
pci230_ai_inttrig_start(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)2341 static int pci230_ai_inttrig_start(struct comedi_device *dev,
2342 struct comedi_subdevice *s,
2343 unsigned int trig_num)
2344 {
2345 if (trig_num != 0)
2346 return -EINVAL;
2347
2348 s->async->inttrig = NULLFUNC;
2349 pci230_ai_start(dev, s);
2350
2351 return 1;
2352 }
2353
pci230_ai_cmd(struct comedi_device * dev,struct comedi_subdevice * s)2354 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2355 {
2356 unsigned int i, chan, range, diff;
2357 unsigned int res_mask;
2358 unsigned short adccon, adcen;
2359 unsigned char zgat;
2360
2361 /* Get the command. */
2362 struct comedi_async *async = s->async;
2363 struct comedi_cmd *cmd = &async->cmd;
2364
2365 /*
2366 * Determine which shared resources are needed.
2367 */
2368 res_mask = 0;
2369 /* Need Z2-CT2 to supply a conversion trigger source at a high
2370 * logic level, even if not doing timed conversions. */
2371 res_mask |= (1U << RES_Z2CT2);
2372 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2373 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2374 res_mask |= (1U << RES_Z2CT0);
2375 if (cmd->scan_begin_src == TRIG_TIMER) {
2376 /* Using Z2-CT1 for scan frequency */
2377 res_mask |= (1U << RES_Z2CT1);
2378 }
2379 }
2380 /* Claim resources. */
2381 if (!get_resources(dev, res_mask, OWNER_AICMD))
2382 return -EBUSY;
2383
2384
2385 /* Get number of scans required. */
2386 if (cmd->stop_src == TRIG_COUNT) {
2387 devpriv->ai_scan_count = cmd->stop_arg;
2388 devpriv->ai_continuous = 0;
2389 } else {
2390 /* TRIG_NONE, user calls cancel. */
2391 devpriv->ai_scan_count = 0;
2392 devpriv->ai_continuous = 1;
2393 }
2394 devpriv->ai_scan_pos = 0; /* Position within scan. */
2395
2396 /* Steps;
2397 * - Set channel scan list.
2398 * - Set channel gains.
2399 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2400 * start conversion source to point to something at a high logic
2401 * level (we use the output of counter/timer 2 for this purpose.
2402 * - PAUSE to allow things to settle down.
2403 * - Reset the FIFO again because it needs resetting twice and there
2404 * may have been a false conversion trigger on some versions of
2405 * PCI230/260 due to the start conversion source being set to a
2406 * high logic level.
2407 * - Enable ADC FIFO level interrupt.
2408 * - Set actual conversion trigger source and FIFO interrupt trigger
2409 * level.
2410 * - If convert_src is TRIG_TIMER, set up the timers.
2411 */
2412
2413 adccon = PCI230_ADC_FIFO_EN;
2414 adcen = 0;
2415
2416 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2417 /* Differential - all channels must be differential. */
2418 diff = 1;
2419 adccon |= PCI230_ADC_IM_DIF;
2420 } else {
2421 /* Single ended - all channels must be single-ended. */
2422 diff = 0;
2423 adccon |= PCI230_ADC_IM_SE;
2424 }
2425
2426 range = CR_RANGE(cmd->chanlist[0]);
2427 devpriv->ai_bipolar = pci230_ai_bipolar[range];
2428 if (devpriv->ai_bipolar)
2429 adccon |= PCI230_ADC_IR_BIP;
2430 else
2431 adccon |= PCI230_ADC_IR_UNI;
2432
2433 for (i = 0; i < cmd->chanlist_len; i++) {
2434 unsigned int gainshift;
2435
2436 chan = CR_CHAN(cmd->chanlist[i]);
2437 range = CR_RANGE(cmd->chanlist[i]);
2438 if (diff) {
2439 gainshift = 2 * chan;
2440 if (devpriv->hwver == 0) {
2441 /* Original PCI230/260 expects both inputs of
2442 * the differential channel to be enabled. */
2443 adcen |= 3 << gainshift;
2444 } else {
2445 /* PCI230+/260+ expects only one input of the
2446 * differential channel to be enabled. */
2447 adcen |= 1 << gainshift;
2448 }
2449 } else {
2450 gainshift = (chan & ~1);
2451 adcen |= 1 << chan;
2452 }
2453 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2454 | (pci230_ai_gain[range] << gainshift);
2455 }
2456
2457 /* Set channel scan list. */
2458 outw(adcen, dev->iobase + PCI230_ADCEN);
2459
2460 /* Set channel gains. */
2461 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2462
2463 /* Set counter/timer 2 output high for use as the initial start
2464 * conversion source. */
2465 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2466
2467 /* Temporarily use CT2 output as conversion trigger source and
2468 * temporarily set FIFO interrupt trigger level to 'full'. */
2469 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2470
2471 /* Enable and reset FIFO, specify FIFO trigger level full, specify
2472 * uni/bip, se/diff, and temporarily set the start conversion source
2473 * to CT2 output. Note that CT2 output is currently high, and this
2474 * will produce a false conversion trigger on some versions of the
2475 * PCI230/260, but that will be dealt with later. */
2476 devpriv->adccon = adccon;
2477 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2478
2479 /* Delay */
2480 /* Failure to include this will result in the first few channels'-worth
2481 * of data being corrupt, normally manifesting itself by large negative
2482 * voltages. It seems the board needs time to settle between the first
2483 * FIFO reset (above) and the second FIFO reset (below). Setting the
2484 * channel gains and scan list _before_ the first FIFO reset also
2485 * helps, though only slightly. */
2486 udelay(25);
2487
2488 /* Reset FIFO again. */
2489 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2490
2491 if (cmd->convert_src == TRIG_TIMER) {
2492 /* Set up CT2 as conversion timer, but gate it off for now.
2493 * Note, counter/timer output 2 can be monitored on the
2494 * connector: PCI230 pin 21, PCI260 pin 18. */
2495 zgat = GAT_CONFIG(2, GAT_GND);
2496 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2497 /* Set counter/timer 2 to the specified conversion period. */
2498 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2499 cmd->flags & TRIG_ROUND_MASK);
2500 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2501 /*
2502 * Set up monostable on CT0 output for scan timing. A
2503 * rising edge on the trigger (gate) input of CT0 will
2504 * trigger the monostable, causing its output to go low
2505 * for the configured period. The period depends on
2506 * the conversion period and the number of conversions
2507 * in the scan.
2508 *
2509 * Set the trigger high before setting up the
2510 * monostable to stop it triggering. The trigger
2511 * source will be changed later.
2512 */
2513 zgat = GAT_CONFIG(0, GAT_VCC);
2514 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2515 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2516 ((uint64_t) cmd->convert_arg
2517 * cmd->scan_end_arg),
2518 TRIG_ROUND_UP);
2519 if (cmd->scan_begin_src == TRIG_TIMER) {
2520 /*
2521 * Monostable on CT0 will be triggered by
2522 * output of CT1 at configured scan frequency.
2523 *
2524 * Set up CT1 but gate it off for now.
2525 */
2526 zgat = GAT_CONFIG(1, GAT_GND);
2527 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2528 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2529 cmd->scan_begin_arg,
2530 cmd->
2531 flags &
2532 TRIG_ROUND_MASK);
2533 }
2534 }
2535 }
2536
2537 if (cmd->start_src == TRIG_INT) {
2538 s->async->inttrig = pci230_ai_inttrig_start;
2539 } else {
2540 /* TRIG_NOW */
2541 pci230_ai_start(dev, s);
2542 }
2543
2544 return 0;
2545 }
2546
divide_ns(uint64_t ns,unsigned int timebase,unsigned int round_mode)2547 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
2548 unsigned int round_mode)
2549 {
2550 uint64_t div;
2551 unsigned int rem;
2552
2553 div = ns;
2554 rem = do_div(div, timebase);
2555 round_mode &= TRIG_ROUND_MASK;
2556 switch (round_mode) {
2557 default:
2558 case TRIG_ROUND_NEAREST:
2559 div += (rem + (timebase / 2)) / timebase;
2560 break;
2561 case TRIG_ROUND_DOWN:
2562 break;
2563 case TRIG_ROUND_UP:
2564 div += (rem + timebase - 1) / timebase;
2565 break;
2566 }
2567 return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
2568 }
2569
2570 /* Given desired period in ns, returns the required internal clock source
2571 * and gets the initial count. */
pci230_choose_clk_count(uint64_t ns,unsigned int * count,unsigned int round_mode)2572 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
2573 unsigned int round_mode)
2574 {
2575 unsigned int clk_src, cnt;
2576
2577 for (clk_src = CLK_10MHZ;; clk_src++) {
2578 cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
2579 if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
2580 break;
2581
2582 }
2583 *count = cnt;
2584 return clk_src;
2585 }
2586
pci230_ns_to_single_timer(unsigned int * ns,unsigned int round)2587 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
2588 {
2589 unsigned int count;
2590 unsigned int clk_src;
2591
2592 clk_src = pci230_choose_clk_count(*ns, &count, round);
2593 *ns = count * pci230_timebase[clk_src];
2594 return;
2595 }
2596
pci230_ct_setup_ns_mode(struct comedi_device * dev,unsigned int ct,unsigned int mode,uint64_t ns,unsigned int round)2597 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
2598 unsigned int mode, uint64_t ns,
2599 unsigned int round)
2600 {
2601 unsigned int clk_src;
2602 unsigned int count;
2603
2604 /* Set mode. */
2605 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
2606 /* Determine clock source and count. */
2607 clk_src = pci230_choose_clk_count(ns, &count, round);
2608 /* Program clock source. */
2609 outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
2610 /* Set initial count. */
2611 if (count >= 65536)
2612 count = 0;
2613
2614 i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
2615 }
2616
pci230_cancel_ct(struct comedi_device * dev,unsigned int ct)2617 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
2618 {
2619 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
2620 I8254_MODE1);
2621 /* Counter ct, 8254 mode 1, initial count not written. */
2622 }
2623
2624 /* Interrupt handler */
pci230_interrupt(int irq,void * d)2625 static irqreturn_t pci230_interrupt(int irq, void *d)
2626 {
2627 unsigned char status_int, valid_status_int;
2628 struct comedi_device *dev = (struct comedi_device *)d;
2629 struct comedi_subdevice *s;
2630 unsigned long irqflags;
2631
2632 /* Read interrupt status/enable register. */
2633 status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2634
2635 if (status_int == PCI230_INT_DISABLE)
2636 return IRQ_NONE;
2637
2638
2639 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2640 valid_status_int = devpriv->int_en & status_int;
2641 /* Disable triggered interrupts.
2642 * (Only those interrupts that need re-enabling, are, later in the
2643 * handler). */
2644 devpriv->ier = devpriv->int_en & ~status_int;
2645 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2646 devpriv->intr_running = 1;
2647 devpriv->intr_cpuid = THISCPU;
2648 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2649
2650 /*
2651 * Check the source of interrupt and handle it.
2652 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2653 * interrupts. However, at present (Comedi-0.7.60) does not allow
2654 * concurrent execution of commands, instructions or a mixture of the
2655 * two.
2656 */
2657
2658 if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2659 s = dev->write_subdev;
2660 pci230_handle_ao_nofifo(dev, s);
2661 comedi_event(dev, s);
2662 }
2663
2664 if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2665 s = dev->write_subdev;
2666 pci230_handle_ao_fifo(dev, s);
2667 comedi_event(dev, s);
2668 }
2669
2670 if ((valid_status_int & PCI230_INT_ADC) != 0) {
2671 s = dev->read_subdev;
2672 pci230_handle_ai(dev, s);
2673 comedi_event(dev, s);
2674 }
2675
2676 /* Reenable interrupts. */
2677 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2678 if (devpriv->ier != devpriv->int_en) {
2679 devpriv->ier = devpriv->int_en;
2680 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2681 }
2682 devpriv->intr_running = 0;
2683 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2684
2685 return IRQ_HANDLED;
2686 }
2687
pci230_handle_ao_nofifo(struct comedi_device * dev,struct comedi_subdevice * s)2688 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
2689 struct comedi_subdevice *s)
2690 {
2691 short data;
2692 int i, ret;
2693 struct comedi_async *async = s->async;
2694 struct comedi_cmd *cmd = &async->cmd;
2695
2696 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
2697 return;
2698
2699
2700 for (i = 0; i < cmd->chanlist_len; i++) {
2701 /* Read sample from Comedi's circular buffer. */
2702 ret = comedi_buf_get(s->async, &data);
2703 if (ret == 0) {
2704 s->async->events |= COMEDI_CB_OVERFLOW;
2705 pci230_ao_stop(dev, s);
2706 comedi_error(dev, "AO buffer underrun");
2707 return;
2708 }
2709 /* Write value to DAC. */
2710 pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
2711 }
2712
2713 async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
2714 if (!devpriv->ao_continuous) {
2715 devpriv->ao_scan_count--;
2716 if (devpriv->ao_scan_count == 0) {
2717 /* End of acquisition. */
2718 async->events |= COMEDI_CB_EOA;
2719 pci230_ao_stop(dev, s);
2720 }
2721 }
2722 }
2723
2724 /* Loads DAC FIFO (if using it) from buffer. */
2725 /* Returns 0 if AO finished due to completion or error, 1 if still going. */
pci230_handle_ao_fifo(struct comedi_device * dev,struct comedi_subdevice * s)2726 static int pci230_handle_ao_fifo(struct comedi_device *dev,
2727 struct comedi_subdevice *s)
2728 {
2729 struct comedi_async *async = s->async;
2730 struct comedi_cmd *cmd = &async->cmd;
2731 unsigned int num_scans;
2732 unsigned int room;
2733 unsigned short dacstat;
2734 unsigned int i, n;
2735 unsigned int bytes_per_scan;
2736 unsigned int events = 0;
2737 int running;
2738
2739 /* Get DAC FIFO status. */
2740 dacstat = inw(dev->iobase + PCI230_DACCON);
2741
2742 /* Determine number of scans available in buffer. */
2743 bytes_per_scan = cmd->chanlist_len * sizeof(short);
2744 num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
2745 if (!devpriv->ao_continuous) {
2746 /* Fixed number of scans. */
2747 if (num_scans > devpriv->ao_scan_count)
2748 num_scans = devpriv->ao_scan_count;
2749
2750 if (devpriv->ao_scan_count == 0) {
2751 /* End of acquisition. */
2752 events |= COMEDI_CB_EOA;
2753 }
2754 }
2755 if (events == 0) {
2756 /* Check for FIFO underrun. */
2757 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2758 comedi_error(dev, "AO FIFO underrun");
2759 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2760 }
2761 /* Check for buffer underrun if FIFO less than half full
2762 * (otherwise there will be loads of "DAC FIFO not half full"
2763 * interrupts). */
2764 if ((num_scans == 0)
2765 && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
2766 comedi_error(dev, "AO buffer underrun");
2767 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2768 }
2769 }
2770 if (events == 0) {
2771 /* Determine how much room is in the FIFO (in samples). */
2772 if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
2773 room = PCI230P2_DAC_FIFOROOM_FULL;
2774 else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
2775 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
2776 else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
2777 room = PCI230P2_DAC_FIFOROOM_EMPTY;
2778 else
2779 room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
2780
2781 /* Convert room to number of scans that can be added. */
2782 room /= cmd->chanlist_len;
2783 /* Determine number of scans to process. */
2784 if (num_scans > room)
2785 num_scans = room;
2786
2787 /* Process scans. */
2788 for (n = 0; n < num_scans; n++) {
2789 for (i = 0; i < cmd->chanlist_len; i++) {
2790 short datum;
2791
2792 comedi_buf_get(async, &datum);
2793 pci230_ao_write_fifo(dev, datum,
2794 CR_CHAN(cmd->chanlist[i]));
2795 }
2796 }
2797 events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
2798 if (!devpriv->ao_continuous) {
2799 devpriv->ao_scan_count -= num_scans;
2800 if (devpriv->ao_scan_count == 0) {
2801 /* All data for the command has been written
2802 * to FIFO. Set FIFO interrupt trigger level
2803 * to 'empty'. */
2804 devpriv->daccon = (devpriv->daccon
2805 &
2806 ~PCI230P2_DAC_INT_FIFO_MASK)
2807 | PCI230P2_DAC_INT_FIFO_EMPTY;
2808 outw(devpriv->daccon,
2809 dev->iobase + PCI230_DACCON);
2810 }
2811 }
2812 /* Check if FIFO underrun occurred while writing to FIFO. */
2813 dacstat = inw(dev->iobase + PCI230_DACCON);
2814 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2815 comedi_error(dev, "AO FIFO underrun");
2816 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2817 }
2818 }
2819 if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
2820 != 0) {
2821 /* Stopping AO due to completion or error. */
2822 pci230_ao_stop(dev, s);
2823 running = 0;
2824 } else {
2825 running = 1;
2826 }
2827 async->events |= events;
2828 return running;
2829 }
2830
pci230_handle_ai(struct comedi_device * dev,struct comedi_subdevice * s)2831 static void pci230_handle_ai(struct comedi_device *dev,
2832 struct comedi_subdevice *s)
2833 {
2834 unsigned int events = 0;
2835 unsigned int status_fifo;
2836 unsigned int i;
2837 unsigned int todo;
2838 unsigned int fifoamount;
2839 struct comedi_async *async = s->async;
2840 unsigned int scanlen = async->cmd.scan_end_arg;
2841
2842 /* Determine number of samples to read. */
2843 if (devpriv->ai_continuous) {
2844 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2845 } else if (devpriv->ai_scan_count == 0) {
2846 todo = 0;
2847 } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2848 || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2849 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2850 } else {
2851 todo = (devpriv->ai_scan_count * scanlen)
2852 - devpriv->ai_scan_pos;
2853 if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
2854 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2855
2856 }
2857
2858 if (todo == 0)
2859 return;
2860
2861
2862 fifoamount = 0;
2863 for (i = 0; i < todo; i++) {
2864 if (fifoamount == 0) {
2865 /* Read FIFO state. */
2866 status_fifo = inw(dev->iobase + PCI230_ADCCON);
2867
2868 if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2869 /* Report error otherwise FIFO overruns will go
2870 * unnoticed by the caller. */
2871 comedi_error(dev, "AI FIFO overrun");
2872 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2873 break;
2874 } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2875 /* FIFO empty. */
2876 break;
2877 } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2878 /* FIFO half full. */
2879 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2880 } else {
2881 /* FIFO not empty. */
2882 if (devpriv->hwver > 0) {
2883 /* Read PCI230+/260+ ADC FIFO level. */
2884 fifoamount = inw(dev->iobase
2885 + PCI230P_ADCFFLEV);
2886 if (fifoamount == 0) {
2887 /* Shouldn't happen. */
2888 break;
2889 }
2890 } else {
2891 fifoamount = 1;
2892 }
2893 }
2894 }
2895
2896 /* Read sample and store in Comedi's circular buffer. */
2897 if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2898 events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2899 comedi_error(dev, "AI buffer overflow");
2900 break;
2901 }
2902 fifoamount--;
2903 devpriv->ai_scan_pos++;
2904 if (devpriv->ai_scan_pos == scanlen) {
2905 /* End of scan. */
2906 devpriv->ai_scan_pos = 0;
2907 devpriv->ai_scan_count--;
2908 async->events |= COMEDI_CB_EOS;
2909 }
2910 }
2911
2912 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2913 /* End of acquisition. */
2914 events |= COMEDI_CB_EOA;
2915 } else {
2916 /* More samples required, tell Comedi to block. */
2917 events |= COMEDI_CB_BLOCK;
2918 }
2919 async->events |= events;
2920
2921 if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2922 COMEDI_CB_OVERFLOW)) != 0) {
2923 /* disable hardware conversions */
2924 pci230_ai_stop(dev, s);
2925 } else {
2926 /* update FIFO interrupt trigger level */
2927 pci230_ai_update_fifo_trigger_level(dev, s);
2928 }
2929 }
2930
pci230_ao_stop(struct comedi_device * dev,struct comedi_subdevice * s)2931 static void pci230_ao_stop(struct comedi_device *dev,
2932 struct comedi_subdevice *s)
2933 {
2934 unsigned long irqflags;
2935 unsigned char intsrc;
2936 int started;
2937 struct comedi_cmd *cmd;
2938
2939 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
2940 started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
2941 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
2942 if (!started)
2943 return;
2944
2945
2946 cmd = &s->async->cmd;
2947 if (cmd->scan_begin_src == TRIG_TIMER) {
2948 /* Stop scan rate generator. */
2949 pci230_cancel_ct(dev, 1);
2950 }
2951
2952 /* Determine interrupt source. */
2953 if (devpriv->hwver < 2) {
2954 /* Not using DAC FIFO. Using CT1 interrupt. */
2955 intsrc = PCI230_INT_ZCLK_CT1;
2956 } else {
2957 /* Using DAC FIFO interrupt. */
2958 intsrc = PCI230P2_INT_DAC;
2959 }
2960 /* Disable interrupt and wait for interrupt routine to finish running
2961 * unless we are called from the interrupt routine. */
2962 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2963 devpriv->int_en &= ~intsrc;
2964 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2965 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2966 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2967 }
2968 if (devpriv->ier != devpriv->int_en) {
2969 devpriv->ier = devpriv->int_en;
2970 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2971 }
2972 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2973
2974 if (devpriv->hwver >= 2) {
2975 /* Using DAC FIFO. Reset FIFO, clear underrun error,
2976 * disable FIFO. */
2977 devpriv->daccon &= PCI230_DAC_OR_MASK;
2978 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
2979 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
2980 dev->iobase + PCI230_DACCON);
2981 }
2982
2983 /* Release resources. */
2984 put_all_resources(dev, OWNER_AOCMD);
2985 }
2986
pci230_ao_cancel(struct comedi_device * dev,struct comedi_subdevice * s)2987 static int pci230_ao_cancel(struct comedi_device *dev,
2988 struct comedi_subdevice *s)
2989 {
2990 pci230_ao_stop(dev, s);
2991 return 0;
2992 }
2993
pci230_ai_stop(struct comedi_device * dev,struct comedi_subdevice * s)2994 static void pci230_ai_stop(struct comedi_device *dev,
2995 struct comedi_subdevice *s)
2996 {
2997 unsigned long irqflags;
2998 struct comedi_cmd *cmd;
2999 int started;
3000
3001 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
3002 started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
3003 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
3004 if (!started)
3005 return;
3006
3007
3008 cmd = &s->async->cmd;
3009 if (cmd->convert_src == TRIG_TIMER) {
3010 /* Stop conversion rate generator. */
3011 pci230_cancel_ct(dev, 2);
3012 }
3013 if (cmd->scan_begin_src != TRIG_FOLLOW) {
3014 /* Stop scan period monostable. */
3015 pci230_cancel_ct(dev, 0);
3016 }
3017
3018 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
3019 /* Disable ADC interrupt and wait for interrupt routine to finish
3020 * running unless we are called from the interrupt routine. */
3021 devpriv->int_en &= ~PCI230_INT_ADC;
3022 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
3023 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
3024 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
3025 }
3026 if (devpriv->ier != devpriv->int_en) {
3027 devpriv->ier = devpriv->int_en;
3028 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
3029 }
3030 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
3031
3032 /* Reset FIFO, disable FIFO and set start conversion source to none.
3033 * Keep se/diff and bip/uni settings */
3034 devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
3035 | PCI230_ADC_IM_MASK)) |
3036 PCI230_ADC_TRIG_NONE;
3037 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
3038 dev->iobase + PCI230_ADCCON);
3039
3040 /* Release resources. */
3041 put_all_resources(dev, OWNER_AICMD);
3042 }
3043
pci230_ai_cancel(struct comedi_device * dev,struct comedi_subdevice * s)3044 static int pci230_ai_cancel(struct comedi_device *dev,
3045 struct comedi_subdevice *s)
3046 {
3047 pci230_ai_stop(dev, s);
3048 return 0;
3049 }
3050
3051 MODULE_AUTHOR("Comedi http://www.comedi.org");
3052 MODULE_DESCRIPTION("Comedi low-level driver");
3053 MODULE_LICENSE("GPL");
3054