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