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