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