1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * comedi/drivers/amplc_pci230.c
4 * Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
5 *
6 * Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
7 *
8 * COMEDI - Linux Control and Measurement Device Interface
9 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
10 */
11
12 /*
13 * Driver: amplc_pci230
14 * Description: Amplicon PCI230, PCI260 Multifunction I/O boards
15 * Author: Allan Willcox <allanwillcox@ozemail.com.au>,
16 * Steve D Sharples <steve.sharples@nottingham.ac.uk>,
17 * Ian Abbott <abbotti@mev.co.uk>
18 * Updated: Mon, 01 Sep 2014 10:09:16 +0000
19 * Devices: [Amplicon] PCI230 (amplc_pci230), PCI230+, PCI260, PCI260+
20 * Status: works
21 *
22 * Configuration options:
23 * none
24 *
25 * Manual configuration of PCI cards is not supported; they are configured
26 * automatically.
27 *
28 * The PCI230+ and PCI260+ have the same PCI device IDs as the PCI230 and
29 * PCI260, but can be distinguished by the size of the PCI regions. A
30 * card will be configured as a "+" model if detected as such.
31 *
32 * Subdevices:
33 *
34 * PCI230(+) PCI260(+)
35 * --------- ---------
36 * Subdevices 3 1
37 * 0 AI AI
38 * 1 AO
39 * 2 DIO
40 *
41 * AI Subdevice:
42 *
43 * The AI subdevice has 16 single-ended channels or 8 differential
44 * channels.
45 *
46 * The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and
47 * PCI260+ cards have 16-bit resolution.
48 *
49 * For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
50 * inputs 14 and 15 for channel 7). If the card is physically a PCI230
51 * or PCI260 then it actually uses a "pseudo-differential" mode where the
52 * inputs are sampled a few microseconds apart. The PCI230+ and PCI260+
53 * use true differential sampling. Another difference is that if the
54 * card is physically a PCI230 or PCI260, the inverting input is 2N,
55 * whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a
56 * PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
57 * PCI260+) and differential mode is used, the differential inputs need
58 * to be physically swapped on the connector.
59 *
60 * The following input ranges are supported:
61 *
62 * 0 => [-10, +10] V
63 * 1 => [-5, +5] V
64 * 2 => [-2.5, +2.5] V
65 * 3 => [-1.25, +1.25] V
66 * 4 => [0, 10] V
67 * 5 => [0, 5] V
68 * 6 => [0, 2.5] V
69 *
70 * AI Commands:
71 *
72 * +=========+==============+===========+============+==========+
73 * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
74 * +=========+==============+===========+============+==========+
75 * |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
76 * |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT|
77 * | | |TRIG_INT | | |
78 * | |--------------|-----------| | |
79 * | | TRIG_TIMER(1)|TRIG_TIMER | | |
80 * | | TRIG_EXT(2) | | | |
81 * | | TRIG_INT | | | |
82 * +---------+--------------+-----------+------------+----------+
83 *
84 * Note 1: If AI command and AO command are used simultaneously, only
85 * one may have scan_begin_src == TRIG_TIMER.
86 *
87 * Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
88 * DIO channel 16 (pin 49) which will need to be configured as
89 * a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input
90 * (pin 17) is used instead. For PCI230, scan_begin_src ==
91 * TRIG_EXT is not supported. The trigger is a rising edge
92 * on the input.
93 *
94 * Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
95 * (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The
96 * convert_arg value is interpreted as follows:
97 *
98 * convert_arg == (CR_EDGE | 0) => rising edge
99 * convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
100 * convert_arg == 0 => falling edge (backwards compatibility)
101 * convert_arg == 1 => rising edge (backwards compatibility)
102 *
103 * All entries in the channel list must use the same analogue reference.
104 * If the analogue reference is not AREF_DIFF (not differential) each
105 * pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
106 * input range. The input ranges used in the sequence must be all
107 * bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel
108 * sequence must consist of 1 or more identical subsequences. Within the
109 * subsequence, channels must be in ascending order with no repeated
110 * channels. For example, the following sequences are valid: 0 1 2 3
111 * (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
112 * subsequence), 1 1 1 1 (repeated valid subsequence). The following
113 * sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
114 * (incompletely repeated subsequence). Some versions of the PCI230+ and
115 * PCI260+ have a bug that requires a subsequence longer than one entry
116 * long to include channel 0.
117 *
118 * AO Subdevice:
119 *
120 * The AO subdevice has 2 channels with 12-bit resolution.
121 * The following output ranges are supported:
122 * 0 => [0, 10] V
123 * 1 => [-10, +10] V
124 *
125 * AO Commands:
126 *
127 * +=========+==============+===========+============+==========+
128 * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
129 * +=========+==============+===========+============+==========+
130 * |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE |
131 * | | TRIG_EXT(2) | | |TRIG_COUNT|
132 * | | TRIG_INT | | | |
133 * +---------+--------------+-----------+------------+----------+
134 *
135 * Note 1: If AI command and AO command are used simultaneously, only
136 * one may have scan_begin_src == TRIG_TIMER.
137 *
138 * Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
139 * configured as a PCI230+ and is only supported on later
140 * versions of the card. As a card configured as a PCI230+ is
141 * not guaranteed to support external triggering, please consider
142 * this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK
143 * input (PCI230+ pin 25). Triggering will be on the rising edge
144 * unless the CR_INVERT flag is set in scan_begin_arg.
145 *
146 * The channels in the channel sequence must be in ascending order with
147 * no repeats. All entries in the channel sequence must use the same
148 * output range.
149 *
150 * DIO Subdevice:
151 *
152 * The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO
153 * channels are configurable as inputs or outputs in four groups:
154 *
155 * Port A - channels 0 to 7
156 * Port B - channels 8 to 15
157 * Port CL - channels 16 to 19
158 * Port CH - channels 20 to 23
159 *
160 * Only mode 0 of the 8255 chip is supported.
161 *
162 * Bit 0 of port C (DIO channel 16) is also used as an external scan
163 * trigger input for AI commands on PCI230 and PCI230+, so would need to
164 * be configured as an input to use it for that purpose.
165 */
166
167 /*
168 * Extra triggered scan functionality, interrupt bug-fix added by Steve
169 * Sharples. Support for PCI230+/260+, more triggered scan functionality,
170 * and workarounds for (or detection of) various hardware problems added
171 * by Ian Abbott.
172 */
173
174 #include <linux/module.h>
175 #include <linux/delay.h>
176 #include <linux/interrupt.h>
177
178 #include "../comedi_pci.h"
179
180 #include "comedi_8254.h"
181 #include "8255.h"
182
183 /*
184 * PCI230 PCI configuration register information
185 */
186 #define PCI_DEVICE_ID_PCI230 0x0000
187 #define PCI_DEVICE_ID_PCI260 0x0006
188
189 /*
190 * PCI230 i/o space 1 registers.
191 */
192 #define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */
193 #define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */
194 #define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */
195 #define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */
196 #define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */
197 #define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */
198 #define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */
199 #define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */
200 #define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */
201 #define PCI230_INT_STAT 0x1E /* Interrupt status (r) */
202
203 /*
204 * PCI230 i/o space 2 registers.
205 */
206 #define PCI230_DACCON 0x00 /* DAC control */
207 #define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */
208 #define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */
209 #define PCI230_ADCDATA 0x08 /* ADC data (r) */
210 #define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */
211 #define PCI230_ADCCON 0x0A /* ADC control */
212 #define PCI230_ADCEN 0x0C /* ADC channel enable bits */
213 #define PCI230_ADCG 0x0E /* ADC gain control bits */
214 /* PCI230+ i/o space 2 additional registers. */
215 #define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */
216 #define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */
217 #define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */
218 #define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */
219 #define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */
220 #define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */
221 #define PCI230P_EXTFUNC 0x1C /* Extended functions */
222 #define PCI230P_HWVER 0x1E /* Hardware version (r) */
223 /* PCI230+ hardware version 2 onwards. */
224 #define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */
225 #define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */
226 #define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */
227
228 /*
229 * DACCON read-write values.
230 */
231 #define PCI230_DAC_OR(x) (((x) & 0x1) << 0)
232 #define PCI230_DAC_OR_UNI PCI230_DAC_OR(0) /* Output unipolar */
233 #define PCI230_DAC_OR_BIP PCI230_DAC_OR(1) /* Output bipolar */
234 #define PCI230_DAC_OR_MASK PCI230_DAC_OR(1)
235 /*
236 * The following applies only if DAC FIFO support is enabled in the EXTFUNC
237 * register (and only for PCI230+ hardware version 2 onwards).
238 */
239 #define PCI230P2_DAC_FIFO_EN BIT(8) /* FIFO enable */
240 /*
241 * The following apply only if the DAC FIFO is enabled (and only for PCI230+
242 * hardware version 2 onwards).
243 */
244 #define PCI230P2_DAC_TRIG(x) (((x) & 0x7) << 2)
245 #define PCI230P2_DAC_TRIG_NONE PCI230P2_DAC_TRIG(0) /* none */
246 #define PCI230P2_DAC_TRIG_SW PCI230P2_DAC_TRIG(1) /* soft trig */
247 #define PCI230P2_DAC_TRIG_EXTP PCI230P2_DAC_TRIG(2) /* ext + edge */
248 #define PCI230P2_DAC_TRIG_EXTN PCI230P2_DAC_TRIG(3) /* ext - edge */
249 #define PCI230P2_DAC_TRIG_Z2CT0 PCI230P2_DAC_TRIG(4) /* Z2 CT0 out */
250 #define PCI230P2_DAC_TRIG_Z2CT1 PCI230P2_DAC_TRIG(5) /* Z2 CT1 out */
251 #define PCI230P2_DAC_TRIG_Z2CT2 PCI230P2_DAC_TRIG(6) /* Z2 CT2 out */
252 #define PCI230P2_DAC_TRIG_MASK PCI230P2_DAC_TRIG(7)
253 #define PCI230P2_DAC_FIFO_WRAP BIT(7) /* FIFO wraparound mode */
254 #define PCI230P2_DAC_INT_FIFO(x) (((x) & 7) << 9)
255 #define PCI230P2_DAC_INT_FIFO_EMPTY PCI230P2_DAC_INT_FIFO(0) /* empty */
256 #define PCI230P2_DAC_INT_FIFO_NEMPTY PCI230P2_DAC_INT_FIFO(1) /* !empty */
257 #define PCI230P2_DAC_INT_FIFO_NHALF PCI230P2_DAC_INT_FIFO(2) /* !half */
258 #define PCI230P2_DAC_INT_FIFO_HALF PCI230P2_DAC_INT_FIFO(3) /* half */
259 #define PCI230P2_DAC_INT_FIFO_NFULL PCI230P2_DAC_INT_FIFO(4) /* !full */
260 #define PCI230P2_DAC_INT_FIFO_FULL PCI230P2_DAC_INT_FIFO(5) /* full */
261 #define PCI230P2_DAC_INT_FIFO_MASK PCI230P2_DAC_INT_FIFO(7)
262
263 /*
264 * DACCON read-only values.
265 */
266 #define PCI230_DAC_BUSY BIT(1) /* DAC busy. */
267 /*
268 * The following apply only if the DAC FIFO is enabled (and only for PCI230+
269 * hardware version 2 onwards).
270 */
271 #define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED BIT(5) /* Underrun error */
272 #define PCI230P2_DAC_FIFO_EMPTY BIT(13) /* FIFO empty */
273 #define PCI230P2_DAC_FIFO_FULL BIT(14) /* FIFO full */
274 #define PCI230P2_DAC_FIFO_HALF BIT(15) /* FIFO half full */
275
276 /*
277 * DACCON write-only, transient values.
278 */
279 /*
280 * The following apply only if the DAC FIFO is enabled (and only for PCI230+
281 * hardware version 2 onwards).
282 */
283 #define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR BIT(5) /* Clear underrun */
284 #define PCI230P2_DAC_FIFO_RESET BIT(12) /* FIFO reset */
285
286 /*
287 * PCI230+ hardware version 2 DAC FIFO levels.
288 */
289 #define PCI230P2_DAC_FIFOLEVEL_HALF 512
290 #define PCI230P2_DAC_FIFOLEVEL_FULL 1024
291 /* Free space in DAC FIFO. */
292 #define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL
293 #define PCI230P2_DAC_FIFOROOM_ONETOHALF \
294 (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
295 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1
296 #define PCI230P2_DAC_FIFOROOM_FULL 0
297
298 /*
299 * ADCCON read/write values.
300 */
301 #define PCI230_ADC_TRIG(x) (((x) & 0x7) << 0)
302 #define PCI230_ADC_TRIG_NONE PCI230_ADC_TRIG(0) /* none */
303 #define PCI230_ADC_TRIG_SW PCI230_ADC_TRIG(1) /* soft trig */
304 #define PCI230_ADC_TRIG_EXTP PCI230_ADC_TRIG(2) /* ext + edge */
305 #define PCI230_ADC_TRIG_EXTN PCI230_ADC_TRIG(3) /* ext - edge */
306 #define PCI230_ADC_TRIG_Z2CT0 PCI230_ADC_TRIG(4) /* Z2 CT0 out*/
307 #define PCI230_ADC_TRIG_Z2CT1 PCI230_ADC_TRIG(5) /* Z2 CT1 out */
308 #define PCI230_ADC_TRIG_Z2CT2 PCI230_ADC_TRIG(6) /* Z2 CT2 out */
309 #define PCI230_ADC_TRIG_MASK PCI230_ADC_TRIG(7)
310 #define PCI230_ADC_IR(x) (((x) & 0x1) << 3)
311 #define PCI230_ADC_IR_UNI PCI230_ADC_IR(0) /* Input unipolar */
312 #define PCI230_ADC_IR_BIP PCI230_ADC_IR(1) /* Input bipolar */
313 #define PCI230_ADC_IR_MASK PCI230_ADC_IR(1)
314 #define PCI230_ADC_IM(x) (((x) & 0x1) << 4)
315 #define PCI230_ADC_IM_SE PCI230_ADC_IM(0) /* single ended */
316 #define PCI230_ADC_IM_DIF PCI230_ADC_IM(1) /* differential */
317 #define PCI230_ADC_IM_MASK PCI230_ADC_IM(1)
318 #define PCI230_ADC_FIFO_EN BIT(8) /* FIFO enable */
319 #define PCI230_ADC_INT_FIFO(x) (((x) & 0x7) << 9)
320 #define PCI230_ADC_INT_FIFO_EMPTY PCI230_ADC_INT_FIFO(0) /* empty */
321 #define PCI230_ADC_INT_FIFO_NEMPTY PCI230_ADC_INT_FIFO(1) /* !empty */
322 #define PCI230_ADC_INT_FIFO_NHALF PCI230_ADC_INT_FIFO(2) /* !half */
323 #define PCI230_ADC_INT_FIFO_HALF PCI230_ADC_INT_FIFO(3) /* half */
324 #define PCI230_ADC_INT_FIFO_NFULL PCI230_ADC_INT_FIFO(4) /* !full */
325 #define PCI230_ADC_INT_FIFO_FULL PCI230_ADC_INT_FIFO(5) /* full */
326 #define PCI230P_ADC_INT_FIFO_THRESH PCI230_ADC_INT_FIFO(7) /* threshold */
327 #define PCI230_ADC_INT_FIFO_MASK PCI230_ADC_INT_FIFO(7)
328
329 /*
330 * ADCCON write-only, transient values.
331 */
332 #define PCI230_ADC_FIFO_RESET BIT(12) /* FIFO reset */
333 #define PCI230_ADC_GLOB_RESET BIT(13) /* Global reset */
334
335 /*
336 * ADCCON read-only values.
337 */
338 #define PCI230_ADC_BUSY BIT(15) /* ADC busy */
339 #define PCI230_ADC_FIFO_EMPTY BIT(12) /* FIFO empty */
340 #define PCI230_ADC_FIFO_FULL BIT(13) /* FIFO full */
341 #define PCI230_ADC_FIFO_HALF BIT(14) /* FIFO half full */
342 #define PCI230_ADC_FIFO_FULL_LATCHED BIT(5) /* FIFO overrun occurred */
343
344 /*
345 * PCI230 ADC FIFO levels.
346 */
347 #define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */
348 #define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */
349
350 /*
351 * PCI230+ EXTFUNC values.
352 */
353 /* Route EXTTRIG pin to external gate inputs. */
354 #define PCI230P_EXTFUNC_GAT_EXTTRIG BIT(0)
355 /* PCI230+ hardware version 2 values. */
356 /* Allow DAC FIFO to be enabled. */
357 #define PCI230P2_EXTFUNC_DACFIFO BIT(1)
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
pci230_clk_config(unsigned int chan,unsigned int src)371 static unsigned int pci230_clk_config(unsigned int chan, unsigned int src)
372 {
373 return ((chan & 3) << 3) | (src & 7);
374 }
375
376 /*
377 * Counter/timer gate input configuration sources.
378 */
379 #define GAT_VCC 0 /* VCC (i.e. enabled) */
380 #define GAT_GND 1 /* GND (i.e. disabled) */
381 #define GAT_EXT 2 /* external gate input (PPCn on PCI230) */
382 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
383
pci230_gat_config(unsigned int chan,unsigned int src)384 static unsigned int pci230_gat_config(unsigned int chan, unsigned int src)
385 {
386 return ((chan & 3) << 3) | (src & 7);
387 }
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 /*
402 * Interrupt enables/status register values.
403 */
404 #define PCI230_INT_DISABLE 0
405 #define PCI230_INT_PPI_C0 BIT(0)
406 #define PCI230_INT_PPI_C3 BIT(1)
407 #define PCI230_INT_ADC BIT(2)
408 #define PCI230_INT_ZCLK_CT1 BIT(5)
409 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
410 #define PCI230P2_INT_DAC BIT(4)
411
412 /*
413 * (Potentially) shared resources and their owners
414 */
415 enum {
416 RES_Z2CT0 = BIT(0), /* Z2-CT0 */
417 RES_Z2CT1 = BIT(1), /* Z2-CT1 */
418 RES_Z2CT2 = BIT(2) /* Z2-CT2 */
419 };
420
421 enum {
422 OWNER_AICMD, /* Owned by AI command */
423 OWNER_AOCMD, /* Owned by AO command */
424 NUM_OWNERS /* Number of owners */
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 /* Current CPU. XXX should this be hard_smp_processor_id()? */
435 #define THISCPU smp_processor_id()
436
437 /*
438 * Board descriptions for the two boards supported.
439 */
440
441 struct pci230_board {
442 const char *name;
443 unsigned short id;
444 unsigned char ai_bits;
445 unsigned char ao_bits;
446 unsigned char min_hwver; /* Minimum hardware version supported. */
447 unsigned int have_dio:1;
448 };
449
450 static const struct pci230_board pci230_boards[] = {
451 {
452 .name = "pci230+",
453 .id = PCI_DEVICE_ID_PCI230,
454 .ai_bits = 16,
455 .ao_bits = 12,
456 .have_dio = true,
457 .min_hwver = 1,
458 },
459 {
460 .name = "pci260+",
461 .id = PCI_DEVICE_ID_PCI260,
462 .ai_bits = 16,
463 .min_hwver = 1,
464 },
465 {
466 .name = "pci230",
467 .id = PCI_DEVICE_ID_PCI230,
468 .ai_bits = 12,
469 .ao_bits = 12,
470 .have_dio = true,
471 },
472 {
473 .name = "pci260",
474 .id = PCI_DEVICE_ID_PCI260,
475 .ai_bits = 12,
476 },
477 };
478
479 struct pci230_private {
480 spinlock_t isr_spinlock; /* Interrupt spin lock */
481 spinlock_t res_spinlock; /* Shared resources spin lock */
482 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
483 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
484 unsigned long daqio; /* PCI230's DAQ I/O space */
485 int intr_cpuid; /* ID of CPU running ISR */
486 unsigned short hwver; /* Hardware version (for '+' models) */
487 unsigned short adccon; /* ADCCON register value */
488 unsigned short daccon; /* DACCON register value */
489 unsigned short adcfifothresh; /* ADC FIFO threshold (PCI230+/260+) */
490 unsigned short adcg; /* ADCG register value */
491 unsigned char ier; /* Interrupt enable bits */
492 unsigned char res_owned[NUM_OWNERS]; /* Owned resources */
493 unsigned int intr_running:1; /* Flag set in interrupt routine */
494 unsigned int ai_bipolar:1; /* Flag AI range is bipolar */
495 unsigned int ao_bipolar:1; /* Flag AO range is bipolar */
496 unsigned int ai_cmd_started:1; /* Flag AI command started */
497 unsigned int ao_cmd_started:1; /* Flag AO command started */
498 };
499
500 /* PCI230 clock source periods in ns */
501 static const unsigned int pci230_timebase[8] = {
502 [CLK_10MHZ] = I8254_OSC_BASE_10MHZ,
503 [CLK_1MHZ] = I8254_OSC_BASE_1MHZ,
504 [CLK_100KHZ] = I8254_OSC_BASE_100KHZ,
505 [CLK_10KHZ] = I8254_OSC_BASE_10KHZ,
506 [CLK_1KHZ] = I8254_OSC_BASE_1KHZ,
507 };
508
509 /* PCI230 analogue input range table */
510 static const struct comedi_lrange pci230_ai_range = {
511 7, {
512 BIP_RANGE(10),
513 BIP_RANGE(5),
514 BIP_RANGE(2.5),
515 BIP_RANGE(1.25),
516 UNI_RANGE(10),
517 UNI_RANGE(5),
518 UNI_RANGE(2.5)
519 }
520 };
521
522 /* PCI230 analogue gain bits for each input range. */
523 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
524
525 /* PCI230 analogue output range table */
526 static const struct comedi_lrange pci230_ao_range = {
527 2, {
528 UNI_RANGE(10),
529 BIP_RANGE(10)
530 }
531 };
532
pci230_ai_read(struct comedi_device * dev)533 static unsigned short pci230_ai_read(struct comedi_device *dev)
534 {
535 const struct pci230_board *board = dev->board_ptr;
536 struct pci230_private *devpriv = dev->private;
537 unsigned short data;
538
539 /* Read sample. */
540 data = inw(devpriv->daqio + PCI230_ADCDATA);
541 /*
542 * PCI230 is 12 bit - stored in upper bits of 16 bit register
543 * (lower four bits reserved for expansion). PCI230+ is 16 bit AI.
544 *
545 * If a bipolar range was specified, mangle it
546 * (twos complement->straight binary).
547 */
548 if (devpriv->ai_bipolar)
549 data ^= 0x8000;
550 data >>= (16 - board->ai_bits);
551 return data;
552 }
553
pci230_ao_mangle_datum(struct comedi_device * dev,unsigned short datum)554 static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
555 unsigned short datum)
556 {
557 const struct pci230_board *board = dev->board_ptr;
558 struct pci230_private *devpriv = dev->private;
559
560 /*
561 * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
562 * four bits reserved for expansion). PCI230+ is also 12 bit AO.
563 */
564 datum <<= (16 - board->ao_bits);
565 /*
566 * If a bipolar range was specified, mangle it
567 * (straight binary->twos complement).
568 */
569 if (devpriv->ao_bipolar)
570 datum ^= 0x8000;
571 return datum;
572 }
573
pci230_ao_write_nofifo(struct comedi_device * dev,unsigned short datum,unsigned int chan)574 static void pci230_ao_write_nofifo(struct comedi_device *dev,
575 unsigned short datum, unsigned int chan)
576 {
577 struct pci230_private *devpriv = dev->private;
578
579 /* Write mangled datum to appropriate DACOUT register. */
580 outw(pci230_ao_mangle_datum(dev, datum),
581 devpriv->daqio + ((chan == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
582 }
583
pci230_ao_write_fifo(struct comedi_device * dev,unsigned short datum,unsigned int chan)584 static void pci230_ao_write_fifo(struct comedi_device *dev,
585 unsigned short datum, unsigned int chan)
586 {
587 struct pci230_private *devpriv = dev->private;
588
589 /* Write mangled datum to appropriate DACDATA register. */
590 outw(pci230_ao_mangle_datum(dev, datum),
591 devpriv->daqio + PCI230P2_DACDATA);
592 }
593
pci230_claim_shared(struct comedi_device * dev,unsigned char res_mask,unsigned int owner)594 static bool pci230_claim_shared(struct comedi_device *dev,
595 unsigned char res_mask, unsigned int owner)
596 {
597 struct pci230_private *devpriv = dev->private;
598 unsigned int o;
599 unsigned long irqflags;
600
601 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
602 for (o = 0; o < NUM_OWNERS; o++) {
603 if (o == owner)
604 continue;
605 if (devpriv->res_owned[o] & res_mask) {
606 spin_unlock_irqrestore(&devpriv->res_spinlock,
607 irqflags);
608 return false;
609 }
610 }
611 devpriv->res_owned[owner] |= res_mask;
612 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
613 return true;
614 }
615
pci230_release_shared(struct comedi_device * dev,unsigned char res_mask,unsigned int owner)616 static void pci230_release_shared(struct comedi_device *dev,
617 unsigned char res_mask, unsigned int owner)
618 {
619 struct pci230_private *devpriv = dev->private;
620 unsigned long irqflags;
621
622 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
623 devpriv->res_owned[owner] &= ~res_mask;
624 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
625 }
626
pci230_release_all_resources(struct comedi_device * dev,unsigned int owner)627 static void pci230_release_all_resources(struct comedi_device *dev,
628 unsigned int owner)
629 {
630 pci230_release_shared(dev, (unsigned char)~0, owner);
631 }
632
pci230_divide_ns(u64 ns,unsigned int timebase,unsigned int flags)633 static unsigned int pci230_divide_ns(u64 ns, unsigned int timebase,
634 unsigned int flags)
635 {
636 u64 div;
637 unsigned int rem;
638
639 div = ns;
640 rem = do_div(div, timebase);
641 switch (flags & CMDF_ROUND_MASK) {
642 default:
643 case CMDF_ROUND_NEAREST:
644 div += DIV_ROUND_CLOSEST(rem, timebase);
645 break;
646 case CMDF_ROUND_DOWN:
647 break;
648 case CMDF_ROUND_UP:
649 div += DIV_ROUND_UP(rem, timebase);
650 break;
651 }
652 return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
653 }
654
655 /*
656 * Given desired period in ns, returns the required internal clock source
657 * and gets the initial count.
658 */
pci230_choose_clk_count(u64 ns,unsigned int * count,unsigned int flags)659 static unsigned int pci230_choose_clk_count(u64 ns, unsigned int *count,
660 unsigned int flags)
661 {
662 unsigned int clk_src, cnt;
663
664 for (clk_src = CLK_10MHZ;; clk_src++) {
665 cnt = pci230_divide_ns(ns, pci230_timebase[clk_src], flags);
666 if (cnt <= 65536 || clk_src == CLK_1KHZ)
667 break;
668 }
669 *count = cnt;
670 return clk_src;
671 }
672
pci230_ns_to_single_timer(unsigned int * ns,unsigned int flags)673 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int flags)
674 {
675 unsigned int count;
676 unsigned int clk_src;
677
678 clk_src = pci230_choose_clk_count(*ns, &count, flags);
679 *ns = count * pci230_timebase[clk_src];
680 }
681
pci230_ct_setup_ns_mode(struct comedi_device * dev,unsigned int ct,unsigned int mode,u64 ns,unsigned int flags)682 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
683 unsigned int mode, u64 ns,
684 unsigned int flags)
685 {
686 unsigned int clk_src;
687 unsigned int count;
688
689 /* Set mode. */
690 comedi_8254_set_mode(dev->pacer, ct, mode);
691 /* Determine clock source and count. */
692 clk_src = pci230_choose_clk_count(ns, &count, flags);
693 /* Program clock source. */
694 outb(pci230_clk_config(ct, clk_src), dev->iobase + PCI230_ZCLK_SCE);
695 /* Set initial count. */
696 if (count >= 65536)
697 count = 0;
698
699 comedi_8254_write(dev->pacer, ct, count);
700 }
701
pci230_cancel_ct(struct comedi_device * dev,unsigned int ct)702 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
703 {
704 /* Counter ct, 8254 mode 1, initial count not written. */
705 comedi_8254_set_mode(dev->pacer, ct, I8254_MODE1);
706 }
707
pci230_ai_eoc(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned long context)708 static int pci230_ai_eoc(struct comedi_device *dev,
709 struct comedi_subdevice *s,
710 struct comedi_insn *insn,
711 unsigned long context)
712 {
713 struct pci230_private *devpriv = dev->private;
714 unsigned int status;
715
716 status = inw(devpriv->daqio + PCI230_ADCCON);
717 if ((status & PCI230_ADC_FIFO_EMPTY) == 0)
718 return 0;
719 return -EBUSY;
720 }
721
pci230_ai_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)722 static int pci230_ai_insn_read(struct comedi_device *dev,
723 struct comedi_subdevice *s,
724 struct comedi_insn *insn, unsigned int *data)
725 {
726 struct pci230_private *devpriv = dev->private;
727 unsigned int n;
728 unsigned int chan, range, aref;
729 unsigned int gainshift;
730 unsigned short adccon, adcen;
731 int ret;
732
733 /* Unpack channel and range. */
734 chan = CR_CHAN(insn->chanspec);
735 range = CR_RANGE(insn->chanspec);
736 aref = CR_AREF(insn->chanspec);
737 if (aref == AREF_DIFF) {
738 /* Differential. */
739 if (chan >= s->n_chan / 2) {
740 dev_dbg(dev->class_dev,
741 "%s: differential channel number out of range 0 to %u\n",
742 __func__, (s->n_chan / 2) - 1);
743 return -EINVAL;
744 }
745 }
746
747 /*
748 * Use Z2-CT2 as a conversion trigger instead of the built-in
749 * software trigger, as otherwise triggering of differential channels
750 * doesn't work properly for some versions of PCI230/260. Also set
751 * FIFO mode because the ADC busy bit only works for software triggers.
752 */
753 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
754 /* Set Z2-CT2 output low to avoid any false triggers. */
755 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0);
756 devpriv->ai_bipolar = comedi_range_is_bipolar(s, range);
757 if (aref == AREF_DIFF) {
758 /* Differential. */
759 gainshift = chan * 2;
760 if (devpriv->hwver == 0) {
761 /*
762 * Original PCI230/260 expects both inputs of the
763 * differential channel to be enabled.
764 */
765 adcen = 3 << gainshift;
766 } else {
767 /*
768 * PCI230+/260+ expects only one input of the
769 * differential channel to be enabled.
770 */
771 adcen = 1 << gainshift;
772 }
773 adccon |= PCI230_ADC_IM_DIF;
774 } else {
775 /* Single ended. */
776 adcen = 1 << chan;
777 gainshift = chan & ~1;
778 adccon |= PCI230_ADC_IM_SE;
779 }
780 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) |
781 (pci230_ai_gain[range] << gainshift);
782 if (devpriv->ai_bipolar)
783 adccon |= PCI230_ADC_IR_BIP;
784 else
785 adccon |= PCI230_ADC_IR_UNI;
786
787 /*
788 * Enable only this channel in the scan list - otherwise by default
789 * we'll get one sample from each channel.
790 */
791 outw(adcen, devpriv->daqio + PCI230_ADCEN);
792
793 /* Set gain for channel. */
794 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
795
796 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
797 devpriv->adccon = adccon;
798 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
799
800 /* Convert n samples */
801 for (n = 0; n < insn->n; n++) {
802 /*
803 * Trigger conversion by toggling Z2-CT2 output
804 * (finish with output high).
805 */
806 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0);
807 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1);
808
809 /* wait for conversion to end */
810 ret = comedi_timeout(dev, s, insn, pci230_ai_eoc, 0);
811 if (ret)
812 return ret;
813
814 /* read data */
815 data[n] = pci230_ai_read(dev);
816 }
817
818 /* return the number of samples read/written */
819 return n;
820 }
821
pci230_ao_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)822 static int pci230_ao_insn_write(struct comedi_device *dev,
823 struct comedi_subdevice *s,
824 struct comedi_insn *insn,
825 unsigned int *data)
826 {
827 struct pci230_private *devpriv = dev->private;
828 unsigned int chan = CR_CHAN(insn->chanspec);
829 unsigned int range = CR_RANGE(insn->chanspec);
830 unsigned int val = s->readback[chan];
831 int i;
832
833 /*
834 * Set range - see analogue output range table; 0 => unipolar 10V,
835 * 1 => bipolar +/-10V range scale
836 */
837 devpriv->ao_bipolar = comedi_range_is_bipolar(s, range);
838 outw(range, devpriv->daqio + PCI230_DACCON);
839
840 for (i = 0; i < insn->n; i++) {
841 val = data[i];
842 pci230_ao_write_nofifo(dev, val, chan);
843 }
844 s->readback[chan] = val;
845
846 return insn->n;
847 }
848
pci230_ao_check_chanlist(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)849 static int pci230_ao_check_chanlist(struct comedi_device *dev,
850 struct comedi_subdevice *s,
851 struct comedi_cmd *cmd)
852 {
853 unsigned int prev_chan = CR_CHAN(cmd->chanlist[0]);
854 unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
855 int i;
856
857 for (i = 1; i < cmd->chanlist_len; i++) {
858 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
859 unsigned int range = CR_RANGE(cmd->chanlist[i]);
860
861 if (chan < prev_chan) {
862 dev_dbg(dev->class_dev,
863 "%s: channel numbers must increase\n",
864 __func__);
865 return -EINVAL;
866 }
867
868 if (range != range0) {
869 dev_dbg(dev->class_dev,
870 "%s: channels must have the same range\n",
871 __func__);
872 return -EINVAL;
873 }
874
875 prev_chan = chan;
876 }
877
878 return 0;
879 }
880
pci230_ao_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)881 static int pci230_ao_cmdtest(struct comedi_device *dev,
882 struct comedi_subdevice *s, struct comedi_cmd *cmd)
883 {
884 const struct pci230_board *board = dev->board_ptr;
885 struct pci230_private *devpriv = dev->private;
886 int err = 0;
887 unsigned int tmp;
888
889 /* Step 1 : check if triggers are trivially valid */
890
891 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
892
893 tmp = TRIG_TIMER | TRIG_INT;
894 if (board->min_hwver > 0 && devpriv->hwver >= 2) {
895 /*
896 * For PCI230+ hardware version 2 onwards, allow external
897 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
898 *
899 * FIXME: The permitted scan_begin_src values shouldn't depend
900 * on devpriv->hwver (the detected card's actual hardware
901 * version). They should only depend on board->min_hwver
902 * (the static capabilities of the configured card). To fix
903 * it, a new card model, e.g. "pci230+2" would have to be
904 * defined with min_hwver set to 2. It doesn't seem worth it
905 * for this alone. At the moment, please consider
906 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
907 * guarantee!
908 */
909 tmp |= TRIG_EXT;
910 }
911 err |= comedi_check_trigger_src(&cmd->scan_begin_src, tmp);
912
913 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
914 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
915 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
916
917 if (err)
918 return 1;
919
920 /* Step 2a : make sure trigger sources are unique */
921
922 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
923 err |= comedi_check_trigger_is_unique(cmd->stop_src);
924
925 /* Step 2b : and mutually compatible */
926
927 if (err)
928 return 2;
929
930 /* Step 3: check if arguments are trivially valid */
931
932 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
933
934 #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */
935 /*
936 * Comedi limit due to unsigned int cmd. Driver limit =
937 * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s
938 */
939 #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */
940
941 switch (cmd->scan_begin_src) {
942 case TRIG_TIMER:
943 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
944 MAX_SPEED_AO);
945 err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
946 MIN_SPEED_AO);
947 break;
948 case TRIG_EXT:
949 /*
950 * External trigger - for PCI230+ hardware version 2 onwards.
951 */
952 /* Trigger number must be 0. */
953 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
954 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
955 ~CR_FLAGS_MASK);
956 err |= -EINVAL;
957 }
958 /*
959 * The only flags allowed are CR_EDGE and CR_INVERT.
960 * The CR_EDGE flag is ignored.
961 */
962 if (cmd->scan_begin_arg & CR_FLAGS_MASK &
963 ~(CR_EDGE | CR_INVERT)) {
964 cmd->scan_begin_arg =
965 COMBINE(cmd->scan_begin_arg, 0,
966 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
967 err |= -EINVAL;
968 }
969 break;
970 default:
971 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
972 break;
973 }
974
975 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
976 cmd->chanlist_len);
977
978 if (cmd->stop_src == TRIG_COUNT)
979 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
980 else /* TRIG_NONE */
981 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
982
983 if (err)
984 return 3;
985
986 /* Step 4: fix up any arguments */
987
988 if (cmd->scan_begin_src == TRIG_TIMER) {
989 tmp = cmd->scan_begin_arg;
990 pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags);
991 if (tmp != cmd->scan_begin_arg)
992 err++;
993 }
994
995 if (err)
996 return 4;
997
998 /* Step 5: check channel list if it exists */
999 if (cmd->chanlist && cmd->chanlist_len > 0)
1000 err |= pci230_ao_check_chanlist(dev, s, cmd);
1001
1002 if (err)
1003 return 5;
1004
1005 return 0;
1006 }
1007
pci230_ao_stop(struct comedi_device * dev,struct comedi_subdevice * s)1008 static void pci230_ao_stop(struct comedi_device *dev,
1009 struct comedi_subdevice *s)
1010 {
1011 struct pci230_private *devpriv = dev->private;
1012 unsigned long irqflags;
1013 unsigned char intsrc;
1014 bool started;
1015 struct comedi_cmd *cmd;
1016
1017 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1018 started = devpriv->ao_cmd_started;
1019 devpriv->ao_cmd_started = false;
1020 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1021 if (!started)
1022 return;
1023 cmd = &s->async->cmd;
1024 if (cmd->scan_begin_src == TRIG_TIMER) {
1025 /* Stop scan rate generator. */
1026 pci230_cancel_ct(dev, 1);
1027 }
1028 /* Determine interrupt source. */
1029 if (devpriv->hwver < 2) {
1030 /* Not using DAC FIFO. Using CT1 interrupt. */
1031 intsrc = PCI230_INT_ZCLK_CT1;
1032 } else {
1033 /* Using DAC FIFO interrupt. */
1034 intsrc = PCI230P2_INT_DAC;
1035 }
1036 /*
1037 * Disable interrupt and wait for interrupt routine to finish running
1038 * unless we are called from the interrupt routine.
1039 */
1040 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1041 devpriv->ier &= ~intsrc;
1042 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
1043 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1044 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1045 }
1046 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1047 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1048 if (devpriv->hwver >= 2) {
1049 /*
1050 * Using DAC FIFO. Reset FIFO, clear underrun error,
1051 * disable FIFO.
1052 */
1053 devpriv->daccon &= PCI230_DAC_OR_MASK;
1054 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET |
1055 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
1056 devpriv->daqio + PCI230_DACCON);
1057 }
1058 /* Release resources. */
1059 pci230_release_all_resources(dev, OWNER_AOCMD);
1060 }
1061
pci230_handle_ao_nofifo(struct comedi_device * dev,struct comedi_subdevice * s)1062 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
1063 struct comedi_subdevice *s)
1064 {
1065 struct comedi_async *async = s->async;
1066 struct comedi_cmd *cmd = &async->cmd;
1067 unsigned short data;
1068 int i;
1069
1070 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
1071 return;
1072
1073 for (i = 0; i < cmd->chanlist_len; i++) {
1074 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
1075
1076 if (!comedi_buf_read_samples(s, &data, 1)) {
1077 async->events |= COMEDI_CB_OVERFLOW;
1078 return;
1079 }
1080 pci230_ao_write_nofifo(dev, data, chan);
1081 s->readback[chan] = data;
1082 }
1083
1084 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
1085 async->events |= COMEDI_CB_EOA;
1086 }
1087
1088 /*
1089 * Loads DAC FIFO (if using it) from buffer.
1090 * Returns false if AO finished due to completion or error, true if still going.
1091 */
pci230_handle_ao_fifo(struct comedi_device * dev,struct comedi_subdevice * s)1092 static bool pci230_handle_ao_fifo(struct comedi_device *dev,
1093 struct comedi_subdevice *s)
1094 {
1095 struct pci230_private *devpriv = dev->private;
1096 struct comedi_async *async = s->async;
1097 struct comedi_cmd *cmd = &async->cmd;
1098 unsigned int num_scans = comedi_nscans_left(s, 0);
1099 unsigned int room;
1100 unsigned short dacstat;
1101 unsigned int i, n;
1102 unsigned int events = 0;
1103
1104 /* Get DAC FIFO status. */
1105 dacstat = inw(devpriv->daqio + PCI230_DACCON);
1106
1107 if (cmd->stop_src == TRIG_COUNT && num_scans == 0)
1108 events |= COMEDI_CB_EOA;
1109
1110 if (events == 0) {
1111 /* Check for FIFO underrun. */
1112 if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
1113 dev_err(dev->class_dev, "AO FIFO underrun\n");
1114 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1115 }
1116 /*
1117 * Check for buffer underrun if FIFO less than half full
1118 * (otherwise there will be loads of "DAC FIFO not half full"
1119 * interrupts).
1120 */
1121 if (num_scans == 0 &&
1122 (dacstat & PCI230P2_DAC_FIFO_HALF) == 0) {
1123 dev_err(dev->class_dev, "AO buffer underrun\n");
1124 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1125 }
1126 }
1127 if (events == 0) {
1128 /* Determine how much room is in the FIFO (in samples). */
1129 if (dacstat & PCI230P2_DAC_FIFO_FULL)
1130 room = PCI230P2_DAC_FIFOROOM_FULL;
1131 else if (dacstat & PCI230P2_DAC_FIFO_HALF)
1132 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
1133 else if (dacstat & PCI230P2_DAC_FIFO_EMPTY)
1134 room = PCI230P2_DAC_FIFOROOM_EMPTY;
1135 else
1136 room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
1137 /* Convert room to number of scans that can be added. */
1138 room /= cmd->chanlist_len;
1139 /* Determine number of scans to process. */
1140 if (num_scans > room)
1141 num_scans = room;
1142 /* Process scans. */
1143 for (n = 0; n < num_scans; n++) {
1144 for (i = 0; i < cmd->chanlist_len; i++) {
1145 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
1146 unsigned short datum;
1147
1148 comedi_buf_read_samples(s, &datum, 1);
1149 pci230_ao_write_fifo(dev, datum, chan);
1150 s->readback[chan] = datum;
1151 }
1152 }
1153
1154 if (cmd->stop_src == TRIG_COUNT &&
1155 async->scans_done >= cmd->stop_arg) {
1156 /*
1157 * All data for the command has been written
1158 * to FIFO. Set FIFO interrupt trigger level
1159 * to 'empty'.
1160 */
1161 devpriv->daccon &= ~PCI230P2_DAC_INT_FIFO_MASK;
1162 devpriv->daccon |= PCI230P2_DAC_INT_FIFO_EMPTY;
1163 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
1164 }
1165 /* Check if FIFO underrun occurred while writing to FIFO. */
1166 dacstat = inw(devpriv->daqio + PCI230_DACCON);
1167 if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
1168 dev_err(dev->class_dev, "AO FIFO underrun\n");
1169 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1170 }
1171 }
1172 async->events |= events;
1173 return !(async->events & COMEDI_CB_CANCEL_MASK);
1174 }
1175
pci230_ao_inttrig_scan_begin(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1176 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1177 struct comedi_subdevice *s,
1178 unsigned int trig_num)
1179 {
1180 struct pci230_private *devpriv = dev->private;
1181 unsigned long irqflags;
1182
1183 if (trig_num)
1184 return -EINVAL;
1185
1186 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1187 if (!devpriv->ao_cmd_started) {
1188 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1189 return 1;
1190 }
1191 /* Perform scan. */
1192 if (devpriv->hwver < 2) {
1193 /* Not using DAC FIFO. */
1194 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1195 pci230_handle_ao_nofifo(dev, s);
1196 comedi_handle_events(dev, s);
1197 } else {
1198 /* Using DAC FIFO. */
1199 /* Read DACSWTRIG register to trigger conversion. */
1200 inw(devpriv->daqio + PCI230P2_DACSWTRIG);
1201 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1202 }
1203 /* Delay. Should driver be responsible for this? */
1204 /* XXX TODO: See if DAC busy bit can be used. */
1205 udelay(8);
1206 return 1;
1207 }
1208
pci230_ao_start(struct comedi_device * dev,struct comedi_subdevice * s)1209 static void pci230_ao_start(struct comedi_device *dev,
1210 struct comedi_subdevice *s)
1211 {
1212 struct pci230_private *devpriv = dev->private;
1213 struct comedi_async *async = s->async;
1214 struct comedi_cmd *cmd = &async->cmd;
1215 unsigned long irqflags;
1216
1217 devpriv->ao_cmd_started = true;
1218
1219 if (devpriv->hwver >= 2) {
1220 /* Using DAC FIFO. */
1221 unsigned short scantrig;
1222 bool run;
1223
1224 /* Preload FIFO data. */
1225 run = pci230_handle_ao_fifo(dev, s);
1226 comedi_handle_events(dev, s);
1227 if (!run) {
1228 /* Stopped. */
1229 return;
1230 }
1231 /* Set scan trigger source. */
1232 switch (cmd->scan_begin_src) {
1233 case TRIG_TIMER:
1234 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1235 break;
1236 case TRIG_EXT:
1237 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1238 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1239 /* +ve edge */
1240 scantrig = PCI230P2_DAC_TRIG_EXTP;
1241 } else {
1242 /* -ve edge */
1243 scantrig = PCI230P2_DAC_TRIG_EXTN;
1244 }
1245 break;
1246 case TRIG_INT:
1247 scantrig = PCI230P2_DAC_TRIG_SW;
1248 break;
1249 default:
1250 /* Shouldn't get here. */
1251 scantrig = PCI230P2_DAC_TRIG_NONE;
1252 break;
1253 }
1254 devpriv->daccon =
1255 (devpriv->daccon & ~PCI230P2_DAC_TRIG_MASK) | scantrig;
1256 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
1257 }
1258 switch (cmd->scan_begin_src) {
1259 case TRIG_TIMER:
1260 if (devpriv->hwver < 2) {
1261 /* Not using DAC FIFO. */
1262 /* Enable CT1 timer interrupt. */
1263 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1264 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1265 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1266 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1267 irqflags);
1268 }
1269 /* Set CT1 gate high to start counting. */
1270 outb(pci230_gat_config(1, GAT_VCC),
1271 dev->iobase + PCI230_ZGAT_SCE);
1272 break;
1273 case TRIG_INT:
1274 async->inttrig = pci230_ao_inttrig_scan_begin;
1275 break;
1276 }
1277 if (devpriv->hwver >= 2) {
1278 /* Using DAC FIFO. Enable DAC FIFO interrupt. */
1279 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1280 devpriv->ier |= PCI230P2_INT_DAC;
1281 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1282 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1283 }
1284 }
1285
pci230_ao_inttrig_start(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1286 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1287 struct comedi_subdevice *s,
1288 unsigned int trig_num)
1289 {
1290 struct comedi_cmd *cmd = &s->async->cmd;
1291
1292 if (trig_num != cmd->start_src)
1293 return -EINVAL;
1294
1295 s->async->inttrig = NULL;
1296 pci230_ao_start(dev, s);
1297
1298 return 1;
1299 }
1300
pci230_ao_cmd(struct comedi_device * dev,struct comedi_subdevice * s)1301 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1302 {
1303 struct pci230_private *devpriv = dev->private;
1304 unsigned short daccon;
1305 unsigned int range;
1306
1307 /* Get the command. */
1308 struct comedi_cmd *cmd = &s->async->cmd;
1309
1310 if (cmd->scan_begin_src == TRIG_TIMER) {
1311 /* Claim Z2-CT1. */
1312 if (!pci230_claim_shared(dev, RES_Z2CT1, OWNER_AOCMD))
1313 return -EBUSY;
1314 }
1315
1316 /*
1317 * Set range - see analogue output range table; 0 => unipolar 10V,
1318 * 1 => bipolar +/-10V range scale
1319 */
1320 range = CR_RANGE(cmd->chanlist[0]);
1321 devpriv->ao_bipolar = comedi_range_is_bipolar(s, range);
1322 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1323 /* Use DAC FIFO for hardware version 2 onwards. */
1324 if (devpriv->hwver >= 2) {
1325 unsigned short dacen;
1326 unsigned int i;
1327
1328 dacen = 0;
1329 for (i = 0; i < cmd->chanlist_len; i++)
1330 dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1331
1332 /* Set channel scan list. */
1333 outw(dacen, devpriv->daqio + PCI230P2_DACEN);
1334 /*
1335 * Enable DAC FIFO.
1336 * Set DAC scan source to 'none'.
1337 * Set DAC FIFO interrupt trigger level to 'not half full'.
1338 * Reset DAC FIFO and clear underrun.
1339 *
1340 * N.B. DAC FIFO interrupts are currently disabled.
1341 */
1342 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET |
1343 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR |
1344 PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1345 }
1346
1347 /* Set DACCON. */
1348 outw(daccon, devpriv->daqio + PCI230_DACCON);
1349 /* Preserve most of DACCON apart from write-only, transient bits. */
1350 devpriv->daccon = daccon & ~(PCI230P2_DAC_FIFO_RESET |
1351 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1352
1353 if (cmd->scan_begin_src == TRIG_TIMER) {
1354 /*
1355 * Set the counter timer 1 to the specified scan frequency.
1356 * cmd->scan_begin_arg is sampling period in ns.
1357 * Gate it off for now.
1358 */
1359 outb(pci230_gat_config(1, GAT_GND),
1360 dev->iobase + PCI230_ZGAT_SCE);
1361 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1362 cmd->scan_begin_arg,
1363 cmd->flags);
1364 }
1365
1366 /* N.B. cmd->start_src == TRIG_INT */
1367 s->async->inttrig = pci230_ao_inttrig_start;
1368
1369 return 0;
1370 }
1371
pci230_ao_cancel(struct comedi_device * dev,struct comedi_subdevice * s)1372 static int pci230_ao_cancel(struct comedi_device *dev,
1373 struct comedi_subdevice *s)
1374 {
1375 pci230_ao_stop(dev, s);
1376 return 0;
1377 }
1378
pci230_ai_check_scan_period(struct comedi_cmd * cmd)1379 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1380 {
1381 unsigned int min_scan_period, chanlist_len;
1382 int err = 0;
1383
1384 chanlist_len = cmd->chanlist_len;
1385 if (cmd->chanlist_len == 0)
1386 chanlist_len = 1;
1387
1388 min_scan_period = chanlist_len * cmd->convert_arg;
1389 if (min_scan_period < chanlist_len ||
1390 min_scan_period < cmd->convert_arg) {
1391 /* Arithmetic overflow. */
1392 min_scan_period = UINT_MAX;
1393 err++;
1394 }
1395 if (cmd->scan_begin_arg < min_scan_period) {
1396 cmd->scan_begin_arg = min_scan_period;
1397 err++;
1398 }
1399
1400 return !err;
1401 }
1402
pci230_ai_check_chanlist(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)1403 static int pci230_ai_check_chanlist(struct comedi_device *dev,
1404 struct comedi_subdevice *s,
1405 struct comedi_cmd *cmd)
1406 {
1407 struct pci230_private *devpriv = dev->private;
1408 unsigned int max_diff_chan = (s->n_chan / 2) - 1;
1409 unsigned int prev_chan = 0;
1410 unsigned int prev_range = 0;
1411 unsigned int prev_aref = 0;
1412 bool prev_bipolar = false;
1413 unsigned int subseq_len = 0;
1414 int i;
1415
1416 for (i = 0; i < cmd->chanlist_len; i++) {
1417 unsigned int chanspec = cmd->chanlist[i];
1418 unsigned int chan = CR_CHAN(chanspec);
1419 unsigned int range = CR_RANGE(chanspec);
1420 unsigned int aref = CR_AREF(chanspec);
1421 bool bipolar = comedi_range_is_bipolar(s, range);
1422
1423 if (aref == AREF_DIFF && chan >= max_diff_chan) {
1424 dev_dbg(dev->class_dev,
1425 "%s: differential channel number out of range 0 to %u\n",
1426 __func__, max_diff_chan);
1427 return -EINVAL;
1428 }
1429
1430 if (i > 0) {
1431 /*
1432 * Channel numbers must strictly increase or
1433 * subsequence must repeat exactly.
1434 */
1435 if (chan <= prev_chan && subseq_len == 0)
1436 subseq_len = i;
1437
1438 if (subseq_len > 0 &&
1439 cmd->chanlist[i % subseq_len] != chanspec) {
1440 dev_dbg(dev->class_dev,
1441 "%s: channel numbers must increase or sequence must repeat exactly\n",
1442 __func__);
1443 return -EINVAL;
1444 }
1445
1446 if (aref != prev_aref) {
1447 dev_dbg(dev->class_dev,
1448 "%s: channel sequence analogue references must be all the same (single-ended or differential)\n",
1449 __func__);
1450 return -EINVAL;
1451 }
1452
1453 if (bipolar != prev_bipolar) {
1454 dev_dbg(dev->class_dev,
1455 "%s: channel sequence ranges must be all bipolar or all unipolar\n",
1456 __func__);
1457 return -EINVAL;
1458 }
1459
1460 if (aref != AREF_DIFF && range != prev_range &&
1461 ((chan ^ prev_chan) & ~1) == 0) {
1462 dev_dbg(dev->class_dev,
1463 "%s: single-ended channel pairs must have the same range\n",
1464 __func__);
1465 return -EINVAL;
1466 }
1467 }
1468 prev_chan = chan;
1469 prev_range = range;
1470 prev_aref = aref;
1471 prev_bipolar = bipolar;
1472 }
1473
1474 if (subseq_len == 0)
1475 subseq_len = cmd->chanlist_len;
1476
1477 if (cmd->chanlist_len % subseq_len) {
1478 dev_dbg(dev->class_dev,
1479 "%s: sequence must repeat exactly\n", __func__);
1480 return -EINVAL;
1481 }
1482
1483 /*
1484 * Buggy PCI230+ or PCI260+ requires channel 0 to be (first) in the
1485 * sequence if the sequence contains more than one channel. Hardware
1486 * versions 1 and 2 have the bug. There is no hardware version 3.
1487 *
1488 * Actually, there are two firmwares that report themselves as
1489 * hardware version 1 (the boards have different ADC chips with
1490 * slightly different timing requirements, which was supposed to
1491 * be invisible to software). The first one doesn't seem to have
1492 * the bug, but the second one does, and we can't tell them apart!
1493 */
1494 if (devpriv->hwver > 0 && devpriv->hwver < 4) {
1495 if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0])) {
1496 dev_info(dev->class_dev,
1497 "amplc_pci230: ai_cmdtest: Buggy PCI230+/260+ h/w version %u requires first channel of multi-channel sequence to be 0 (corrected in h/w version 4)\n",
1498 devpriv->hwver);
1499 return -EINVAL;
1500 }
1501 }
1502
1503 return 0;
1504 }
1505
pci230_ai_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)1506 static int pci230_ai_cmdtest(struct comedi_device *dev,
1507 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1508 {
1509 const struct pci230_board *board = dev->board_ptr;
1510 struct pci230_private *devpriv = dev->private;
1511 int err = 0;
1512 unsigned int tmp;
1513
1514 /* Step 1 : check if triggers are trivially valid */
1515
1516 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1517
1518 tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1519 if (board->have_dio || board->min_hwver > 0) {
1520 /*
1521 * Unfortunately, we cannot trigger a scan off an external
1522 * source on the PCI260 board, since it uses the PPIC0 (DIO)
1523 * input, which isn't present on the PCI260. For PCI260+
1524 * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead.
1525 */
1526 tmp |= TRIG_EXT;
1527 }
1528 err |= comedi_check_trigger_src(&cmd->scan_begin_src, tmp);
1529 err |= comedi_check_trigger_src(&cmd->convert_src,
1530 TRIG_TIMER | TRIG_INT | TRIG_EXT);
1531 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1532 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1533
1534 if (err)
1535 return 1;
1536
1537 /* Step 2a : make sure trigger sources are unique */
1538
1539 err |= comedi_check_trigger_is_unique(cmd->start_src);
1540 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
1541 err |= comedi_check_trigger_is_unique(cmd->convert_src);
1542 err |= comedi_check_trigger_is_unique(cmd->stop_src);
1543
1544 /* Step 2b : and mutually compatible */
1545
1546 /*
1547 * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1548 * set up to generate a fixed number of timed conversion pulses.
1549 */
1550 if (cmd->scan_begin_src != TRIG_FOLLOW &&
1551 cmd->convert_src != TRIG_TIMER)
1552 err |= -EINVAL;
1553
1554 if (err)
1555 return 2;
1556
1557 /* Step 3: check if arguments are trivially valid */
1558
1559 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
1560
1561 #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */
1562 #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */
1563 #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */
1564 /*
1565 * Comedi limit due to unsigned int cmd. Driver limit =
1566 * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s
1567 */
1568 #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */
1569
1570 if (cmd->convert_src == TRIG_TIMER) {
1571 unsigned int max_speed_ai;
1572
1573 if (devpriv->hwver == 0) {
1574 /*
1575 * PCI230 or PCI260. Max speed depends whether
1576 * single-ended or pseudo-differential.
1577 */
1578 if (cmd->chanlist && cmd->chanlist_len > 0) {
1579 /* Peek analogue reference of first channel. */
1580 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1581 max_speed_ai = MAX_SPEED_AI_DIFF;
1582 else
1583 max_speed_ai = MAX_SPEED_AI_SE;
1584
1585 } else {
1586 /* No channel list. Assume single-ended. */
1587 max_speed_ai = MAX_SPEED_AI_SE;
1588 }
1589 } else {
1590 /* PCI230+ or PCI260+. */
1591 max_speed_ai = MAX_SPEED_AI_PLUS;
1592 }
1593
1594 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
1595 max_speed_ai);
1596 err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
1597 MIN_SPEED_AI);
1598 } else if (cmd->convert_src == TRIG_EXT) {
1599 /*
1600 * external trigger
1601 *
1602 * convert_arg == (CR_EDGE | 0)
1603 * => trigger on +ve edge.
1604 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1605 * => trigger on -ve edge.
1606 */
1607 if (cmd->convert_arg & CR_FLAGS_MASK) {
1608 /* Trigger number must be 0. */
1609 if (cmd->convert_arg & ~CR_FLAGS_MASK) {
1610 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1611 ~CR_FLAGS_MASK);
1612 err |= -EINVAL;
1613 }
1614 /*
1615 * The only flags allowed are CR_INVERT and CR_EDGE.
1616 * CR_EDGE is required.
1617 */
1618 if ((cmd->convert_arg & CR_FLAGS_MASK & ~CR_INVERT) !=
1619 CR_EDGE) {
1620 /* Set CR_EDGE, preserve CR_INVERT. */
1621 cmd->convert_arg =
1622 COMBINE(cmd->start_arg, CR_EDGE | 0,
1623 CR_FLAGS_MASK & ~CR_INVERT);
1624 err |= -EINVAL;
1625 }
1626 } else {
1627 /*
1628 * Backwards compatibility with previous versions:
1629 * convert_arg == 0 => trigger on -ve edge.
1630 * convert_arg == 1 => trigger on +ve edge.
1631 */
1632 err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
1633 1);
1634 }
1635 } else {
1636 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
1637 }
1638
1639 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
1640 cmd->chanlist_len);
1641
1642 if (cmd->stop_src == TRIG_COUNT)
1643 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
1644 else /* TRIG_NONE */
1645 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
1646
1647 if (cmd->scan_begin_src == TRIG_EXT) {
1648 /*
1649 * external "trigger" to begin each scan:
1650 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1651 * of CT2 (sample convert trigger is CT2)
1652 */
1653 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
1654 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1655 ~CR_FLAGS_MASK);
1656 err |= -EINVAL;
1657 }
1658 /* The only flag allowed is CR_EDGE, which is ignored. */
1659 if (cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) {
1660 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1661 CR_FLAGS_MASK & ~CR_EDGE);
1662 err |= -EINVAL;
1663 }
1664 } else if (cmd->scan_begin_src == TRIG_TIMER) {
1665 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1666 if (!pci230_ai_check_scan_period(cmd))
1667 err |= -EINVAL;
1668
1669 } else {
1670 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1671 }
1672
1673 if (err)
1674 return 3;
1675
1676 /* Step 4: fix up any arguments */
1677
1678 if (cmd->convert_src == TRIG_TIMER) {
1679 tmp = cmd->convert_arg;
1680 pci230_ns_to_single_timer(&cmd->convert_arg, cmd->flags);
1681 if (tmp != cmd->convert_arg)
1682 err++;
1683 }
1684
1685 if (cmd->scan_begin_src == TRIG_TIMER) {
1686 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1687 tmp = cmd->scan_begin_arg;
1688 pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags);
1689 if (!pci230_ai_check_scan_period(cmd)) {
1690 /* Was below minimum required. Round up. */
1691 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1692 CMDF_ROUND_UP);
1693 pci230_ai_check_scan_period(cmd);
1694 }
1695 if (tmp != cmd->scan_begin_arg)
1696 err++;
1697 }
1698
1699 if (err)
1700 return 4;
1701
1702 /* Step 5: check channel list if it exists */
1703 if (cmd->chanlist && cmd->chanlist_len > 0)
1704 err |= pci230_ai_check_chanlist(dev, s, cmd);
1705
1706 if (err)
1707 return 5;
1708
1709 return 0;
1710 }
1711
pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,struct comedi_subdevice * s)1712 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
1713 struct comedi_subdevice *s)
1714 {
1715 struct pci230_private *devpriv = dev->private;
1716 struct comedi_cmd *cmd = &s->async->cmd;
1717 unsigned int wake;
1718 unsigned short triglev;
1719 unsigned short adccon;
1720
1721 if (cmd->flags & CMDF_WAKE_EOS)
1722 wake = cmd->scan_end_arg - s->async->cur_chan;
1723 else
1724 wake = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL);
1725
1726 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
1727 triglev = PCI230_ADC_INT_FIFO_HALF;
1728 } else if (wake > 1 && devpriv->hwver > 0) {
1729 /* PCI230+/260+ programmable FIFO interrupt level. */
1730 if (devpriv->adcfifothresh != wake) {
1731 devpriv->adcfifothresh = wake;
1732 outw(wake, devpriv->daqio + PCI230P_ADCFFTH);
1733 }
1734 triglev = PCI230P_ADC_INT_FIFO_THRESH;
1735 } else {
1736 triglev = PCI230_ADC_INT_FIFO_NEMPTY;
1737 }
1738 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
1739 if (adccon != devpriv->adccon) {
1740 devpriv->adccon = adccon;
1741 outw(adccon, devpriv->daqio + PCI230_ADCCON);
1742 }
1743 }
1744
pci230_ai_inttrig_convert(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1745 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
1746 struct comedi_subdevice *s,
1747 unsigned int trig_num)
1748 {
1749 struct pci230_private *devpriv = dev->private;
1750 unsigned long irqflags;
1751 unsigned int delayus;
1752
1753 if (trig_num)
1754 return -EINVAL;
1755
1756 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1757 if (!devpriv->ai_cmd_started) {
1758 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1759 return 1;
1760 }
1761 /*
1762 * Trigger conversion by toggling Z2-CT2 output.
1763 * Finish with output high.
1764 */
1765 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE0);
1766 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1);
1767 /*
1768 * Delay. Should driver be responsible for this? An
1769 * alternative would be to wait until conversion is complete,
1770 * but we can't tell when it's complete because the ADC busy
1771 * bit has a different meaning when FIFO enabled (and when
1772 * FIFO not enabled, it only works for software triggers).
1773 */
1774 if ((devpriv->adccon & PCI230_ADC_IM_MASK) == PCI230_ADC_IM_DIF &&
1775 devpriv->hwver == 0) {
1776 /* PCI230/260 in differential mode */
1777 delayus = 8;
1778 } else {
1779 /* single-ended or PCI230+/260+ */
1780 delayus = 4;
1781 }
1782 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1783 udelay(delayus);
1784 return 1;
1785 }
1786
pci230_ai_inttrig_scan_begin(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1787 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
1788 struct comedi_subdevice *s,
1789 unsigned int trig_num)
1790 {
1791 struct pci230_private *devpriv = dev->private;
1792 unsigned long irqflags;
1793 unsigned char zgat;
1794
1795 if (trig_num)
1796 return -EINVAL;
1797
1798 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1799 if (devpriv->ai_cmd_started) {
1800 /* Trigger scan by waggling CT0 gate source. */
1801 zgat = pci230_gat_config(0, GAT_GND);
1802 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1803 zgat = pci230_gat_config(0, GAT_VCC);
1804 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1805 }
1806 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1807
1808 return 1;
1809 }
1810
pci230_ai_stop(struct comedi_device * dev,struct comedi_subdevice * s)1811 static void pci230_ai_stop(struct comedi_device *dev,
1812 struct comedi_subdevice *s)
1813 {
1814 struct pci230_private *devpriv = dev->private;
1815 unsigned long irqflags;
1816 struct comedi_cmd *cmd;
1817 bool started;
1818
1819 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1820 started = devpriv->ai_cmd_started;
1821 devpriv->ai_cmd_started = false;
1822 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1823 if (!started)
1824 return;
1825 cmd = &s->async->cmd;
1826 if (cmd->convert_src == TRIG_TIMER) {
1827 /* Stop conversion rate generator. */
1828 pci230_cancel_ct(dev, 2);
1829 }
1830 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1831 /* Stop scan period monostable. */
1832 pci230_cancel_ct(dev, 0);
1833 }
1834 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1835 /*
1836 * Disable ADC interrupt and wait for interrupt routine to finish
1837 * running unless we are called from the interrupt routine.
1838 */
1839 devpriv->ier &= ~PCI230_INT_ADC;
1840 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
1841 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1842 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1843 }
1844 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1845 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1846 /*
1847 * Reset FIFO, disable FIFO and set start conversion source to none.
1848 * Keep se/diff and bip/uni settings.
1849 */
1850 devpriv->adccon =
1851 (devpriv->adccon & (PCI230_ADC_IR_MASK | PCI230_ADC_IM_MASK)) |
1852 PCI230_ADC_TRIG_NONE;
1853 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
1854 devpriv->daqio + PCI230_ADCCON);
1855 /* Release resources. */
1856 pci230_release_all_resources(dev, OWNER_AICMD);
1857 }
1858
pci230_ai_start(struct comedi_device * dev,struct comedi_subdevice * s)1859 static void pci230_ai_start(struct comedi_device *dev,
1860 struct comedi_subdevice *s)
1861 {
1862 struct pci230_private *devpriv = dev->private;
1863 unsigned long irqflags;
1864 unsigned short conv;
1865 struct comedi_async *async = s->async;
1866 struct comedi_cmd *cmd = &async->cmd;
1867
1868 devpriv->ai_cmd_started = true;
1869
1870 /* Enable ADC FIFO trigger level interrupt. */
1871 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1872 devpriv->ier |= PCI230_INT_ADC;
1873 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1874 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1875
1876 /*
1877 * Update conversion trigger source which is currently set
1878 * to CT2 output, which is currently stuck high.
1879 */
1880 switch (cmd->convert_src) {
1881 default:
1882 conv = PCI230_ADC_TRIG_NONE;
1883 break;
1884 case TRIG_TIMER:
1885 /* Using CT2 output. */
1886 conv = PCI230_ADC_TRIG_Z2CT2;
1887 break;
1888 case TRIG_EXT:
1889 if (cmd->convert_arg & CR_EDGE) {
1890 if ((cmd->convert_arg & CR_INVERT) == 0) {
1891 /* Trigger on +ve edge. */
1892 conv = PCI230_ADC_TRIG_EXTP;
1893 } else {
1894 /* Trigger on -ve edge. */
1895 conv = PCI230_ADC_TRIG_EXTN;
1896 }
1897 } else {
1898 /* Backwards compatibility. */
1899 if (cmd->convert_arg) {
1900 /* Trigger on +ve edge. */
1901 conv = PCI230_ADC_TRIG_EXTP;
1902 } else {
1903 /* Trigger on -ve edge. */
1904 conv = PCI230_ADC_TRIG_EXTN;
1905 }
1906 }
1907 break;
1908 case TRIG_INT:
1909 /*
1910 * Use CT2 output for software trigger due to problems
1911 * in differential mode on PCI230/260.
1912 */
1913 conv = PCI230_ADC_TRIG_Z2CT2;
1914 break;
1915 }
1916 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) | conv;
1917 outw(devpriv->adccon, devpriv->daqio + PCI230_ADCCON);
1918 if (cmd->convert_src == TRIG_INT)
1919 async->inttrig = pci230_ai_inttrig_convert;
1920
1921 /*
1922 * Update FIFO interrupt trigger level, which is currently
1923 * set to "full".
1924 */
1925 pci230_ai_update_fifo_trigger_level(dev, s);
1926 if (cmd->convert_src == TRIG_TIMER) {
1927 /* Update timer gates. */
1928 unsigned char zgat;
1929
1930 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1931 /*
1932 * Conversion timer CT2 needs to be gated by
1933 * inverted output of monostable CT2.
1934 */
1935 zgat = pci230_gat_config(2, GAT_NOUTNM2);
1936 } else {
1937 /*
1938 * Conversion timer CT2 needs to be gated on
1939 * continuously.
1940 */
1941 zgat = pci230_gat_config(2, GAT_VCC);
1942 }
1943 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1944 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1945 /* Set monostable CT0 trigger source. */
1946 switch (cmd->scan_begin_src) {
1947 default:
1948 zgat = pci230_gat_config(0, GAT_VCC);
1949 break;
1950 case TRIG_EXT:
1951 /*
1952 * For CT0 on PCI230, the external trigger
1953 * (gate) signal comes from PPC0, which is
1954 * channel 16 of the DIO subdevice. The
1955 * application needs to configure this as an
1956 * input in order to use it as an external scan
1957 * trigger.
1958 */
1959 zgat = pci230_gat_config(0, GAT_EXT);
1960 break;
1961 case TRIG_TIMER:
1962 /*
1963 * Monostable CT0 triggered by rising edge on
1964 * inverted output of CT1 (falling edge on CT1).
1965 */
1966 zgat = pci230_gat_config(0, GAT_NOUTNM2);
1967 break;
1968 case TRIG_INT:
1969 /*
1970 * Monostable CT0 is triggered by inttrig
1971 * function waggling the CT0 gate source.
1972 */
1973 zgat = pci230_gat_config(0, GAT_VCC);
1974 break;
1975 }
1976 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1977 switch (cmd->scan_begin_src) {
1978 case TRIG_TIMER:
1979 /*
1980 * Scan period timer CT1 needs to be
1981 * gated on to start counting.
1982 */
1983 zgat = pci230_gat_config(1, GAT_VCC);
1984 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1985 break;
1986 case TRIG_INT:
1987 async->inttrig = pci230_ai_inttrig_scan_begin;
1988 break;
1989 }
1990 }
1991 } else if (cmd->convert_src != TRIG_INT) {
1992 /* No longer need Z2-CT2. */
1993 pci230_release_shared(dev, RES_Z2CT2, OWNER_AICMD);
1994 }
1995 }
1996
pci230_ai_inttrig_start(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1997 static int pci230_ai_inttrig_start(struct comedi_device *dev,
1998 struct comedi_subdevice *s,
1999 unsigned int trig_num)
2000 {
2001 struct comedi_cmd *cmd = &s->async->cmd;
2002
2003 if (trig_num != cmd->start_arg)
2004 return -EINVAL;
2005
2006 s->async->inttrig = NULL;
2007 pci230_ai_start(dev, s);
2008
2009 return 1;
2010 }
2011
pci230_handle_ai(struct comedi_device * dev,struct comedi_subdevice * s)2012 static void pci230_handle_ai(struct comedi_device *dev,
2013 struct comedi_subdevice *s)
2014 {
2015 struct pci230_private *devpriv = dev->private;
2016 struct comedi_async *async = s->async;
2017 struct comedi_cmd *cmd = &async->cmd;
2018 unsigned int status_fifo;
2019 unsigned int i;
2020 unsigned int nsamples;
2021 unsigned int fifoamount;
2022 unsigned short val;
2023
2024 /* Determine number of samples to read. */
2025 nsamples = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL);
2026 if (nsamples == 0)
2027 return;
2028
2029 fifoamount = 0;
2030 for (i = 0; i < nsamples; i++) {
2031 if (fifoamount == 0) {
2032 /* Read FIFO state. */
2033 status_fifo = inw(devpriv->daqio + PCI230_ADCCON);
2034 if (status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) {
2035 /*
2036 * Report error otherwise FIFO overruns will go
2037 * unnoticed by the caller.
2038 */
2039 dev_err(dev->class_dev, "AI FIFO overrun\n");
2040 async->events |= COMEDI_CB_ERROR;
2041 break;
2042 } else if (status_fifo & PCI230_ADC_FIFO_EMPTY) {
2043 /* FIFO empty. */
2044 break;
2045 } else if (status_fifo & PCI230_ADC_FIFO_HALF) {
2046 /* FIFO half full. */
2047 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2048 } else if (devpriv->hwver > 0) {
2049 /* Read PCI230+/260+ ADC FIFO level. */
2050 fifoamount = inw(devpriv->daqio +
2051 PCI230P_ADCFFLEV);
2052 if (fifoamount == 0)
2053 break; /* Shouldn't happen. */
2054 } else {
2055 /* FIFO not empty. */
2056 fifoamount = 1;
2057 }
2058 }
2059
2060 val = pci230_ai_read(dev);
2061 if (!comedi_buf_write_samples(s, &val, 1))
2062 break;
2063
2064 fifoamount--;
2065
2066 if (cmd->stop_src == TRIG_COUNT &&
2067 async->scans_done >= cmd->stop_arg) {
2068 async->events |= COMEDI_CB_EOA;
2069 break;
2070 }
2071 }
2072
2073 /* update FIFO interrupt trigger level if still running */
2074 if (!(async->events & COMEDI_CB_CANCEL_MASK))
2075 pci230_ai_update_fifo_trigger_level(dev, s);
2076 }
2077
pci230_ai_cmd(struct comedi_device * dev,struct comedi_subdevice * s)2078 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2079 {
2080 struct pci230_private *devpriv = dev->private;
2081 unsigned int i, chan, range, diff;
2082 unsigned int res_mask;
2083 unsigned short adccon, adcen;
2084 unsigned char zgat;
2085
2086 /* Get the command. */
2087 struct comedi_async *async = s->async;
2088 struct comedi_cmd *cmd = &async->cmd;
2089
2090 /*
2091 * Determine which shared resources are needed.
2092 */
2093 res_mask = 0;
2094 /*
2095 * Need Z2-CT2 to supply a conversion trigger source at a high
2096 * logic level, even if not doing timed conversions.
2097 */
2098 res_mask |= RES_Z2CT2;
2099 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2100 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2101 res_mask |= RES_Z2CT0;
2102 if (cmd->scan_begin_src == TRIG_TIMER) {
2103 /* Using Z2-CT1 for scan frequency */
2104 res_mask |= RES_Z2CT1;
2105 }
2106 }
2107 /* Claim resources. */
2108 if (!pci230_claim_shared(dev, res_mask, OWNER_AICMD))
2109 return -EBUSY;
2110
2111 /*
2112 * Steps:
2113 * - Set channel scan list.
2114 * - Set channel gains.
2115 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2116 * start conversion source to point to something at a high logic
2117 * level (we use the output of counter/timer 2 for this purpose.
2118 * - PAUSE to allow things to settle down.
2119 * - Reset the FIFO again because it needs resetting twice and there
2120 * may have been a false conversion trigger on some versions of
2121 * PCI230/260 due to the start conversion source being set to a
2122 * high logic level.
2123 * - Enable ADC FIFO level interrupt.
2124 * - Set actual conversion trigger source and FIFO interrupt trigger
2125 * level.
2126 * - If convert_src is TRIG_TIMER, set up the timers.
2127 */
2128
2129 adccon = PCI230_ADC_FIFO_EN;
2130 adcen = 0;
2131
2132 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2133 /* Differential - all channels must be differential. */
2134 diff = 1;
2135 adccon |= PCI230_ADC_IM_DIF;
2136 } else {
2137 /* Single ended - all channels must be single-ended. */
2138 diff = 0;
2139 adccon |= PCI230_ADC_IM_SE;
2140 }
2141
2142 range = CR_RANGE(cmd->chanlist[0]);
2143 devpriv->ai_bipolar = comedi_range_is_bipolar(s, range);
2144 if (devpriv->ai_bipolar)
2145 adccon |= PCI230_ADC_IR_BIP;
2146 else
2147 adccon |= PCI230_ADC_IR_UNI;
2148
2149 for (i = 0; i < cmd->chanlist_len; i++) {
2150 unsigned int gainshift;
2151
2152 chan = CR_CHAN(cmd->chanlist[i]);
2153 range = CR_RANGE(cmd->chanlist[i]);
2154 if (diff) {
2155 gainshift = 2 * chan;
2156 if (devpriv->hwver == 0) {
2157 /*
2158 * Original PCI230/260 expects both inputs of
2159 * the differential channel to be enabled.
2160 */
2161 adcen |= 3 << gainshift;
2162 } else {
2163 /*
2164 * PCI230+/260+ expects only one input of the
2165 * differential channel to be enabled.
2166 */
2167 adcen |= 1 << gainshift;
2168 }
2169 } else {
2170 gainshift = chan & ~1;
2171 adcen |= 1 << chan;
2172 }
2173 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) |
2174 (pci230_ai_gain[range] << gainshift);
2175 }
2176
2177 /* Set channel scan list. */
2178 outw(adcen, devpriv->daqio + PCI230_ADCEN);
2179
2180 /* Set channel gains. */
2181 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
2182
2183 /*
2184 * Set counter/timer 2 output high for use as the initial start
2185 * conversion source.
2186 */
2187 comedi_8254_set_mode(dev->pacer, 2, I8254_MODE1);
2188
2189 /*
2190 * Temporarily use CT2 output as conversion trigger source and
2191 * temporarily set FIFO interrupt trigger level to 'full'.
2192 */
2193 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2194
2195 /*
2196 * Enable and reset FIFO, specify FIFO trigger level full, specify
2197 * uni/bip, se/diff, and temporarily set the start conversion source
2198 * to CT2 output. Note that CT2 output is currently high, and this
2199 * will produce a false conversion trigger on some versions of the
2200 * PCI230/260, but that will be dealt with later.
2201 */
2202 devpriv->adccon = adccon;
2203 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
2204
2205 /*
2206 * Delay -
2207 * Failure to include this will result in the first few channels'-worth
2208 * of data being corrupt, normally manifesting itself by large negative
2209 * voltages. It seems the board needs time to settle between the first
2210 * FIFO reset (above) and the second FIFO reset (below). Setting the
2211 * channel gains and scan list _before_ the first FIFO reset also
2212 * helps, though only slightly.
2213 */
2214 usleep_range(25, 100);
2215
2216 /* Reset FIFO again. */
2217 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
2218
2219 if (cmd->convert_src == TRIG_TIMER) {
2220 /*
2221 * Set up CT2 as conversion timer, but gate it off for now.
2222 * Note, counter/timer output 2 can be monitored on the
2223 * connector: PCI230 pin 21, PCI260 pin 18.
2224 */
2225 zgat = pci230_gat_config(2, GAT_GND);
2226 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
2227 /* Set counter/timer 2 to the specified conversion period. */
2228 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2229 cmd->flags);
2230 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2231 /*
2232 * Set up monostable on CT0 output for scan timing. A
2233 * rising edge on the trigger (gate) input of CT0 will
2234 * trigger the monostable, causing its output to go low
2235 * for the configured period. The period depends on
2236 * the conversion period and the number of conversions
2237 * in the scan.
2238 *
2239 * Set the trigger high before setting up the
2240 * monostable to stop it triggering. The trigger
2241 * source will be changed later.
2242 */
2243 zgat = pci230_gat_config(0, GAT_VCC);
2244 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
2245 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2246 ((u64)cmd->convert_arg *
2247 cmd->scan_end_arg),
2248 CMDF_ROUND_UP);
2249 if (cmd->scan_begin_src == TRIG_TIMER) {
2250 /*
2251 * Monostable on CT0 will be triggered by
2252 * output of CT1 at configured scan frequency.
2253 *
2254 * Set up CT1 but gate it off for now.
2255 */
2256 zgat = pci230_gat_config(1, GAT_GND);
2257 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
2258 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2259 cmd->scan_begin_arg,
2260 cmd->flags);
2261 }
2262 }
2263 }
2264
2265 if (cmd->start_src == TRIG_INT)
2266 s->async->inttrig = pci230_ai_inttrig_start;
2267 else /* TRIG_NOW */
2268 pci230_ai_start(dev, s);
2269
2270 return 0;
2271 }
2272
pci230_ai_cancel(struct comedi_device * dev,struct comedi_subdevice * s)2273 static int pci230_ai_cancel(struct comedi_device *dev,
2274 struct comedi_subdevice *s)
2275 {
2276 pci230_ai_stop(dev, s);
2277 return 0;
2278 }
2279
2280 /* Interrupt handler */
pci230_interrupt(int irq,void * d)2281 static irqreturn_t pci230_interrupt(int irq, void *d)
2282 {
2283 unsigned char status_int, valid_status_int, temp_ier;
2284 struct comedi_device *dev = d;
2285 struct pci230_private *devpriv = dev->private;
2286 struct comedi_subdevice *s_ao = dev->write_subdev;
2287 struct comedi_subdevice *s_ai = dev->read_subdev;
2288 unsigned long irqflags;
2289
2290 /* Read interrupt status/enable register. */
2291 status_int = inb(dev->iobase + PCI230_INT_STAT);
2292
2293 if (status_int == PCI230_INT_DISABLE)
2294 return IRQ_NONE;
2295
2296 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2297 valid_status_int = devpriv->ier & status_int;
2298 /*
2299 * Disable triggered interrupts.
2300 * (Only those interrupts that need re-enabling, are, later in the
2301 * handler).
2302 */
2303 temp_ier = devpriv->ier & ~status_int;
2304 outb(temp_ier, dev->iobase + PCI230_INT_SCE);
2305 devpriv->intr_running = true;
2306 devpriv->intr_cpuid = THISCPU;
2307 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2308
2309 /*
2310 * Check the source of interrupt and handle it.
2311 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2312 * interrupts. However, at present (Comedi-0.7.60) does not allow
2313 * concurrent execution of commands, instructions or a mixture of the
2314 * two.
2315 */
2316
2317 if (valid_status_int & PCI230_INT_ZCLK_CT1)
2318 pci230_handle_ao_nofifo(dev, s_ao);
2319
2320 if (valid_status_int & PCI230P2_INT_DAC)
2321 pci230_handle_ao_fifo(dev, s_ao);
2322
2323 if (valid_status_int & PCI230_INT_ADC)
2324 pci230_handle_ai(dev, s_ai);
2325
2326 /* Reenable interrupts. */
2327 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2328 if (devpriv->ier != temp_ier)
2329 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
2330 devpriv->intr_running = false;
2331 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2332
2333 if (s_ao)
2334 comedi_handle_events(dev, s_ao);
2335 comedi_handle_events(dev, s_ai);
2336
2337 return IRQ_HANDLED;
2338 }
2339
2340 /* Check if PCI device matches a specific board. */
pci230_match_pci_board(const struct pci230_board * board,struct pci_dev * pci_dev)2341 static bool pci230_match_pci_board(const struct pci230_board *board,
2342 struct pci_dev *pci_dev)
2343 {
2344 /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */
2345 if (board->id != pci_dev->device)
2346 return false;
2347 if (board->min_hwver == 0)
2348 return true;
2349 /* Looking for a '+' model. First check length of registers. */
2350 if (pci_resource_len(pci_dev, 3) < 32)
2351 return false; /* Not a '+' model. */
2352 /*
2353 * TODO: temporarily enable PCI device and read the hardware version
2354 * register. For now, assume it's okay.
2355 */
2356 return true;
2357 }
2358
2359 /* Look for board matching PCI device. */
pci230_find_pci_board(struct pci_dev * pci_dev)2360 static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev)
2361 {
2362 unsigned int i;
2363
2364 for (i = 0; i < ARRAY_SIZE(pci230_boards); i++)
2365 if (pci230_match_pci_board(&pci230_boards[i], pci_dev))
2366 return &pci230_boards[i];
2367 return NULL;
2368 }
2369
pci230_auto_attach(struct comedi_device * dev,unsigned long context_unused)2370 static int pci230_auto_attach(struct comedi_device *dev,
2371 unsigned long context_unused)
2372 {
2373 struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
2374 const struct pci230_board *board;
2375 struct pci230_private *devpriv;
2376 struct comedi_subdevice *s;
2377 int rc;
2378
2379 dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
2380 pci_name(pci_dev));
2381
2382 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
2383 if (!devpriv)
2384 return -ENOMEM;
2385
2386 spin_lock_init(&devpriv->isr_spinlock);
2387 spin_lock_init(&devpriv->res_spinlock);
2388 spin_lock_init(&devpriv->ai_stop_spinlock);
2389 spin_lock_init(&devpriv->ao_stop_spinlock);
2390
2391 board = pci230_find_pci_board(pci_dev);
2392 if (!board) {
2393 dev_err(dev->class_dev,
2394 "amplc_pci230: BUG! cannot determine board type!\n");
2395 return -EINVAL;
2396 }
2397 dev->board_ptr = board;
2398 dev->board_name = board->name;
2399
2400 rc = comedi_pci_enable(dev);
2401 if (rc)
2402 return rc;
2403
2404 /*
2405 * Read base addresses of the PCI230's two I/O regions from PCI
2406 * configuration register.
2407 */
2408 dev->iobase = pci_resource_start(pci_dev, 2);
2409 devpriv->daqio = pci_resource_start(pci_dev, 3);
2410 dev_dbg(dev->class_dev,
2411 "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
2412 dev->board_name, dev->iobase, devpriv->daqio);
2413 /* Read bits of DACCON register - only the output range. */
2414 devpriv->daccon = inw(devpriv->daqio + PCI230_DACCON) &
2415 PCI230_DAC_OR_MASK;
2416 /*
2417 * Read hardware version register and set extended function register
2418 * if they exist.
2419 */
2420 if (pci_resource_len(pci_dev, 3) >= 32) {
2421 unsigned short extfunc = 0;
2422
2423 devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER);
2424 if (devpriv->hwver < board->min_hwver) {
2425 dev_err(dev->class_dev,
2426 "%s - bad hardware version - got %u, need %u\n",
2427 dev->board_name, devpriv->hwver,
2428 board->min_hwver);
2429 return -EIO;
2430 }
2431 if (devpriv->hwver > 0) {
2432 if (!board->have_dio) {
2433 /*
2434 * No DIO ports. Route counters' external gates
2435 * to the EXTTRIG signal (PCI260+ pin 17).
2436 * (Otherwise, they would be routed to DIO
2437 * inputs PC0, PC1 and PC2 which don't exist
2438 * on PCI260[+].)
2439 */
2440 extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
2441 }
2442 if (board->ao_bits && devpriv->hwver >= 2) {
2443 /* Enable DAC FIFO functionality. */
2444 extfunc |= PCI230P2_EXTFUNC_DACFIFO;
2445 }
2446 }
2447 outw(extfunc, devpriv->daqio + PCI230P_EXTFUNC);
2448 if (extfunc & PCI230P2_EXTFUNC_DACFIFO) {
2449 /*
2450 * Temporarily enable DAC FIFO, reset it and disable
2451 * FIFO wraparound.
2452 */
2453 outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN |
2454 PCI230P2_DAC_FIFO_RESET,
2455 devpriv->daqio + PCI230_DACCON);
2456 /* Clear DAC FIFO channel enable register. */
2457 outw(0, devpriv->daqio + PCI230P2_DACEN);
2458 /* Disable DAC FIFO. */
2459 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
2460 }
2461 }
2462 /* Disable board's interrupts. */
2463 outb(0, dev->iobase + PCI230_INT_SCE);
2464 /* Set ADC to a reasonable state. */
2465 devpriv->adcg = 0;
2466 devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE |
2467 PCI230_ADC_IR_BIP;
2468 outw(BIT(0), devpriv->daqio + PCI230_ADCEN);
2469 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
2470 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2471 devpriv->daqio + PCI230_ADCCON);
2472
2473 if (pci_dev->irq) {
2474 rc = request_irq(pci_dev->irq, pci230_interrupt, IRQF_SHARED,
2475 dev->board_name, dev);
2476 if (rc == 0)
2477 dev->irq = pci_dev->irq;
2478 }
2479
2480 dev->pacer = comedi_8254_init(dev->iobase + PCI230_Z2_CT_BASE,
2481 0, I8254_IO8, 0);
2482 if (!dev->pacer)
2483 return -ENOMEM;
2484
2485 rc = comedi_alloc_subdevices(dev, 3);
2486 if (rc)
2487 return rc;
2488
2489 s = &dev->subdevices[0];
2490 /* analog input subdevice */
2491 s->type = COMEDI_SUBD_AI;
2492 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
2493 s->n_chan = 16;
2494 s->maxdata = (1 << board->ai_bits) - 1;
2495 s->range_table = &pci230_ai_range;
2496 s->insn_read = pci230_ai_insn_read;
2497 s->len_chanlist = 256; /* but there are restrictions. */
2498 if (dev->irq) {
2499 dev->read_subdev = s;
2500 s->subdev_flags |= SDF_CMD_READ;
2501 s->do_cmd = pci230_ai_cmd;
2502 s->do_cmdtest = pci230_ai_cmdtest;
2503 s->cancel = pci230_ai_cancel;
2504 }
2505
2506 s = &dev->subdevices[1];
2507 /* analog output subdevice */
2508 if (board->ao_bits) {
2509 s->type = COMEDI_SUBD_AO;
2510 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
2511 s->n_chan = 2;
2512 s->maxdata = (1 << board->ao_bits) - 1;
2513 s->range_table = &pci230_ao_range;
2514 s->insn_write = pci230_ao_insn_write;
2515 s->len_chanlist = 2;
2516 if (dev->irq) {
2517 dev->write_subdev = s;
2518 s->subdev_flags |= SDF_CMD_WRITE;
2519 s->do_cmd = pci230_ao_cmd;
2520 s->do_cmdtest = pci230_ao_cmdtest;
2521 s->cancel = pci230_ao_cancel;
2522 }
2523
2524 rc = comedi_alloc_subdev_readback(s);
2525 if (rc)
2526 return rc;
2527 } else {
2528 s->type = COMEDI_SUBD_UNUSED;
2529 }
2530
2531 s = &dev->subdevices[2];
2532 /* digital i/o subdevice */
2533 if (board->have_dio) {
2534 rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE);
2535 if (rc)
2536 return rc;
2537 } else {
2538 s->type = COMEDI_SUBD_UNUSED;
2539 }
2540
2541 return 0;
2542 }
2543
2544 static struct comedi_driver amplc_pci230_driver = {
2545 .driver_name = "amplc_pci230",
2546 .module = THIS_MODULE,
2547 .auto_attach = pci230_auto_attach,
2548 .detach = comedi_pci_detach,
2549 };
2550
amplc_pci230_pci_probe(struct pci_dev * dev,const struct pci_device_id * id)2551 static int amplc_pci230_pci_probe(struct pci_dev *dev,
2552 const struct pci_device_id *id)
2553 {
2554 return comedi_pci_auto_config(dev, &lc_pci230_driver,
2555 id->driver_data);
2556 }
2557
2558 static const struct pci_device_id amplc_pci230_pci_table[] = {
2559 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
2560 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
2561 { 0 }
2562 };
2563 MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table);
2564
2565 static struct pci_driver amplc_pci230_pci_driver = {
2566 .name = "amplc_pci230",
2567 .id_table = amplc_pci230_pci_table,
2568 .probe = amplc_pci230_pci_probe,
2569 .remove = comedi_pci_auto_unconfig,
2570 };
2571 module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
2572
2573 MODULE_AUTHOR("Comedi https://www.comedi.org");
2574 MODULE_DESCRIPTION("Comedi driver for Amplicon PCI230(+) and PCI260(+)");
2575 MODULE_LICENSE("GPL");
2576