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