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