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