2 comedi/drivers/amplc_pci230.c
3 Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
5 Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
7 COMEDI - Linux Control and Measurement Device Interface
8 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
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.
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.
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.
26 Description: Amplicon PCI230, PCI260 Multifunction I/O boards
27 Author: Allan Willcox <allanwillcox@ozemail.com.au>,
28 Steve D Sharples <steve.sharples@nottingham.ac.uk>,
29 Ian Abbott <abbotti@mev.co.uk>
30 Updated: Wed, 22 Oct 2008 12:34:49 +0100
31 Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
32 PCI230+ (pci230+ or amplc_pci230),
33 PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
36 Configuration 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
42 Configuring a "amplc_pci230" will match any supported card and it will
43 choose the best match, picking the "+" models if possible. Configuring
44 a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
45 a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card
46 and it will be treated as a PCI260. Configuring a "pci230+" will match
47 a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card.
60 The AI subdevice has 16 single-ended channels or 8 differential
63 The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and
64 PCI260+ cards have 16-bit resolution.
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.
77 The following input ranges are supported:
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|
95 | |--------------|-----------| | |
96 | | TRIG_TIMER(1)|TRIG_TIMER | | |
97 | | TRIG_EXT(2) | | | |
99 +---------+--------------+-----------+------------+----------+
101 Note 1: If AI command and AO command are used simultaneously, only
102 one may have scan_begin_src == TRIG_TIMER.
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
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:
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)
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.
137 The AO subdevice has 2 channels with 12-bit resolution.
139 The following output ranges are supported:
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|
152 +---------+--------------+-----------+------------+----------+
154 Note 1: If AI command and AO command are used simultaneously, only
155 one may have scan_begin_src == TRIG_TIMER.
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.
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
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:
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
179 Only mode 0 of the 8255 chip is supported.
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.
186 Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples.
187 Support for PCI230+/260+, more triggered scan functionality, and workarounds
188 for (or detection of) various hardware problems added by Ian Abbott.
191 #include "../comedidev.h"
193 #include <linux/delay.h>
194 #include <linux/interrupt.h>
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
205 #define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */
206 #define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */
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) */
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) */
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
253 #define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS */
254 /* - 10µs for se, 20µs de. */
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)
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 */
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 */
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
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)
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 */
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 */
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 */
347 /* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
348 * mode. Can be anything. */
349 #define PCI230_ADC_CONV 0xffff
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. */
359 * Counter/timer clock input configuration sources.
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
379 * Counter/timer gate input configuration sources.
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))
389 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
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
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)
409 #define PCI230_TEST_BIT(val, n) ((val>>n)&1)
410 /* Assumes bits numbered with zero offset, ie. 0-15 */
412 /* (Potentially) shared resources and their owners */
414 RES_Z2CT0, /* Z2-CT0 */
415 RES_Z2CT1, /* Z2-CT1 */
416 RES_Z2CT2, /* Z2-CT2 */
417 NUM_RESOURCES /* Number of (potentially) shared resources. */
421 OWNER_NONE, /* Not owned */
422 OWNER_AICMD, /* Owned by AI command */
423 OWNER_AOCMD /* Owned by AO command */
430 /* Combine old and new bits. */
431 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
433 /* A generic null function pointer value. */
436 /* Current CPU. XXX should this be hard_smp_processor_id()? */
437 #define THISCPU smp_processor_id()
439 /* State flags for atomic bit operations */
440 #define AI_CMD_STARTED 0
441 #define AO_CMD_STARTED 1
444 * Board descriptions for the two boards supported.
447 struct pci230_board {
455 unsigned int min_hwver; /* Minimum hardware version supported. */
457 static const struct pci230_board pci230_boards[] = {
460 .id = PCI_DEVICE_ID_PCI230,
470 .id = PCI_DEVICE_ID_PCI260,
480 .id = PCI_DEVICE_ID_PCI230,
489 .id = PCI_DEVICE_ID_PCI260,
497 .name = "amplc_pci230", /* Wildcard matches any above */
498 .id = PCI_DEVICE_ID_INVALID,
502 /* this structure is for data unique to this hardware driver. If
503 several hardware drivers keep similar information in this structure,
504 feel free to suggest moving the variable to the struct comedi_device struct. */
505 struct pci230_private {
506 struct pci_dev *pci_dev;
507 spinlock_t isr_spinlock; /* Interrupt spin lock */
508 spinlock_t res_spinlock; /* Shared resources spin lock */
509 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
510 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
511 unsigned long state; /* State flags */
512 unsigned long iobase1; /* PCI230's I/O space 1 */
513 unsigned int ao_readback[2]; /* Used for AO readback */
514 unsigned int ai_scan_count; /* Number of analogue input scans
516 unsigned int ai_scan_pos; /* Current position within analogue
518 unsigned int ao_scan_count; /* Number of analogue output scans
520 int intr_cpuid; /* ID of CPU running interrupt routine. */
521 unsigned short hwver; /* Hardware version (for '+' models). */
522 unsigned short adccon; /* ADCCON register value. */
523 unsigned short daccon; /* DACCON register value. */
524 unsigned short adcfifothresh; /* ADC FIFO programmable interrupt
525 * level threshold (PCI230+/260+). */
526 unsigned short adcg; /* ADCG register value. */
527 unsigned char int_en; /* Interrupt enables bits. */
528 unsigned char ai_continuous; /* Flag set when cmd->stop_src ==
529 * TRIG_NONE - user chooses to stop
530 * continuous conversion by
532 unsigned char ao_continuous; /* Flag set when cmd->stop_src ==
533 * TRIG_NONE - user chooses to stop
534 * continuous conversion by
536 unsigned char ai_bipolar; /* Set if bipolar input range so we
537 * know to mangle it. */
538 unsigned char ao_bipolar; /* Set if bipolar output range so we
539 * know to mangle it. */
540 unsigned char ier; /* Copy of interrupt enables/status register. */
541 unsigned char intr_running; /* Flag set in interrupt routine. */
542 unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */
545 /* PCI230 clock source periods in ns */
546 static const unsigned int pci230_timebase[8] = {
547 [CLK_10MHZ] = TIMEBASE_10MHZ,
548 [CLK_1MHZ] = TIMEBASE_1MHZ,
549 [CLK_100KHZ] = TIMEBASE_100KHZ,
550 [CLK_10KHZ] = TIMEBASE_10KHZ,
551 [CLK_1KHZ] = TIMEBASE_1KHZ,
554 /* PCI230 analogue input range table */
555 static const struct comedi_lrange pci230_ai_range = { 7, {
566 /* PCI230 analogue gain bits for each input range. */
567 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
569 /* PCI230 adccon bipolar flag for each analogue input range. */
570 static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
572 /* PCI230 analogue output range table */
573 static const struct comedi_lrange pci230_ao_range = { 2, {
579 /* PCI230 daccon bipolar flag for each analogue output range. */
580 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
582 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
583 unsigned int mode, uint64_t ns,
585 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
586 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct);
587 static void pci230_ao_stop(struct comedi_device *dev,
588 struct comedi_subdevice *s);
589 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
590 struct comedi_subdevice *s);
591 static int pci230_handle_ao_fifo(struct comedi_device *dev,
592 struct comedi_subdevice *s);
593 static void pci230_ai_stop(struct comedi_device *dev,
594 struct comedi_subdevice *s);
595 static void pci230_handle_ai(struct comedi_device *dev,
596 struct comedi_subdevice *s);
598 static short pci230_ai_read(struct comedi_device *dev)
600 const struct pci230_board *thisboard = comedi_board(dev);
601 struct pci230_private *devpriv = dev->private;
605 data = (short)inw(dev->iobase + PCI230_ADCDATA);
606 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
607 * four bits reserved for expansion). */
608 /* PCI230+ is 16 bit AI. */
609 data = data >> (16 - thisboard->ai_bits);
611 /* If a bipolar range was specified, mangle it (twos
612 * complement->straight binary). */
613 if (devpriv->ai_bipolar)
614 data ^= 1 << (thisboard->ai_bits - 1);
619 static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
622 const struct pci230_board *thisboard = comedi_board(dev);
623 struct pci230_private *devpriv = dev->private;
625 /* If a bipolar range was specified, mangle it (straight binary->twos
627 if (devpriv->ao_bipolar)
628 datum ^= 1 << (thisboard->ao_bits - 1);
630 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
631 * four bits reserved for expansion). */
632 /* PCI230+ is also 12 bit AO. */
633 datum <<= (16 - thisboard->ao_bits);
634 return (unsigned short)datum;
637 static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
638 short datum, unsigned int chan)
640 struct pci230_private *devpriv = dev->private;
642 /* Store unmangled datum to be read back later. */
643 devpriv->ao_readback[chan] = datum;
645 /* Write mangled datum to appropriate DACOUT register. */
646 outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
652 static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
655 struct pci230_private *devpriv = dev->private;
657 /* Store unmangled datum to be read back later. */
658 devpriv->ao_readback[chan] = datum;
660 /* Write mangled datum to appropriate DACDATA register. */
661 outw(pci230_ao_mangle_datum(dev, datum),
662 dev->iobase + PCI230P2_DACDATA);
665 static int get_resources(struct comedi_device *dev, unsigned int res_mask,
668 struct pci230_private *devpriv = dev->private;
672 unsigned int claimed;
673 unsigned long irqflags;
677 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
678 for (b = 1, i = 0; (i < NUM_RESOURCES)
679 && (res_mask != 0); b <<= 1, i++) {
680 if ((res_mask & b) != 0) {
682 if (devpriv->res_owner[i] == OWNER_NONE) {
683 devpriv->res_owner[i] = owner;
685 } else if (devpriv->res_owner[i] != owner) {
686 for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
687 if ((claimed & b) != 0) {
688 devpriv->res_owner[i]
698 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
702 static inline int get_one_resource(struct comedi_device *dev,
703 unsigned int resource, unsigned char owner)
705 return get_resources(dev, (1U << resource), owner);
708 static void put_resources(struct comedi_device *dev, unsigned int res_mask,
711 struct pci230_private *devpriv = dev->private;
714 unsigned long irqflags;
716 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
717 for (b = 1, i = 0; (i < NUM_RESOURCES)
718 && (res_mask != 0); b <<= 1, i++) {
719 if ((res_mask & b) != 0) {
721 if (devpriv->res_owner[i] == owner)
722 devpriv->res_owner[i] = OWNER_NONE;
726 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
729 static inline void put_one_resource(struct comedi_device *dev,
730 unsigned int resource, unsigned char owner)
732 put_resources(dev, (1U << resource), owner);
735 static inline void put_all_resources(struct comedi_device *dev,
738 put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
742 * COMEDI_SUBD_AI instruction;
744 static int pci230_ai_rinsn(struct comedi_device *dev,
745 struct comedi_subdevice *s, struct comedi_insn *insn,
748 struct pci230_private *devpriv = dev->private;
750 unsigned int chan, range, aref;
751 unsigned int gainshift;
753 unsigned short adccon, adcen;
755 /* Unpack channel and range. */
756 chan = CR_CHAN(insn->chanspec);
757 range = CR_RANGE(insn->chanspec);
758 aref = CR_AREF(insn->chanspec);
759 if (aref == AREF_DIFF) {
761 if (chan >= s->n_chan / 2) {
762 DPRINTK("comedi%d: amplc_pci230: ai_rinsn: "
763 "differential channel number out of range "
764 "0 to %u\n", dev->minor, (s->n_chan / 2) - 1);
769 /* Use Z2-CT2 as a conversion trigger instead of the built-in
770 * software trigger, as otherwise triggering of differential channels
771 * doesn't work properly for some versions of PCI230/260. Also set
772 * FIFO mode because the ADC busy bit only works for software triggers.
774 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
775 /* Set Z2-CT2 output low to avoid any false triggers. */
776 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
777 devpriv->ai_bipolar = pci230_ai_bipolar[range];
778 if (aref == AREF_DIFF) {
780 gainshift = chan * 2;
781 if (devpriv->hwver == 0) {
782 /* Original PCI230/260 expects both inputs of the
783 * differential channel to be enabled. */
784 adcen = 3 << gainshift;
786 /* PCI230+/260+ expects only one input of the
787 * differential channel to be enabled. */
788 adcen = 1 << gainshift;
790 adccon |= PCI230_ADC_IM_DIF;
794 gainshift = chan & ~1;
795 adccon |= PCI230_ADC_IM_SE;
797 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
798 | (pci230_ai_gain[range] << gainshift);
799 if (devpriv->ai_bipolar)
800 adccon |= PCI230_ADC_IR_BIP;
802 adccon |= PCI230_ADC_IR_UNI;
805 /* Enable only this channel in the scan list - otherwise by default
806 * we'll get one sample from each channel. */
807 outw(adcen, dev->iobase + PCI230_ADCEN);
809 /* Set gain for channel. */
810 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
812 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
813 devpriv->adccon = adccon;
814 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
816 /* Convert n samples */
817 for (n = 0; n < insn->n; n++) {
818 /* Trigger conversion by toggling Z2-CT2 output (finish with
820 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
822 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
826 /* wait for conversion to end */
827 for (i = 0; i < TIMEOUT; i++) {
828 status = inw(dev->iobase + PCI230_ADCCON);
829 if (!(status & PCI230_ADC_FIFO_EMPTY))
834 dev_err(dev->class_dev, "timeout\n");
839 data[n] = pci230_ai_read(dev);
842 /* return the number of samples read/written */
847 * COMEDI_SUBD_AO instructions;
849 static int pci230_ao_winsn(struct comedi_device *dev,
850 struct comedi_subdevice *s, struct comedi_insn *insn,
853 struct pci230_private *devpriv = dev->private;
857 /* Unpack channel and range. */
858 chan = CR_CHAN(insn->chanspec);
859 range = CR_RANGE(insn->chanspec);
861 /* Set range - see analogue output range table; 0 => unipolar 10V,
862 * 1 => bipolar +/-10V range scale */
863 devpriv->ao_bipolar = pci230_ao_bipolar[range];
864 outw(range, dev->iobase + PCI230_DACCON);
866 /* Writing a list of values to an AO channel is probably not
867 * very useful, but that's how the interface is defined. */
868 for (i = 0; i < insn->n; i++) {
869 /* Write value to DAC and store it. */
870 pci230_ao_write_nofifo(dev, data[i], chan);
873 /* return the number of samples read/written */
877 /* AO subdevices should have a read insn as well as a write insn.
878 * Usually this means copying a value stored in devpriv. */
879 static int pci230_ao_rinsn(struct comedi_device *dev,
880 struct comedi_subdevice *s, struct comedi_insn *insn,
883 struct pci230_private *devpriv = dev->private;
885 int chan = CR_CHAN(insn->chanspec);
887 for (i = 0; i < insn->n; i++)
888 data[i] = devpriv->ao_readback[chan];
893 static int pci230_ao_cmdtest(struct comedi_device *dev,
894 struct comedi_subdevice *s, struct comedi_cmd *cmd)
896 const struct pci230_board *thisboard = comedi_board(dev);
897 struct pci230_private *devpriv = dev->private;
901 /* cmdtest tests a particular command to see if it is valid.
902 * Using the cmdtest ioctl, a user can create a valid cmd
903 * and then have it executes by the cmd ioctl.
905 * cmdtest returns 1,2,3,4 or 0, depending on which tests
906 * the command passes. */
908 /* Step 1: make sure trigger sources are trivially valid.
909 * "invalid source" returned by comedilib to user mode process
912 tmp = cmd->start_src;
913 cmd->start_src &= TRIG_INT;
914 if (!cmd->start_src || tmp != cmd->start_src)
917 tmp = cmd->scan_begin_src;
918 if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
920 * For PCI230+ hardware version 2 onwards, allow external
921 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
923 * FIXME: The permitted scan_begin_src values shouldn't depend
924 * on devpriv->hwver (the detected card's actual hardware
925 * version). They should only depend on thisboard->min_hwver
926 * (the static capabilities of the configured card). To fix
927 * it, a new card model, e.g. "pci230+2" would have to be
928 * defined with min_hwver set to 2. It doesn't seem worth it
929 * for this alone. At the moment, please consider
930 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
933 cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
935 cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT;
937 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
940 tmp = cmd->convert_src;
941 cmd->convert_src &= TRIG_NOW;
942 if (!cmd->convert_src || tmp != cmd->convert_src)
945 tmp = cmd->scan_end_src;
946 cmd->scan_end_src &= TRIG_COUNT;
947 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
951 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
952 if (!cmd->stop_src || tmp != cmd->stop_src)
958 /* Step 2: make sure trigger sources are unique and mutually compatible
959 * "source conflict" returned by comedilib to user mode process
962 /* these tests are true if more than one _src bit is set */
963 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
965 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
967 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
969 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
971 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
977 /* Step 3: make sure arguments are trivially compatible.
978 * "invalid argument" returned by comedilib to user mode process
981 if (cmd->start_arg != 0) {
985 #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */
986 #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */
987 /*- Comedi limit due to unsigned int cmd. Driver limit
988 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
989 * clock) = 65.536s */
991 switch (cmd->scan_begin_src) {
993 if (cmd->scan_begin_arg < MAX_SPEED_AO) {
994 cmd->scan_begin_arg = MAX_SPEED_AO;
997 if (cmd->scan_begin_arg > MIN_SPEED_AO) {
998 cmd->scan_begin_arg = MIN_SPEED_AO;
1003 /* External trigger - for PCI230+ hardware version 2 onwards. */
1004 /* Trigger number must be 0. */
1005 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1006 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1010 /* The only flags allowed are CR_EDGE and CR_INVERT. The
1011 * CR_EDGE flag is ignored. */
1012 if ((cmd->scan_begin_arg
1013 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1014 cmd->scan_begin_arg =
1015 COMBINE(cmd->scan_begin_arg, 0,
1016 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
1021 if (cmd->scan_begin_arg != 0) {
1022 cmd->scan_begin_arg = 0;
1028 if (cmd->scan_end_arg != cmd->chanlist_len) {
1029 cmd->scan_end_arg = cmd->chanlist_len;
1032 if (cmd->stop_src == TRIG_NONE) {
1034 if (cmd->stop_arg != 0) {
1043 /* Step 4: fix up any arguments.
1044 * "argument conflict" returned by comedilib to user mode process
1047 if (cmd->scan_begin_src == TRIG_TIMER) {
1048 tmp = cmd->scan_begin_arg;
1049 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1050 cmd->flags & TRIG_ROUND_MASK);
1051 if (tmp != cmd->scan_begin_arg)
1058 /* Step 5: check channel list if it exists. */
1060 if (cmd->chanlist && cmd->chanlist_len > 0) {
1063 range_err = (1 << 1)
1065 unsigned int errors;
1067 unsigned int chan, prev_chan;
1068 unsigned int range, first_range;
1070 prev_chan = CR_CHAN(cmd->chanlist[0]);
1071 first_range = CR_RANGE(cmd->chanlist[0]);
1073 for (n = 1; n < cmd->chanlist_len; n++) {
1074 chan = CR_CHAN(cmd->chanlist[n]);
1075 range = CR_RANGE(cmd->chanlist[n]);
1076 /* Channel numbers must strictly increase. */
1077 if (chan < prev_chan)
1080 /* Ranges must be the same. */
1081 if (range != first_range)
1082 errors |= range_err;
1088 if ((errors & seq_err) != 0) {
1089 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1090 "channel numbers must increase\n",
1093 if ((errors & range_err) != 0) {
1094 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1095 "channels must have the same range\n",
1107 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1108 struct comedi_subdevice *s,
1109 unsigned int trig_num)
1111 struct pci230_private *devpriv = dev->private;
1112 unsigned long irqflags;
1117 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1118 if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
1120 if (devpriv->hwver < 2) {
1121 /* Not using DAC FIFO. */
1122 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1124 pci230_handle_ao_nofifo(dev, s);
1125 comedi_event(dev, s);
1127 /* Using DAC FIFO. */
1128 /* Read DACSWTRIG register to trigger conversion. */
1129 inw(dev->iobase + PCI230P2_DACSWTRIG);
1130 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1133 /* Delay. Should driver be responsible for this? */
1134 /* XXX TODO: See if DAC busy bit can be used. */
1141 static void pci230_ao_start(struct comedi_device *dev,
1142 struct comedi_subdevice *s)
1144 struct pci230_private *devpriv = dev->private;
1145 struct comedi_async *async = s->async;
1146 struct comedi_cmd *cmd = &async->cmd;
1147 unsigned long irqflags;
1149 set_bit(AO_CMD_STARTED, &devpriv->state);
1150 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1151 /* An empty acquisition! */
1152 async->events |= COMEDI_CB_EOA;
1153 pci230_ao_stop(dev, s);
1154 comedi_event(dev, s);
1156 if (devpriv->hwver >= 2) {
1157 /* Using DAC FIFO. */
1158 unsigned short scantrig;
1161 /* Preload FIFO data. */
1162 run = pci230_handle_ao_fifo(dev, s);
1163 comedi_event(dev, s);
1168 /* Set scan trigger source. */
1169 switch (cmd->scan_begin_src) {
1171 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1174 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1175 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1177 scantrig = PCI230P2_DAC_TRIG_EXTP;
1180 scantrig = PCI230P2_DAC_TRIG_EXTN;
1184 scantrig = PCI230P2_DAC_TRIG_SW;
1187 /* Shouldn't get here. */
1188 scantrig = PCI230P2_DAC_TRIG_NONE;
1191 devpriv->daccon = (devpriv->daccon
1192 & ~PCI230P2_DAC_TRIG_MASK) |
1194 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1197 switch (cmd->scan_begin_src) {
1199 if (devpriv->hwver < 2) {
1200 /* Not using DAC FIFO. */
1201 /* Enable CT1 timer interrupt. */
1202 spin_lock_irqsave(&devpriv->isr_spinlock,
1204 devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1205 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1207 devpriv->iobase1 + PCI230_INT_SCE);
1208 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1211 /* Set CT1 gate high to start counting. */
1212 outb(GAT_CONFIG(1, GAT_VCC),
1213 devpriv->iobase1 + PCI230_ZGAT_SCE);
1216 async->inttrig = pci230_ao_inttrig_scan_begin;
1219 if (devpriv->hwver >= 2) {
1220 /* Using DAC FIFO. Enable DAC FIFO interrupt. */
1221 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1222 devpriv->int_en |= PCI230P2_INT_DAC;
1223 devpriv->ier |= PCI230P2_INT_DAC;
1224 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1225 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1231 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1232 struct comedi_subdevice *s,
1233 unsigned int trig_num)
1238 s->async->inttrig = NULLFUNC;
1239 pci230_ao_start(dev, s);
1244 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1246 struct pci230_private *devpriv = dev->private;
1247 unsigned short daccon;
1250 /* Get the command. */
1251 struct comedi_cmd *cmd = &s->async->cmd;
1253 if (cmd->scan_begin_src == TRIG_TIMER) {
1255 if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
1260 /* Get number of scans required. */
1261 if (cmd->stop_src == TRIG_COUNT) {
1262 devpriv->ao_scan_count = cmd->stop_arg;
1263 devpriv->ao_continuous = 0;
1265 /* TRIG_NONE, user calls cancel. */
1266 devpriv->ao_scan_count = 0;
1267 devpriv->ao_continuous = 1;
1270 /* Set range - see analogue output range table; 0 => unipolar 10V,
1271 * 1 => bipolar +/-10V range scale */
1272 range = CR_RANGE(cmd->chanlist[0]);
1273 devpriv->ao_bipolar = pci230_ao_bipolar[range];
1274 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1275 /* Use DAC FIFO for hardware version 2 onwards. */
1276 if (devpriv->hwver >= 2) {
1277 unsigned short dacen;
1281 for (i = 0; i < cmd->chanlist_len; i++)
1282 dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1284 /* Set channel scan list. */
1285 outw(dacen, dev->iobase + PCI230P2_DACEN);
1288 * Set DAC scan source to 'none'.
1289 * Set DAC FIFO interrupt trigger level to 'not half full'.
1290 * Reset DAC FIFO and clear underrun.
1292 * N.B. DAC FIFO interrupts are currently disabled.
1294 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1295 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1296 | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1300 outw(daccon, dev->iobase + PCI230_DACCON);
1301 /* Preserve most of DACCON apart from write-only, transient bits. */
1302 devpriv->daccon = daccon
1303 & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1305 if (cmd->scan_begin_src == TRIG_TIMER) {
1306 /* Set the counter timer 1 to the specified scan frequency. */
1307 /* cmd->scan_begin_arg is sampling period in ns */
1308 /* gate it off for now. */
1309 outb(GAT_CONFIG(1, GAT_GND),
1310 devpriv->iobase1 + PCI230_ZGAT_SCE);
1311 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1312 cmd->scan_begin_arg,
1313 cmd->flags & TRIG_ROUND_MASK);
1316 /* N.B. cmd->start_src == TRIG_INT */
1317 s->async->inttrig = pci230_ao_inttrig_start;
1322 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1324 unsigned int min_scan_period, chanlist_len;
1327 chanlist_len = cmd->chanlist_len;
1328 if (cmd->chanlist_len == 0)
1331 min_scan_period = chanlist_len * cmd->convert_arg;
1332 if ((min_scan_period < chanlist_len)
1333 || (min_scan_period < cmd->convert_arg)) {
1334 /* Arithmetic overflow. */
1335 min_scan_period = UINT_MAX;
1338 if (cmd->scan_begin_arg < min_scan_period) {
1339 cmd->scan_begin_arg = min_scan_period;
1346 static int pci230_ai_cmdtest(struct comedi_device *dev,
1347 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1349 const struct pci230_board *thisboard = comedi_board(dev);
1350 struct pci230_private *devpriv = dev->private;
1354 /* cmdtest tests a particular command to see if it is valid.
1355 * Using the cmdtest ioctl, a user can create a valid cmd
1356 * and then have it executes by the cmd ioctl.
1358 * cmdtest returns 1,2,3,4,5 or 0, depending on which tests
1359 * the command passes. */
1361 /* Step 1: make sure trigger sources are trivially valid.
1362 * "invalid source" returned by comedilib to user mode process
1365 tmp = cmd->start_src;
1366 cmd->start_src &= TRIG_NOW | TRIG_INT;
1367 if (!cmd->start_src || tmp != cmd->start_src)
1370 tmp = cmd->scan_begin_src;
1371 /* Unfortunately, we cannot trigger a scan off an external source
1372 * on the PCI260 board, since it uses the PPIC0 (DIO) input, which
1373 * isn't present on the PCI260. For PCI260+ we can use the
1374 * EXTTRIG/EXTCONVCLK input on pin 17 instead. */
1375 if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1376 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT
1379 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1381 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1384 tmp = cmd->convert_src;
1385 cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1386 if (!cmd->convert_src || tmp != cmd->convert_src)
1389 tmp = cmd->scan_end_src;
1390 cmd->scan_end_src &= TRIG_COUNT;
1391 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1394 tmp = cmd->stop_src;
1395 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1396 if (!cmd->stop_src || tmp != cmd->stop_src)
1402 /* Step 2: make sure trigger sources are unique and mutually compatible
1403 * "source conflict" returned by comedilib to user mode process
1406 /* these tests are true if more than one _src bit is set */
1407 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1409 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1411 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1413 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1415 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1418 /* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1419 * set up to generate a fixed number of timed conversion pulses. */
1420 if ((cmd->scan_begin_src != TRIG_FOLLOW)
1421 && (cmd->convert_src != TRIG_TIMER))
1427 /* Step 3: make sure arguments are trivially compatible.
1428 * "invalid argument" returned by comedilib to user mode process
1431 if (cmd->start_arg != 0) {
1435 #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */
1436 #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */
1437 #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */
1438 #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */
1439 /*- Comedi limit due to unsigned int cmd. Driver limit
1440 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1441 * clock) = 65.536s */
1443 if (cmd->convert_src == TRIG_TIMER) {
1444 unsigned int max_speed_ai;
1446 if (devpriv->hwver == 0) {
1447 /* PCI230 or PCI260. Max speed depends whether
1448 * single-ended or pseudo-differential. */
1449 if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1450 /* Peek analogue reference of first channel. */
1451 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1452 max_speed_ai = MAX_SPEED_AI_DIFF;
1454 max_speed_ai = MAX_SPEED_AI_SE;
1457 /* No channel list. Assume single-ended. */
1458 max_speed_ai = MAX_SPEED_AI_SE;
1461 /* PCI230+ or PCI260+. */
1462 max_speed_ai = MAX_SPEED_AI_PLUS;
1465 if (cmd->convert_arg < max_speed_ai) {
1466 cmd->convert_arg = max_speed_ai;
1469 if (cmd->convert_arg > MIN_SPEED_AI) {
1470 cmd->convert_arg = MIN_SPEED_AI;
1473 } else if (cmd->convert_src == TRIG_EXT) {
1477 * convert_arg == (CR_EDGE | 0)
1478 * => trigger on +ve edge.
1479 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1480 * => trigger on -ve edge.
1482 if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1483 /* Trigger number must be 0. */
1484 if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1485 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1489 /* The only flags allowed are CR_INVERT and CR_EDGE.
1490 * CR_EDGE is required. */
1491 if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1493 /* Set CR_EDGE, preserve CR_INVERT. */
1495 COMBINE(cmd->start_arg, (CR_EDGE | 0),
1496 CR_FLAGS_MASK & ~CR_INVERT);
1500 /* Backwards compatibility with previous versions. */
1501 /* convert_arg == 0 => trigger on -ve edge. */
1502 /* convert_arg == 1 => trigger on +ve edge. */
1503 if (cmd->convert_arg > 1) {
1504 /* Default to trigger on +ve edge. */
1505 cmd->convert_arg = 1;
1510 if (cmd->convert_arg != 0) {
1511 cmd->convert_arg = 0;
1516 if (cmd->scan_end_arg != cmd->chanlist_len) {
1517 cmd->scan_end_arg = cmd->chanlist_len;
1521 if (cmd->stop_src == TRIG_NONE) {
1522 if (cmd->stop_arg != 0) {
1528 if (cmd->scan_begin_src == TRIG_EXT) {
1529 /* external "trigger" to begin each scan
1530 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1531 * of CT2 (sample convert trigger is CT2) */
1532 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1533 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1537 /* The only flag allowed is CR_EDGE, which is ignored. */
1538 if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1539 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1540 CR_FLAGS_MASK & ~CR_EDGE);
1543 } else if (cmd->scan_begin_src == TRIG_TIMER) {
1544 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1545 if (!pci230_ai_check_scan_period(cmd))
1549 if (cmd->scan_begin_arg != 0) {
1550 cmd->scan_begin_arg = 0;
1558 /* Step 4: fix up any arguments.
1559 * "argument conflict" returned by comedilib to user mode process
1562 if (cmd->convert_src == TRIG_TIMER) {
1563 tmp = cmd->convert_arg;
1564 pci230_ns_to_single_timer(&cmd->convert_arg,
1565 cmd->flags & TRIG_ROUND_MASK);
1566 if (tmp != cmd->convert_arg)
1570 if (cmd->scan_begin_src == TRIG_TIMER) {
1571 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1572 tmp = cmd->scan_begin_arg;
1573 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1574 cmd->flags & TRIG_ROUND_MASK);
1575 if (!pci230_ai_check_scan_period(cmd)) {
1576 /* Was below minimum required. Round up. */
1577 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1579 pci230_ai_check_scan_period(cmd);
1581 if (tmp != cmd->scan_begin_arg)
1588 /* Step 5: check channel list if it exists. */
1590 if (cmd->chanlist && cmd->chanlist_len > 0) {
1593 rangepair_err = 1 << 1,
1594 polarity_err = 1 << 2,
1596 diffchan_err = 1 << 4,
1597 buggy_chan0_err = 1 << 5
1599 unsigned int errors;
1600 unsigned int chan, prev_chan;
1601 unsigned int range, prev_range;
1602 unsigned int polarity, prev_polarity;
1603 unsigned int aref, prev_aref;
1604 unsigned int subseq_len;
1609 prev_chan = prev_aref = prev_range = prev_polarity = 0;
1610 for (n = 0; n < cmd->chanlist_len; n++) {
1611 chan = CR_CHAN(cmd->chanlist[n]);
1612 range = CR_RANGE(cmd->chanlist[n]);
1613 aref = CR_AREF(cmd->chanlist[n]);
1614 polarity = pci230_ai_bipolar[range];
1615 /* Only the first half of the channels are available if
1616 * differential. (These are remapped in software. In
1617 * hardware, only the even channels are available.) */
1618 if ((aref == AREF_DIFF)
1619 && (chan >= (s->n_chan / 2))) {
1620 errors |= diffchan_err;
1623 /* Channel numbers must strictly increase or
1624 * subsequence must repeat exactly. */
1625 if ((chan <= prev_chan)
1626 && (subseq_len == 0)) {
1629 if ((subseq_len > 0)
1630 && (cmd->chanlist[n] !=
1631 cmd->chanlist[n % subseq_len])) {
1634 /* Channels must have same AREF. */
1635 if (aref != prev_aref)
1638 /* Channel ranges must have same polarity. */
1639 if (polarity != prev_polarity)
1640 errors |= polarity_err;
1642 /* Single-ended channel pairs must have same
1644 if ((aref != AREF_DIFF)
1645 && (((chan ^ prev_chan) & ~1) == 0)
1646 && (range != prev_range)) {
1647 errors |= rangepair_err;
1653 prev_polarity = polarity;
1655 if (subseq_len == 0) {
1656 /* Subsequence is whole sequence. */
1659 /* If channel list is a repeating subsequence, need a whole
1660 * number of repeats. */
1661 if ((n % subseq_len) != 0)
1664 if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
1666 * Buggy PCI230+ or PCI260+ requires channel 0 to be
1667 * (first) in the sequence if the sequence contains
1668 * more than one channel. Hardware versions 1 and 2
1669 * have the bug. There is no hardware version 3.
1671 * Actually, there are two firmwares that report
1672 * themselves as hardware version 1 (the boards
1673 * have different ADC chips with slightly different
1674 * timing requirements, which was supposed to be
1675 * invisible to software). The first one doesn't
1676 * seem to have the bug, but the second one
1677 * does, and we can't tell them apart!
1679 if ((subseq_len > 1)
1680 && (CR_CHAN(cmd->chanlist[0]) != 0)) {
1681 errors |= buggy_chan0_err;
1686 if ((errors & seq_err) != 0) {
1687 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1688 "channel numbers must increase or "
1689 "sequence must repeat exactly\n",
1692 if ((errors & rangepair_err) != 0) {
1693 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1694 "single-ended channel pairs must "
1695 "have the same range\n", dev->minor);
1697 if ((errors & polarity_err) != 0) {
1698 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1699 "channel sequence ranges must be all "
1700 "bipolar or all unipolar\n",
1703 if ((errors & aref_err) != 0) {
1704 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1705 "channel sequence analogue references "
1706 "must be all the same (single-ended "
1707 "or differential)\n", dev->minor);
1709 if ((errors & diffchan_err) != 0) {
1710 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1711 "differential channel number out of "
1712 "range 0 to %u\n", dev->minor,
1713 (s->n_chan / 2) - 1);
1715 if ((errors & buggy_chan0_err) != 0) {
1716 dev_info(dev->class_dev,
1717 "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",
1729 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
1730 struct comedi_subdevice *s)
1732 struct pci230_private *devpriv = dev->private;
1733 struct comedi_cmd *cmd = &s->async->cmd;
1734 unsigned int scanlen = cmd->scan_end_arg;
1736 unsigned short triglev;
1737 unsigned short adccon;
1739 if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
1740 /* Wake at end of scan. */
1741 wake = scanlen - devpriv->ai_scan_pos;
1743 if (devpriv->ai_continuous
1744 || (devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL)
1745 || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
1746 wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
1748 wake = (devpriv->ai_scan_count * scanlen)
1749 - devpriv->ai_scan_pos;
1752 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
1753 triglev = PCI230_ADC_INT_FIFO_HALF;
1755 if ((wake > 1) && (devpriv->hwver > 0)) {
1756 /* PCI230+/260+ programmable FIFO interrupt level. */
1757 if (devpriv->adcfifothresh != wake) {
1758 devpriv->adcfifothresh = wake;
1759 outw(wake, dev->iobase + PCI230P_ADCFFTH);
1761 triglev = PCI230P_ADC_INT_FIFO_THRESH;
1763 triglev = PCI230_ADC_INT_FIFO_NEMPTY;
1766 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
1767 if (adccon != devpriv->adccon) {
1768 devpriv->adccon = adccon;
1769 outw(adccon, dev->iobase + PCI230_ADCCON);
1773 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
1774 struct comedi_subdevice *s,
1775 unsigned int trig_num)
1777 struct pci230_private *devpriv = dev->private;
1778 unsigned long irqflags;
1783 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1784 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1785 unsigned int delayus;
1787 /* Trigger conversion by toggling Z2-CT2 output. Finish
1788 * with output high. */
1789 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1791 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1793 /* Delay. Should driver be responsible for this? An
1794 * alternative would be to wait until conversion is complete,
1795 * but we can't tell when it's complete because the ADC busy
1796 * bit has a different meaning when FIFO enabled (and when
1797 * FIFO not enabled, it only works for software triggers). */
1798 if (((devpriv->adccon & PCI230_ADC_IM_MASK)
1799 == PCI230_ADC_IM_DIF)
1800 && (devpriv->hwver == 0)) {
1801 /* PCI230/260 in differential mode */
1804 /* single-ended or PCI230+/260+ */
1807 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1810 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1816 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
1817 struct comedi_subdevice *s,
1818 unsigned int trig_num)
1820 struct pci230_private *devpriv = dev->private;
1821 unsigned long irqflags;
1827 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1828 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1829 /* Trigger scan by waggling CT0 gate source. */
1830 zgat = GAT_CONFIG(0, GAT_GND);
1831 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1832 zgat = GAT_CONFIG(0, GAT_VCC);
1833 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1835 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1840 static void pci230_ai_start(struct comedi_device *dev,
1841 struct comedi_subdevice *s)
1843 struct pci230_private *devpriv = dev->private;
1844 unsigned long irqflags;
1845 unsigned short conv;
1846 struct comedi_async *async = s->async;
1847 struct comedi_cmd *cmd = &async->cmd;
1849 set_bit(AI_CMD_STARTED, &devpriv->state);
1850 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
1851 /* An empty acquisition! */
1852 async->events |= COMEDI_CB_EOA;
1853 pci230_ai_stop(dev, s);
1854 comedi_event(dev, s);
1856 /* Enable ADC FIFO trigger level interrupt. */
1857 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1858 devpriv->int_en |= PCI230_INT_ADC;
1859 devpriv->ier |= PCI230_INT_ADC;
1860 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1861 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1863 /* Update conversion trigger source which is currently set
1864 * to CT2 output, which is currently stuck high. */
1865 switch (cmd->convert_src) {
1867 conv = PCI230_ADC_TRIG_NONE;
1870 /* Using CT2 output. */
1871 conv = PCI230_ADC_TRIG_Z2CT2;
1874 if ((cmd->convert_arg & CR_EDGE) != 0) {
1875 if ((cmd->convert_arg & CR_INVERT) == 0) {
1876 /* Trigger on +ve edge. */
1877 conv = PCI230_ADC_TRIG_EXTP;
1879 /* Trigger on -ve edge. */
1880 conv = PCI230_ADC_TRIG_EXTN;
1883 /* Backwards compatibility. */
1884 if (cmd->convert_arg != 0) {
1885 /* Trigger on +ve edge. */
1886 conv = PCI230_ADC_TRIG_EXTP;
1888 /* Trigger on -ve edge. */
1889 conv = PCI230_ADC_TRIG_EXTN;
1894 /* Use CT2 output for software trigger due to problems
1895 * in differential mode on PCI230/260. */
1896 conv = PCI230_ADC_TRIG_Z2CT2;
1899 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
1901 outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
1902 if (cmd->convert_src == TRIG_INT)
1903 async->inttrig = pci230_ai_inttrig_convert;
1905 /* Update FIFO interrupt trigger level, which is currently
1907 pci230_ai_update_fifo_trigger_level(dev, s);
1908 if (cmd->convert_src == TRIG_TIMER) {
1909 /* Update timer gates. */
1912 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1913 /* Conversion timer CT2 needs to be gated by
1914 * inverted output of monostable CT2. */
1915 zgat = GAT_CONFIG(2, GAT_NOUTNM2);
1917 /* Conversion timer CT2 needs to be gated on
1919 zgat = GAT_CONFIG(2, GAT_VCC);
1921 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1922 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1923 /* Set monostable CT0 trigger source. */
1924 switch (cmd->scan_begin_src) {
1926 zgat = GAT_CONFIG(0, GAT_VCC);
1930 * For CT0 on PCI230, the external
1931 * trigger (gate) signal comes from
1932 * PPC0, which is channel 16 of the DIO
1933 * subdevice. The application needs to
1934 * configure this as an input in order
1935 * to use it as an external scan
1938 zgat = GAT_CONFIG(0, GAT_EXT);
1942 * Monostable CT0 triggered by rising
1943 * edge on inverted output of CT1
1944 * (falling edge on CT1).
1946 zgat = GAT_CONFIG(0, GAT_NOUTNM2);
1950 * Monostable CT0 is triggered by
1951 * inttrig function waggling the CT0
1954 zgat = GAT_CONFIG(0, GAT_VCC);
1957 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1958 switch (cmd->scan_begin_src) {
1960 /* Scan period timer CT1 needs to be
1961 * gated on to start counting. */
1962 zgat = GAT_CONFIG(1, GAT_VCC);
1963 outb(zgat, devpriv->iobase1
1968 pci230_ai_inttrig_scan_begin;
1972 } else if (cmd->convert_src != TRIG_INT) {
1973 /* No longer need Z2-CT2. */
1974 put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
1979 static int pci230_ai_inttrig_start(struct comedi_device *dev,
1980 struct comedi_subdevice *s,
1981 unsigned int trig_num)
1986 s->async->inttrig = NULLFUNC;
1987 pci230_ai_start(dev, s);
1992 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1994 struct pci230_private *devpriv = dev->private;
1995 unsigned int i, chan, range, diff;
1996 unsigned int res_mask;
1997 unsigned short adccon, adcen;
2000 /* Get the command. */
2001 struct comedi_async *async = s->async;
2002 struct comedi_cmd *cmd = &async->cmd;
2005 * Determine which shared resources are needed.
2008 /* Need Z2-CT2 to supply a conversion trigger source at a high
2009 * logic level, even if not doing timed conversions. */
2010 res_mask |= (1U << RES_Z2CT2);
2011 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2012 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2013 res_mask |= (1U << RES_Z2CT0);
2014 if (cmd->scan_begin_src == TRIG_TIMER) {
2015 /* Using Z2-CT1 for scan frequency */
2016 res_mask |= (1U << RES_Z2CT1);
2019 /* Claim resources. */
2020 if (!get_resources(dev, res_mask, OWNER_AICMD))
2024 /* Get number of scans required. */
2025 if (cmd->stop_src == TRIG_COUNT) {
2026 devpriv->ai_scan_count = cmd->stop_arg;
2027 devpriv->ai_continuous = 0;
2029 /* TRIG_NONE, user calls cancel. */
2030 devpriv->ai_scan_count = 0;
2031 devpriv->ai_continuous = 1;
2033 devpriv->ai_scan_pos = 0; /* Position within scan. */
2036 * - Set channel scan list.
2037 * - Set channel gains.
2038 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2039 * start conversion source to point to something at a high logic
2040 * level (we use the output of counter/timer 2 for this purpose.
2041 * - PAUSE to allow things to settle down.
2042 * - Reset the FIFO again because it needs resetting twice and there
2043 * may have been a false conversion trigger on some versions of
2044 * PCI230/260 due to the start conversion source being set to a
2046 * - Enable ADC FIFO level interrupt.
2047 * - Set actual conversion trigger source and FIFO interrupt trigger
2049 * - If convert_src is TRIG_TIMER, set up the timers.
2052 adccon = PCI230_ADC_FIFO_EN;
2055 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2056 /* Differential - all channels must be differential. */
2058 adccon |= PCI230_ADC_IM_DIF;
2060 /* Single ended - all channels must be single-ended. */
2062 adccon |= PCI230_ADC_IM_SE;
2065 range = CR_RANGE(cmd->chanlist[0]);
2066 devpriv->ai_bipolar = pci230_ai_bipolar[range];
2067 if (devpriv->ai_bipolar)
2068 adccon |= PCI230_ADC_IR_BIP;
2070 adccon |= PCI230_ADC_IR_UNI;
2072 for (i = 0; i < cmd->chanlist_len; i++) {
2073 unsigned int gainshift;
2075 chan = CR_CHAN(cmd->chanlist[i]);
2076 range = CR_RANGE(cmd->chanlist[i]);
2078 gainshift = 2 * chan;
2079 if (devpriv->hwver == 0) {
2080 /* Original PCI230/260 expects both inputs of
2081 * the differential channel to be enabled. */
2082 adcen |= 3 << gainshift;
2084 /* PCI230+/260+ expects only one input of the
2085 * differential channel to be enabled. */
2086 adcen |= 1 << gainshift;
2089 gainshift = (chan & ~1);
2092 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2093 | (pci230_ai_gain[range] << gainshift);
2096 /* Set channel scan list. */
2097 outw(adcen, dev->iobase + PCI230_ADCEN);
2099 /* Set channel gains. */
2100 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2102 /* Set counter/timer 2 output high for use as the initial start
2103 * conversion source. */
2104 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2106 /* Temporarily use CT2 output as conversion trigger source and
2107 * temporarily set FIFO interrupt trigger level to 'full'. */
2108 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2110 /* Enable and reset FIFO, specify FIFO trigger level full, specify
2111 * uni/bip, se/diff, and temporarily set the start conversion source
2112 * to CT2 output. Note that CT2 output is currently high, and this
2113 * will produce a false conversion trigger on some versions of the
2114 * PCI230/260, but that will be dealt with later. */
2115 devpriv->adccon = adccon;
2116 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2119 /* Failure to include this will result in the first few channels'-worth
2120 * of data being corrupt, normally manifesting itself by large negative
2121 * voltages. It seems the board needs time to settle between the first
2122 * FIFO reset (above) and the second FIFO reset (below). Setting the
2123 * channel gains and scan list _before_ the first FIFO reset also
2124 * helps, though only slightly. */
2127 /* Reset FIFO again. */
2128 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2130 if (cmd->convert_src == TRIG_TIMER) {
2131 /* Set up CT2 as conversion timer, but gate it off for now.
2132 * Note, counter/timer output 2 can be monitored on the
2133 * connector: PCI230 pin 21, PCI260 pin 18. */
2134 zgat = GAT_CONFIG(2, GAT_GND);
2135 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2136 /* Set counter/timer 2 to the specified conversion period. */
2137 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2138 cmd->flags & TRIG_ROUND_MASK);
2139 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2141 * Set up monostable on CT0 output for scan timing. A
2142 * rising edge on the trigger (gate) input of CT0 will
2143 * trigger the monostable, causing its output to go low
2144 * for the configured period. The period depends on
2145 * the conversion period and the number of conversions
2148 * Set the trigger high before setting up the
2149 * monostable to stop it triggering. The trigger
2150 * source will be changed later.
2152 zgat = GAT_CONFIG(0, GAT_VCC);
2153 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2154 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2155 ((uint64_t) cmd->convert_arg
2156 * cmd->scan_end_arg),
2158 if (cmd->scan_begin_src == TRIG_TIMER) {
2160 * Monostable on CT0 will be triggered by
2161 * output of CT1 at configured scan frequency.
2163 * Set up CT1 but gate it off for now.
2165 zgat = GAT_CONFIG(1, GAT_GND);
2166 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2167 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2168 cmd->scan_begin_arg,
2176 if (cmd->start_src == TRIG_INT) {
2177 s->async->inttrig = pci230_ai_inttrig_start;
2180 pci230_ai_start(dev, s);
2186 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
2187 unsigned int round_mode)
2193 rem = do_div(div, timebase);
2194 round_mode &= TRIG_ROUND_MASK;
2195 switch (round_mode) {
2197 case TRIG_ROUND_NEAREST:
2198 div += (rem + (timebase / 2)) / timebase;
2200 case TRIG_ROUND_DOWN:
2203 div += (rem + timebase - 1) / timebase;
2206 return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
2209 /* Given desired period in ns, returns the required internal clock source
2210 * and gets the initial count. */
2211 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
2212 unsigned int round_mode)
2214 unsigned int clk_src, cnt;
2216 for (clk_src = CLK_10MHZ;; clk_src++) {
2217 cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
2218 if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
2226 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
2229 unsigned int clk_src;
2231 clk_src = pci230_choose_clk_count(*ns, &count, round);
2232 *ns = count * pci230_timebase[clk_src];
2236 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
2237 unsigned int mode, uint64_t ns,
2240 struct pci230_private *devpriv = dev->private;
2241 unsigned int clk_src;
2245 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
2246 /* Determine clock source and count. */
2247 clk_src = pci230_choose_clk_count(ns, &count, round);
2248 /* Program clock source. */
2249 outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
2250 /* Set initial count. */
2254 i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
2257 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
2259 struct pci230_private *devpriv = dev->private;
2261 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
2263 /* Counter ct, 8254 mode 1, initial count not written. */
2266 /* Interrupt handler */
2267 static irqreturn_t pci230_interrupt(int irq, void *d)
2269 unsigned char status_int, valid_status_int;
2270 struct comedi_device *dev = (struct comedi_device *)d;
2271 struct pci230_private *devpriv = dev->private;
2272 struct comedi_subdevice *s;
2273 unsigned long irqflags;
2275 /* Read interrupt status/enable register. */
2276 status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2278 if (status_int == PCI230_INT_DISABLE)
2282 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2283 valid_status_int = devpriv->int_en & status_int;
2284 /* Disable triggered interrupts.
2285 * (Only those interrupts that need re-enabling, are, later in the
2287 devpriv->ier = devpriv->int_en & ~status_int;
2288 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2289 devpriv->intr_running = 1;
2290 devpriv->intr_cpuid = THISCPU;
2291 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2294 * Check the source of interrupt and handle it.
2295 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2296 * interrupts. However, at present (Comedi-0.7.60) does not allow
2297 * concurrent execution of commands, instructions or a mixture of the
2301 if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2302 s = dev->write_subdev;
2303 pci230_handle_ao_nofifo(dev, s);
2304 comedi_event(dev, s);
2307 if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2308 s = dev->write_subdev;
2309 pci230_handle_ao_fifo(dev, s);
2310 comedi_event(dev, s);
2313 if ((valid_status_int & PCI230_INT_ADC) != 0) {
2314 s = dev->read_subdev;
2315 pci230_handle_ai(dev, s);
2316 comedi_event(dev, s);
2319 /* Reenable interrupts. */
2320 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2321 if (devpriv->ier != devpriv->int_en) {
2322 devpriv->ier = devpriv->int_en;
2323 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2325 devpriv->intr_running = 0;
2326 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2331 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
2332 struct comedi_subdevice *s)
2334 struct pci230_private *devpriv = dev->private;
2337 struct comedi_async *async = s->async;
2338 struct comedi_cmd *cmd = &async->cmd;
2340 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
2344 for (i = 0; i < cmd->chanlist_len; i++) {
2345 /* Read sample from Comedi's circular buffer. */
2346 ret = comedi_buf_get(s->async, &data);
2348 s->async->events |= COMEDI_CB_OVERFLOW;
2349 pci230_ao_stop(dev, s);
2350 comedi_error(dev, "AO buffer underrun");
2353 /* Write value to DAC. */
2354 pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
2357 async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
2358 if (!devpriv->ao_continuous) {
2359 devpriv->ao_scan_count--;
2360 if (devpriv->ao_scan_count == 0) {
2361 /* End of acquisition. */
2362 async->events |= COMEDI_CB_EOA;
2363 pci230_ao_stop(dev, s);
2368 /* Loads DAC FIFO (if using it) from buffer. */
2369 /* Returns 0 if AO finished due to completion or error, 1 if still going. */
2370 static int pci230_handle_ao_fifo(struct comedi_device *dev,
2371 struct comedi_subdevice *s)
2373 struct pci230_private *devpriv = dev->private;
2374 struct comedi_async *async = s->async;
2375 struct comedi_cmd *cmd = &async->cmd;
2376 unsigned int num_scans;
2378 unsigned short dacstat;
2380 unsigned int bytes_per_scan;
2381 unsigned int events = 0;
2384 /* Get DAC FIFO status. */
2385 dacstat = inw(dev->iobase + PCI230_DACCON);
2387 /* Determine number of scans available in buffer. */
2388 bytes_per_scan = cmd->chanlist_len * sizeof(short);
2389 num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
2390 if (!devpriv->ao_continuous) {
2391 /* Fixed number of scans. */
2392 if (num_scans > devpriv->ao_scan_count)
2393 num_scans = devpriv->ao_scan_count;
2395 if (devpriv->ao_scan_count == 0) {
2396 /* End of acquisition. */
2397 events |= COMEDI_CB_EOA;
2401 /* Check for FIFO underrun. */
2402 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2403 comedi_error(dev, "AO FIFO underrun");
2404 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2406 /* Check for buffer underrun if FIFO less than half full
2407 * (otherwise there will be loads of "DAC FIFO not half full"
2409 if ((num_scans == 0)
2410 && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
2411 comedi_error(dev, "AO buffer underrun");
2412 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2416 /* Determine how much room is in the FIFO (in samples). */
2417 if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
2418 room = PCI230P2_DAC_FIFOROOM_FULL;
2419 else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
2420 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
2421 else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
2422 room = PCI230P2_DAC_FIFOROOM_EMPTY;
2424 room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
2426 /* Convert room to number of scans that can be added. */
2427 room /= cmd->chanlist_len;
2428 /* Determine number of scans to process. */
2429 if (num_scans > room)
2432 /* Process scans. */
2433 for (n = 0; n < num_scans; n++) {
2434 for (i = 0; i < cmd->chanlist_len; i++) {
2437 comedi_buf_get(async, &datum);
2438 pci230_ao_write_fifo(dev, datum,
2439 CR_CHAN(cmd->chanlist[i]));
2442 events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
2443 if (!devpriv->ao_continuous) {
2444 devpriv->ao_scan_count -= num_scans;
2445 if (devpriv->ao_scan_count == 0) {
2446 /* All data for the command has been written
2447 * to FIFO. Set FIFO interrupt trigger level
2449 devpriv->daccon = (devpriv->daccon
2451 ~PCI230P2_DAC_INT_FIFO_MASK)
2452 | PCI230P2_DAC_INT_FIFO_EMPTY;
2453 outw(devpriv->daccon,
2454 dev->iobase + PCI230_DACCON);
2457 /* Check if FIFO underrun occurred while writing to FIFO. */
2458 dacstat = inw(dev->iobase + PCI230_DACCON);
2459 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2460 comedi_error(dev, "AO FIFO underrun");
2461 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2464 if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
2466 /* Stopping AO due to completion or error. */
2467 pci230_ao_stop(dev, s);
2472 async->events |= events;
2476 static void pci230_handle_ai(struct comedi_device *dev,
2477 struct comedi_subdevice *s)
2479 struct pci230_private *devpriv = dev->private;
2480 unsigned int events = 0;
2481 unsigned int status_fifo;
2484 unsigned int fifoamount;
2485 struct comedi_async *async = s->async;
2486 unsigned int scanlen = async->cmd.scan_end_arg;
2488 /* Determine number of samples to read. */
2489 if (devpriv->ai_continuous) {
2490 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2491 } else if (devpriv->ai_scan_count == 0) {
2493 } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2494 || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2495 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2497 todo = (devpriv->ai_scan_count * scanlen)
2498 - devpriv->ai_scan_pos;
2499 if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
2500 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2509 for (i = 0; i < todo; i++) {
2510 if (fifoamount == 0) {
2511 /* Read FIFO state. */
2512 status_fifo = inw(dev->iobase + PCI230_ADCCON);
2514 if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2515 /* Report error otherwise FIFO overruns will go
2516 * unnoticed by the caller. */
2517 comedi_error(dev, "AI FIFO overrun");
2518 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2520 } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2523 } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2524 /* FIFO half full. */
2525 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2527 /* FIFO not empty. */
2528 if (devpriv->hwver > 0) {
2529 /* Read PCI230+/260+ ADC FIFO level. */
2530 fifoamount = inw(dev->iobase
2531 + PCI230P_ADCFFLEV);
2532 if (fifoamount == 0) {
2533 /* Shouldn't happen. */
2542 /* Read sample and store in Comedi's circular buffer. */
2543 if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2544 events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2545 comedi_error(dev, "AI buffer overflow");
2549 devpriv->ai_scan_pos++;
2550 if (devpriv->ai_scan_pos == scanlen) {
2552 devpriv->ai_scan_pos = 0;
2553 devpriv->ai_scan_count--;
2554 async->events |= COMEDI_CB_EOS;
2558 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2559 /* End of acquisition. */
2560 events |= COMEDI_CB_EOA;
2562 /* More samples required, tell Comedi to block. */
2563 events |= COMEDI_CB_BLOCK;
2565 async->events |= events;
2567 if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2568 COMEDI_CB_OVERFLOW)) != 0) {
2569 /* disable hardware conversions */
2570 pci230_ai_stop(dev, s);
2572 /* update FIFO interrupt trigger level */
2573 pci230_ai_update_fifo_trigger_level(dev, s);
2577 static void pci230_ao_stop(struct comedi_device *dev,
2578 struct comedi_subdevice *s)
2580 struct pci230_private *devpriv = dev->private;
2581 unsigned long irqflags;
2582 unsigned char intsrc;
2584 struct comedi_cmd *cmd;
2586 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
2587 started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
2588 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
2593 cmd = &s->async->cmd;
2594 if (cmd->scan_begin_src == TRIG_TIMER) {
2595 /* Stop scan rate generator. */
2596 pci230_cancel_ct(dev, 1);
2599 /* Determine interrupt source. */
2600 if (devpriv->hwver < 2) {
2601 /* Not using DAC FIFO. Using CT1 interrupt. */
2602 intsrc = PCI230_INT_ZCLK_CT1;
2604 /* Using DAC FIFO interrupt. */
2605 intsrc = PCI230P2_INT_DAC;
2607 /* Disable interrupt and wait for interrupt routine to finish running
2608 * unless we are called from the interrupt routine. */
2609 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2610 devpriv->int_en &= ~intsrc;
2611 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2612 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2613 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2615 if (devpriv->ier != devpriv->int_en) {
2616 devpriv->ier = devpriv->int_en;
2617 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2619 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2621 if (devpriv->hwver >= 2) {
2622 /* Using DAC FIFO. Reset FIFO, clear underrun error,
2624 devpriv->daccon &= PCI230_DAC_OR_MASK;
2625 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
2626 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
2627 dev->iobase + PCI230_DACCON);
2630 /* Release resources. */
2631 put_all_resources(dev, OWNER_AOCMD);
2634 static int pci230_ao_cancel(struct comedi_device *dev,
2635 struct comedi_subdevice *s)
2637 pci230_ao_stop(dev, s);
2641 static void pci230_ai_stop(struct comedi_device *dev,
2642 struct comedi_subdevice *s)
2644 struct pci230_private *devpriv = dev->private;
2645 unsigned long irqflags;
2646 struct comedi_cmd *cmd;
2649 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2650 started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
2651 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2656 cmd = &s->async->cmd;
2657 if (cmd->convert_src == TRIG_TIMER) {
2658 /* Stop conversion rate generator. */
2659 pci230_cancel_ct(dev, 2);
2661 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2662 /* Stop scan period monostable. */
2663 pci230_cancel_ct(dev, 0);
2666 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2667 /* Disable ADC interrupt and wait for interrupt routine to finish
2668 * running unless we are called from the interrupt routine. */
2669 devpriv->int_en &= ~PCI230_INT_ADC;
2670 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2671 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2672 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2674 if (devpriv->ier != devpriv->int_en) {
2675 devpriv->ier = devpriv->int_en;
2676 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2678 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2680 /* Reset FIFO, disable FIFO and set start conversion source to none.
2681 * Keep se/diff and bip/uni settings */
2682 devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
2683 | PCI230_ADC_IM_MASK)) |
2684 PCI230_ADC_TRIG_NONE;
2685 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2686 dev->iobase + PCI230_ADCCON);
2688 /* Release resources. */
2689 put_all_resources(dev, OWNER_AICMD);
2692 static int pci230_ai_cancel(struct comedi_device *dev,
2693 struct comedi_subdevice *s)
2695 pci230_ai_stop(dev, s);
2699 /* Check if PCI device matches a specific board. */
2700 static bool pci230_match_pci_board(const struct pci230_board *board,
2701 struct pci_dev *pci_dev)
2703 /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */
2704 if (board->id != pci_dev->device)
2706 if (board->min_hwver == 0)
2708 /* Looking for a '+' model. First check length of registers. */
2709 if (pci_resource_len(pci_dev, 3) < 32)
2710 return false; /* Not a '+' model. */
2711 /* TODO: temporarily enable PCI device and read the hardware version
2712 * register. For now, assume it's okay. */
2716 /* Look for board matching PCI device. */
2717 static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev)
2721 for (i = 0; i < ARRAY_SIZE(pci230_boards); i++)
2722 if (pci230_match_pci_board(&pci230_boards[i], pci_dev))
2723 return &pci230_boards[i];
2727 /* Look for PCI device matching requested board name, bus and slot. */
2728 static struct pci_dev *pci230_find_pci(struct comedi_device *dev,
2731 const struct pci230_board *thisboard = comedi_board(dev);
2732 struct pci_dev *pci_dev = NULL;
2734 for_each_pci_dev(pci_dev) {
2735 /* Check vendor ID (same for all supported PCI boards). */
2736 if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
2738 /* If bus/slot specified, check them. */
2739 if ((bus || slot) &&
2740 (bus != pci_dev->bus->number ||
2741 slot != PCI_SLOT(pci_dev->devfn)))
2743 if (thisboard->id == PCI_DEVICE_ID_INVALID) {
2744 /* Wildcard board matches any supported PCI board. */
2745 const struct pci230_board *foundboard;
2747 foundboard = pci230_find_pci_board(pci_dev);
2748 if (foundboard == NULL)
2750 /* Replace wildcard board_ptr. */
2751 dev->board_ptr = foundboard;
2752 thisboard = comedi_board(dev);
2754 /* Need to match a specific board. */
2755 if (!pci230_match_pci_board(thisboard, pci_dev))
2758 /* Found a matching PCI device. */
2761 /* No matching PCI device found. */
2763 dev_err(dev->class_dev,
2764 "error! no %s found at pci %02x:%02x\n",
2765 thisboard->name, bus, slot);
2767 dev_err(dev->class_dev,
2768 "error! no %s found\n", thisboard->name);
2772 static int pci230_alloc_private(struct comedi_device *dev)
2774 struct pci230_private *devpriv;
2777 /* sets dev->private to allocated memory */
2778 err = alloc_private(dev, sizeof(struct pci230_private));
2780 dev_err(dev->class_dev, "error! out of memory!\n");
2783 devpriv = dev->private;
2784 spin_lock_init(&devpriv->isr_spinlock);
2785 spin_lock_init(&devpriv->res_spinlock);
2786 spin_lock_init(&devpriv->ai_stop_spinlock);
2787 spin_lock_init(&devpriv->ao_stop_spinlock);
2791 /* Common part of attach and attach_pci. */
2792 static int pci230_attach_common(struct comedi_device *dev,
2793 struct pci_dev *pci_dev)
2795 const struct pci230_board *thisboard = comedi_board(dev);
2796 struct pci230_private *devpriv = dev->private;
2797 struct comedi_subdevice *s;
2798 unsigned long iobase1, iobase2;
2799 /* PCI230's I/O spaces 1 and 2 respectively. */
2802 devpriv->pci_dev = pci_dev;
2803 dev->board_name = thisboard->name;
2804 /* Enable PCI device and reserve I/O spaces. */
2805 if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) {
2806 dev_err(dev->class_dev,
2807 "failed to enable PCI device and request regions\n");
2810 /* Read base addresses of the PCI230's two I/O regions from PCI
2811 * configuration register. */
2812 iobase1 = pci_resource_start(pci_dev, 2);
2813 iobase2 = pci_resource_start(pci_dev, 3);
2814 dev_dbg(dev->class_dev,
2815 "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
2816 dev->board_name, iobase1, iobase2);
2817 devpriv->iobase1 = iobase1;
2818 dev->iobase = iobase2;
2819 /* Read bits of DACCON register - only the output range. */
2820 devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
2821 /* Read hardware version register and set extended function register
2823 if (pci_resource_len(pci_dev, 3) >= 32) {
2824 unsigned short extfunc = 0;
2826 devpriv->hwver = inw(dev->iobase + PCI230P_HWVER);
2827 if (devpriv->hwver < thisboard->min_hwver) {
2828 dev_err(dev->class_dev,
2829 "%s - bad hardware version - got %u, need %u\n",
2830 dev->board_name, devpriv->hwver,
2831 thisboard->min_hwver);
2834 if (devpriv->hwver > 0) {
2835 if (!thisboard->have_dio) {
2836 /* No DIO ports. Route counters' external gates
2837 * to the EXTTRIG signal (PCI260+ pin 17).
2838 * (Otherwise, they would be routed to DIO
2839 * inputs PC0, PC1 and PC2 which don't exist
2841 extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
2843 if ((thisboard->ao_chans > 0)
2844 && (devpriv->hwver >= 2)) {
2845 /* Enable DAC FIFO functionality. */
2846 extfunc |= PCI230P2_EXTFUNC_DACFIFO;
2849 outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
2850 if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) {
2851 /* Temporarily enable DAC FIFO, reset it and disable
2852 * FIFO wraparound. */
2853 outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN
2854 | PCI230P2_DAC_FIFO_RESET,
2855 dev->iobase + PCI230_DACCON);
2856 /* Clear DAC FIFO channel enable register. */
2857 outw(0, dev->iobase + PCI230P2_DACEN);
2858 /* Disable DAC FIFO. */
2859 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
2862 /* Disable board's interrupts. */
2863 outb(0, devpriv->iobase1 + PCI230_INT_SCE);
2864 /* Set ADC to a reasonable state. */
2866 devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE
2867 | PCI230_ADC_IR_BIP;
2868 outw(1 << 0, dev->iobase + PCI230_ADCEN);
2869 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2870 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2871 dev->iobase + PCI230_ADCCON);
2872 /* Register the interrupt handler. */
2873 irq_hdl = request_irq(devpriv->pci_dev->irq, pci230_interrupt,
2874 IRQF_SHARED, "amplc_pci230", dev);
2876 dev_warn(dev->class_dev,
2877 "unable to register irq %u, commands will not be available\n",
2878 devpriv->pci_dev->irq);
2880 dev->irq = devpriv->pci_dev->irq;
2881 dev_dbg(dev->class_dev, "registered irq %u\n",
2882 devpriv->pci_dev->irq);
2885 * Allocate the subdevice structures. alloc_subdevice() is a
2886 * convenient macro defined in comedidev.h.
2888 if (alloc_subdevices(dev, 3) < 0)
2890 s = dev->subdevices + 0;
2891 /* analog input subdevice */
2892 s->type = COMEDI_SUBD_AI;
2893 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
2894 s->n_chan = thisboard->ai_chans;
2895 s->maxdata = (1 << thisboard->ai_bits) - 1;
2896 s->range_table = &pci230_ai_range;
2897 s->insn_read = &pci230_ai_rinsn;
2898 s->len_chanlist = 256; /* but there are restrictions. */
2899 /* Only register commands if the interrupt handler is installed. */
2901 dev->read_subdev = s;
2902 s->subdev_flags |= SDF_CMD_READ;
2903 s->do_cmd = &pci230_ai_cmd;
2904 s->do_cmdtest = &pci230_ai_cmdtest;
2905 s->cancel = pci230_ai_cancel;
2907 s = dev->subdevices + 1;
2908 /* analog output subdevice */
2909 if (thisboard->ao_chans > 0) {
2910 s->type = COMEDI_SUBD_AO;
2911 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
2912 s->n_chan = thisboard->ao_chans;
2913 s->maxdata = (1 << thisboard->ao_bits) - 1;
2914 s->range_table = &pci230_ao_range;
2915 s->insn_write = &pci230_ao_winsn;
2916 s->insn_read = &pci230_ao_rinsn;
2917 s->len_chanlist = thisboard->ao_chans;
2918 /* Only register commands if the interrupt handler is
2921 dev->write_subdev = s;
2922 s->subdev_flags |= SDF_CMD_WRITE;
2923 s->do_cmd = &pci230_ao_cmd;
2924 s->do_cmdtest = &pci230_ao_cmdtest;
2925 s->cancel = pci230_ao_cancel;
2928 s->type = COMEDI_SUBD_UNUSED;
2930 s = dev->subdevices + 2;
2931 /* digital i/o subdevice */
2932 if (thisboard->have_dio) {
2933 rc = subdev_8255_init(dev, s, NULL,
2934 (devpriv->iobase1 + PCI230_PPI_X_BASE));
2938 s->type = COMEDI_SUBD_UNUSED;
2940 dev_info(dev->class_dev, "attached\n");
2944 static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2946 const struct pci230_board *thisboard = comedi_board(dev);
2947 struct pci_dev *pci_dev;
2950 dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n",
2951 thisboard->name, it->options[0], it->options[1]);
2952 rc = pci230_alloc_private(dev); /* sets dev->private */
2956 pci_dev = pci230_find_pci(dev, it->options[0], it->options[1]);
2959 return pci230_attach_common(dev, pci_dev);
2962 static int __devinit pci230_attach_pci(struct comedi_device *dev,
2963 struct pci_dev *pci_dev)
2967 dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
2969 rc = pci230_alloc_private(dev); /* sets dev->private */
2972 dev->board_ptr = pci230_find_pci_board(pci_dev);
2973 if (dev->board_ptr == NULL) {
2974 dev_err(dev->class_dev,
2975 "amplc_pci230: BUG! cannot determine board type!\n");
2978 return pci230_attach_common(dev, pci_dev);
2981 static void pci230_detach(struct comedi_device *dev)
2983 const struct pci230_board *thisboard = comedi_board(dev);
2984 struct pci230_private *devpriv = dev->private;
2986 if (dev->subdevices && thisboard->have_dio)
2987 subdev_8255_cleanup(dev, dev->subdevices + 2);
2989 free_irq(dev->irq, dev);
2991 if (devpriv->pci_dev) {
2993 comedi_pci_disable(devpriv->pci_dev);
2994 pci_dev_put(devpriv->pci_dev);
2999 static struct comedi_driver amplc_pci230_driver = {
3000 .driver_name = "amplc_pci230",
3001 .module = THIS_MODULE,
3002 .attach = pci230_attach,
3003 .attach_pci = pci230_attach_pci,
3004 .detach = pci230_detach,
3005 .board_name = &pci230_boards[0].name,
3006 .offset = sizeof(pci230_boards[0]),
3007 .num_names = ARRAY_SIZE(pci230_boards),
3010 static int __devinit amplc_pci230_pci_probe(struct pci_dev *dev,
3011 const struct pci_device_id *ent)
3013 return comedi_pci_auto_config(dev, &lc_pci230_driver);
3016 static void __devexit amplc_pci230_pci_remove(struct pci_dev *dev)
3018 comedi_pci_auto_unconfig(dev);
3021 static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = {
3022 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
3023 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
3026 MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table);
3028 static struct pci_driver amplc_pci230_pci_driver = {
3029 .name = "amplc_pci230",
3030 .id_table = amplc_pci230_pci_table,
3031 .probe = amplc_pci230_pci_probe,
3032 .remove = __devexit_p(amplc_pci230_pci_remove)
3034 module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
3036 MODULE_AUTHOR("Comedi http://www.comedi.org");
3037 MODULE_DESCRIPTION("Comedi low-level driver");
3038 MODULE_LICENSE("GPL");