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