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.
22 * Driver: amplc_pci230
23 * Description: Amplicon PCI230, PCI260 Multifunction I/O boards
24 * Author: Allan Willcox <allanwillcox@ozemail.com.au>,
25 * Steve D Sharples <steve.sharples@nottingham.ac.uk>,
26 * Ian Abbott <abbotti@mev.co.uk>
27 * Updated: Mon, 01 Sep 2014 10:09:16 +0000
28 * Devices: [Amplicon] PCI230 (amplc_pci230), PCI230+, PCI260, PCI260+
31 * Configuration options:
34 * Manual configuration of PCI cards is not supported; they are configured
37 * The PCI230+ and PCI260+ have the same PCI device IDs as the PCI230 and
38 * PCI260, but can be distinguished by the size of the PCI regions. A
39 * card will be configured as a "+" model if detected as such.
52 * The AI subdevice has 16 single-ended channels or 8 differential
55 * The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and
56 * PCI260+ cards have 16-bit resolution.
58 * For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
59 * inputs 14 and 15 for channel 7). If the card is physically a PCI230
60 * or PCI260 then it actually uses a "pseudo-differential" mode where the
61 * inputs are sampled a few microseconds apart. The PCI230+ and PCI260+
62 * use true differential sampling. Another difference is that if the
63 * card is physically a PCI230 or PCI260, the inverting input is 2N,
64 * whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a
65 * PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
66 * PCI260+) and differential mode is used, the differential inputs need
67 * to be physically swapped on the connector.
69 * The following input ranges are supported:
74 * 3 => [-1.25, +1.25] V
81 * +=========+==============+===========+============+==========+
82 * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
83 * +=========+==============+===========+============+==========+
84 * |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
85 * |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT|
87 * | |--------------|-----------| | |
88 * | | TRIG_TIMER(1)|TRIG_TIMER | | |
89 * | | TRIG_EXT(2) | | | |
90 * | | TRIG_INT | | | |
91 * +---------+--------------+-----------+------------+----------+
93 * Note 1: If AI command and AO command are used simultaneously, only
94 * one may have scan_begin_src == TRIG_TIMER.
96 * Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
97 * DIO channel 16 (pin 49) which will need to be configured as
98 * a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input
99 * (pin 17) is used instead. For PCI230, scan_begin_src ==
100 * TRIG_EXT is not supported. The trigger is a rising edge
103 * Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
104 * (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The
105 * convert_arg value is interpreted as follows:
107 * convert_arg == (CR_EDGE | 0) => rising edge
108 * convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
109 * convert_arg == 0 => falling edge (backwards compatibility)
110 * convert_arg == 1 => rising edge (backwards compatibility)
112 * All entries in the channel list must use the same analogue reference.
113 * If the analogue reference is not AREF_DIFF (not differential) each
114 * pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
115 * input range. The input ranges used in the sequence must be all
116 * bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel
117 * sequence must consist of 1 or more identical subsequences. Within the
118 * subsequence, channels must be in ascending order with no repeated
119 * channels. For example, the following sequences are valid: 0 1 2 3
120 * (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
121 * subsequence), 1 1 1 1 (repeated valid subsequence). The following
122 * sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
123 * (incompletely repeated subsequence). Some versions of the PCI230+ and
124 * PCI260+ have a bug that requires a subsequence longer than one entry
125 * long to include channel 0.
129 * The AO subdevice has 2 channels with 12-bit resolution.
130 * The following output ranges are supported:
136 * +=========+==============+===========+============+==========+
137 * |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
138 * +=========+==============+===========+============+==========+
139 * |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE |
140 * | | TRIG_EXT(2) | | |TRIG_COUNT|
141 * | | TRIG_INT | | | |
142 * +---------+--------------+-----------+------------+----------+
144 * Note 1: If AI command and AO command are used simultaneously, only
145 * one may have scan_begin_src == TRIG_TIMER.
147 * Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
148 * configured as a PCI230+ and is only supported on later
149 * versions of the card. As a card configured as a PCI230+ is
150 * not guaranteed to support external triggering, please consider
151 * this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK
152 * input (PCI230+ pin 25). Triggering will be on the rising edge
153 * unless the CR_INVERT flag is set in scan_begin_arg.
155 * The channels in the channel sequence must be in ascending order with
156 * no repeats. All entries in the channel sequence must use the same
161 * The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO
162 * channels are configurable as inputs or outputs in four groups:
164 * Port A - channels 0 to 7
165 * Port B - channels 8 to 15
166 * Port CL - channels 16 to 19
167 * Port CH - channels 20 to 23
169 * Only mode 0 of the 8255 chip is supported.
171 * Bit 0 of port C (DIO channel 16) is also used as an external scan
172 * trigger input for AI commands on PCI230 and PCI230+, so would need to
173 * be configured as an input to use it for that purpose.
177 * Extra triggered scan functionality, interrupt bug-fix added by Steve
178 * Sharples. Support for PCI230+/260+, more triggered scan functionality,
179 * and workarounds for (or detection of) various hardware problems added
183 #include <linux/module.h>
184 #include <linux/pci.h>
185 #include <linux/delay.h>
186 #include <linux/interrupt.h>
188 #include "../comedidev.h"
190 #include "comedi_fc.h"
195 * PCI230 PCI configuration register information
197 #define PCI_DEVICE_ID_PCI230 0x0000
198 #define PCI_DEVICE_ID_PCI260 0x0006
201 * PCI230 i/o space 1 registers.
203 #define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */
204 #define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */
205 #define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */
206 #define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */
207 #define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */
208 #define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */
209 #define PCI230_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
210 #define PCI230_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
211 #define PCI230_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
212 #define PCI230_Z2_CTC 0x17 /* 82C54 counter/timer control word */
213 #define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */
214 #define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */
215 #define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */
216 #define PCI230_INT_STAT 0x1E /* Interrupt status (r) */
219 * PCI230 i/o space 2 registers.
221 #define PCI230_DACCON 0x00 /* DAC control */
222 #define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */
223 #define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */
224 #define PCI230_ADCDATA 0x08 /* ADC data (r) */
225 #define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */
226 #define PCI230_ADCCON 0x0A /* ADC control */
227 #define PCI230_ADCEN 0x0C /* ADC channel enable bits */
228 #define PCI230_ADCG 0x0E /* ADC gain control bits */
229 /* PCI230+ i/o space 2 additional registers. */
230 #define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */
231 #define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */
232 #define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */
233 #define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */
234 #define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */
235 #define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */
236 #define PCI230P_EXTFUNC 0x1C /* Extended functions */
237 #define PCI230P_HWVER 0x1E /* Hardware version (r) */
238 /* PCI230+ hardware version 2 onwards. */
239 #define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */
240 #define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */
241 #define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */
244 * DACCON read-write values.
246 #define PCI230_DAC_OR_UNI (0 << 0) /* Output range unipolar */
247 #define PCI230_DAC_OR_BIP (1 << 0) /* Output range bipolar */
248 #define PCI230_DAC_OR_MASK (1 << 0)
250 * The following applies only if DAC FIFO support is enabled in the EXTFUNC
251 * register (and only for PCI230+ hardware version 2 onwards).
253 #define PCI230P2_DAC_FIFO_EN (1 << 8) /* FIFO enable */
255 * The following apply only if the DAC FIFO is enabled (and only for PCI230+
256 * hardware version 2 onwards).
258 #define PCI230P2_DAC_TRIG_NONE (0 << 2) /* No trigger */
259 #define PCI230P2_DAC_TRIG_SW (1 << 2) /* Software trigger trigger */
260 #define PCI230P2_DAC_TRIG_EXTP (2 << 2) /* EXTTRIG +ve edge trigger */
261 #define PCI230P2_DAC_TRIG_EXTN (3 << 2) /* EXTTRIG -ve edge trigger */
262 #define PCI230P2_DAC_TRIG_Z2CT0 (4 << 2) /* CT0-OUT +ve edge trigger */
263 #define PCI230P2_DAC_TRIG_Z2CT1 (5 << 2) /* CT1-OUT +ve edge trigger */
264 #define PCI230P2_DAC_TRIG_Z2CT2 (6 << 2) /* CT2-OUT +ve edge trigger */
265 #define PCI230P2_DAC_TRIG_MASK (7 << 2)
266 #define PCI230P2_DAC_FIFO_WRAP (1 << 7) /* FIFO wraparound mode */
267 #define PCI230P2_DAC_INT_FIFO_EMPTY (0 << 9) /* FIFO interrupt empty */
268 #define PCI230P2_DAC_INT_FIFO_NEMPTY (1 << 9)
269 #define PCI230P2_DAC_INT_FIFO_NHALF (2 << 9) /* FIFO intr not half full */
270 #define PCI230P2_DAC_INT_FIFO_HALF (3 << 9)
271 #define PCI230P2_DAC_INT_FIFO_NFULL (4 << 9) /* FIFO interrupt not full */
272 #define PCI230P2_DAC_INT_FIFO_FULL (5 << 9)
273 #define PCI230P2_DAC_INT_FIFO_MASK (7 << 9)
276 * DACCON read-only values.
278 #define PCI230_DAC_BUSY (1 << 1) /* DAC busy. */
280 * The following apply only if the DAC FIFO is enabled (and only for PCI230+
281 * hardware version 2 onwards).
283 #define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1 << 5) /* Underrun error */
284 #define PCI230P2_DAC_FIFO_EMPTY (1 << 13) /* FIFO empty */
285 #define PCI230P2_DAC_FIFO_FULL (1 << 14) /* FIFO full */
286 #define PCI230P2_DAC_FIFO_HALF (1 << 15) /* FIFO half full */
289 * 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).
295 #define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1 << 5) /* Clear underrun */
296 #define PCI230P2_DAC_FIFO_RESET (1 << 12) /* FIFO reset */
299 * PCI230+ hardware version 2 DAC FIFO levels.
301 #define PCI230P2_DAC_FIFOLEVEL_HALF 512
302 #define PCI230P2_DAC_FIFOLEVEL_FULL 1024
303 /* Free space in DAC FIFO. */
304 #define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL
305 #define PCI230P2_DAC_FIFOROOM_ONETOHALF \
306 (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
307 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1
308 #define PCI230P2_DAC_FIFOROOM_FULL 0
311 * ADCCON read/write values.
313 #define PCI230_ADC_TRIG_NONE (0 << 0) /* No trigger */
314 #define PCI230_ADC_TRIG_SW (1 << 0) /* Software trigger trigger */
315 #define PCI230_ADC_TRIG_EXTP (2 << 0) /* EXTTRIG +ve edge trigger */
316 #define PCI230_ADC_TRIG_EXTN (3 << 0) /* EXTTRIG -ve edge trigger */
317 #define PCI230_ADC_TRIG_Z2CT0 (4 << 0) /* CT0-OUT +ve edge trigger */
318 #define PCI230_ADC_TRIG_Z2CT1 (5 << 0) /* CT1-OUT +ve edge trigger */
319 #define PCI230_ADC_TRIG_Z2CT2 (6 << 0) /* CT2-OUT +ve edge trigger */
320 #define PCI230_ADC_TRIG_MASK (7 << 0)
321 #define PCI230_ADC_IR_UNI (0 << 3) /* Input range unipolar */
322 #define PCI230_ADC_IR_BIP (1 << 3) /* Input range bipolar */
323 #define PCI230_ADC_IR_MASK (1 << 3)
324 #define PCI230_ADC_IM_SE (0 << 4) /* Input mode single ended */
325 #define PCI230_ADC_IM_DIF (1 << 4) /* Input mode differential */
326 #define PCI230_ADC_IM_MASK (1 << 4)
327 #define PCI230_ADC_FIFO_EN (1 << 8) /* FIFO enable */
328 #define PCI230_ADC_INT_FIFO_EMPTY (0 << 9)
329 #define PCI230_ADC_INT_FIFO_NEMPTY (1 << 9) /* FIFO interrupt not empty */
330 #define PCI230_ADC_INT_FIFO_NHALF (2 << 9)
331 #define PCI230_ADC_INT_FIFO_HALF (3 << 9) /* FIFO interrupt half full */
332 #define PCI230_ADC_INT_FIFO_NFULL (4 << 9)
333 #define PCI230_ADC_INT_FIFO_FULL (5 << 9) /* FIFO interrupt full */
334 #define PCI230P_ADC_INT_FIFO_THRESH (7 << 9) /* FIFO interrupt threshold */
335 #define PCI230_ADC_INT_FIFO_MASK (7 << 9)
338 * ADCCON write-only, transient values.
340 #define PCI230_ADC_FIFO_RESET (1 << 12) /* FIFO reset */
341 #define PCI230_ADC_GLOB_RESET (1 << 13) /* Global reset */
344 * ADCCON read-only values.
346 #define PCI230_ADC_BUSY (1 << 15) /* ADC busy */
347 #define PCI230_ADC_FIFO_EMPTY (1 << 12) /* FIFO empty */
348 #define PCI230_ADC_FIFO_FULL (1 << 13) /* FIFO full */
349 #define PCI230_ADC_FIFO_HALF (1 << 14) /* FIFO half full */
350 #define PCI230_ADC_FIFO_FULL_LATCHED (1 << 5) /* FIFO overrun occurred */
353 * PCI230 ADC FIFO levels.
355 #define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */
356 #define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */
359 * PCI230+ EXTFUNC values.
361 /* Route EXTTRIG pin to external gate inputs. */
362 #define PCI230P_EXTFUNC_GAT_EXTTRIG (1 << 0)
363 /* PCI230+ hardware version 2 values. */
364 /* Allow DAC FIFO to be enabled. */
365 #define PCI230P2_EXTFUNC_DACFIFO (1 << 1)
368 * Counter/timer clock input configuration sources.
370 #define CLK_CLK 0 /* reserved (channel-specific clock) */
371 #define CLK_10MHZ 1 /* internal 10 MHz clock */
372 #define CLK_1MHZ 2 /* internal 1 MHz clock */
373 #define CLK_100KHZ 3 /* internal 100 kHz clock */
374 #define CLK_10KHZ 4 /* internal 10 kHz clock */
375 #define CLK_1KHZ 5 /* internal 1 kHz clock */
376 #define CLK_OUTNM1 6 /* output of channel-1 modulo total */
377 #define CLK_EXT 7 /* external clock */
378 /* Macro to construct clock input configuration register value. */
379 #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
380 /* Timebases in ns. */
381 #define TIMEBASE_10MHZ 100
382 #define TIMEBASE_1MHZ 1000
383 #define TIMEBASE_100KHZ 10000
384 #define TIMEBASE_10KHZ 100000
385 #define TIMEBASE_1KHZ 1000000
388 * Counter/timer gate input configuration sources.
390 #define GAT_VCC 0 /* VCC (i.e. enabled) */
391 #define GAT_GND 1 /* GND (i.e. disabled) */
392 #define GAT_EXT 2 /* external gate input (PPCn on PCI230) */
393 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
394 /* Macro to construct gate input configuration register value. */
395 #define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
398 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
400 * Channel's Channel's
401 * clock input gate input
402 * Channel CLK_OUTNM1 GAT_NOUTNM2
403 * ------- ---------- -----------
404 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
405 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
406 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
410 * Interrupt enables/status register values.
412 #define PCI230_INT_DISABLE 0
413 #define PCI230_INT_PPI_C0 (1 << 0)
414 #define PCI230_INT_PPI_C3 (1 << 1)
415 #define PCI230_INT_ADC (1 << 2)
416 #define PCI230_INT_ZCLK_CT1 (1 << 5)
417 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
418 #define PCI230P2_INT_DAC (1 << 4)
421 * (Potentially) shared resources and their owners
424 RES_Z2CT0 = (1U << 0), /* Z2-CT0 */
425 RES_Z2CT1 = (1U << 1), /* Z2-CT1 */
426 RES_Z2CT2 = (1U << 2) /* Z2-CT2 */
430 OWNER_AICMD, /* Owned by AI command */
431 OWNER_AOCMD, /* Owned by AO command */
432 NUM_OWNERS /* Number of owners */
439 /* Combine old and new bits. */
440 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
442 /* Current CPU. XXX should this be hard_smp_processor_id()? */
443 #define THISCPU smp_processor_id()
446 * Board descriptions for the two boards supported.
449 struct pci230_board {
452 unsigned char ai_bits;
453 unsigned char ao_bits;
454 unsigned char min_hwver; /* Minimum hardware version supported. */
458 static const struct pci230_board pci230_boards[] = {
461 .id = PCI_DEVICE_ID_PCI230,
469 .id = PCI_DEVICE_ID_PCI260,
475 .id = PCI_DEVICE_ID_PCI230,
482 .id = PCI_DEVICE_ID_PCI260,
487 struct pci230_private {
488 spinlock_t isr_spinlock; /* Interrupt spin lock */
489 spinlock_t res_spinlock; /* Shared resources spin lock */
490 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
491 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
492 unsigned long daqio; /* PCI230's DAQ I/O space */
493 int intr_cpuid; /* ID of CPU running ISR */
494 unsigned short hwver; /* Hardware version (for '+' models) */
495 unsigned short adccon; /* ADCCON register value */
496 unsigned short daccon; /* DACCON register value */
497 unsigned short adcfifothresh; /* ADC FIFO threshold (PCI230+/260+) */
498 unsigned short adcg; /* ADCG register value */
499 unsigned char ier; /* Interrupt enable bits */
500 unsigned char res_owned[NUM_OWNERS]; /* Owned resources */
501 bool intr_running:1; /* Flag set in interrupt routine */
502 bool ai_bipolar:1; /* Flag AI range is bipolar */
503 bool ao_bipolar:1; /* Flag AO range is bipolar */
504 bool ai_cmd_started:1; /* Flag AI command started */
505 bool ao_cmd_started:1; /* Flag AO command started */
508 /* PCI230 clock source periods in ns */
509 static const unsigned int pci230_timebase[8] = {
510 [CLK_10MHZ] = TIMEBASE_10MHZ,
511 [CLK_1MHZ] = TIMEBASE_1MHZ,
512 [CLK_100KHZ] = TIMEBASE_100KHZ,
513 [CLK_10KHZ] = TIMEBASE_10KHZ,
514 [CLK_1KHZ] = TIMEBASE_1KHZ,
517 /* PCI230 analogue input range table */
518 static const struct comedi_lrange pci230_ai_range = {
530 /* PCI230 analogue gain bits for each input range. */
531 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
533 /* PCI230 analogue output range table */
534 static const struct comedi_lrange pci230_ao_range = {
541 static unsigned short pci230_ai_read(struct comedi_device *dev)
543 const struct pci230_board *thisboard = dev->board_ptr;
544 struct pci230_private *devpriv = dev->private;
548 data = inw(devpriv->daqio + PCI230_ADCDATA);
550 * PCI230 is 12 bit - stored in upper bits of 16 bit register
551 * (lower four bits reserved for expansion). PCI230+ is 16 bit AI.
553 * If a bipolar range was specified, mangle it
554 * (twos complement->straight binary).
556 if (devpriv->ai_bipolar)
558 data >>= (16 - thisboard->ai_bits);
562 static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
563 unsigned short datum)
565 const struct pci230_board *thisboard = dev->board_ptr;
566 struct pci230_private *devpriv = dev->private;
569 * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
570 * four bits reserved for expansion). PCI230+ is also 12 bit AO.
572 datum <<= (16 - thisboard->ao_bits);
574 * If a bipolar range was specified, mangle it
575 * (straight binary->twos complement).
577 if (devpriv->ao_bipolar)
582 static void pci230_ao_write_nofifo(struct comedi_device *dev,
583 unsigned short datum, unsigned int chan)
585 struct pci230_private *devpriv = dev->private;
587 /* Write mangled datum to appropriate DACOUT register. */
588 outw(pci230_ao_mangle_datum(dev, datum),
589 devpriv->daqio + ((chan == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
592 static void pci230_ao_write_fifo(struct comedi_device *dev,
593 unsigned short datum, unsigned int chan)
595 struct pci230_private *devpriv = dev->private;
597 /* Write mangled datum to appropriate DACDATA register. */
598 outw(pci230_ao_mangle_datum(dev, datum),
599 devpriv->daqio + PCI230P2_DACDATA);
602 static bool pci230_claim_shared(struct comedi_device *dev,
603 unsigned char res_mask, unsigned int owner)
605 struct pci230_private *devpriv = dev->private;
607 unsigned long irqflags;
609 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
610 for (o = 0; o < NUM_OWNERS; o++) {
613 if (devpriv->res_owned[o] & res_mask) {
614 spin_unlock_irqrestore(&devpriv->res_spinlock,
619 devpriv->res_owned[owner] |= res_mask;
620 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
624 static void pci230_release_shared(struct comedi_device *dev,
625 unsigned char res_mask, unsigned int owner)
627 struct pci230_private *devpriv = dev->private;
628 unsigned long irqflags;
630 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
631 devpriv->res_owned[owner] &= ~res_mask;
632 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
635 static void pci230_release_all_resources(struct comedi_device *dev,
638 pci230_release_shared(dev, (unsigned char)~0, owner);
641 static unsigned int pci230_divide_ns(uint64_t ns, unsigned int timebase,
648 rem = do_div(div, timebase);
649 switch (flags & CMDF_ROUND_MASK) {
651 case CMDF_ROUND_NEAREST:
652 div += (rem + (timebase / 2)) / timebase;
654 case CMDF_ROUND_DOWN:
657 div += (rem + timebase - 1) / timebase;
660 return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
664 * Given desired period in ns, returns the required internal clock source
665 * and gets the initial count.
667 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
670 unsigned int clk_src, cnt;
672 for (clk_src = CLK_10MHZ;; clk_src++) {
673 cnt = pci230_divide_ns(ns, pci230_timebase[clk_src], flags);
674 if (cnt <= 65536 || clk_src == CLK_1KHZ)
681 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int flags)
684 unsigned int clk_src;
686 clk_src = pci230_choose_clk_count(*ns, &count, flags);
687 *ns = count * pci230_timebase[clk_src];
690 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
691 unsigned int mode, uint64_t ns,
694 unsigned int clk_src;
698 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, mode);
699 /* Determine clock source and count. */
700 clk_src = pci230_choose_clk_count(ns, &count, flags);
701 /* Program clock source. */
702 outb(CLK_CONFIG(ct, clk_src), dev->iobase + PCI230_ZCLK_SCE);
703 /* Set initial count. */
707 i8254_write(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, count);
710 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
712 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, I8254_MODE1);
713 /* Counter ct, 8254 mode 1, initial count not written. */
716 static int pci230_ai_eoc(struct comedi_device *dev,
717 struct comedi_subdevice *s,
718 struct comedi_insn *insn,
719 unsigned long context)
721 struct pci230_private *devpriv = dev->private;
724 status = inw(devpriv->daqio + PCI230_ADCCON);
725 if ((status & PCI230_ADC_FIFO_EMPTY) == 0)
730 static int pci230_ai_insn_read(struct comedi_device *dev,
731 struct comedi_subdevice *s,
732 struct comedi_insn *insn, unsigned int *data)
734 struct pci230_private *devpriv = dev->private;
736 unsigned int chan, range, aref;
737 unsigned int gainshift;
738 unsigned short adccon, adcen;
741 /* Unpack channel and range. */
742 chan = CR_CHAN(insn->chanspec);
743 range = CR_RANGE(insn->chanspec);
744 aref = CR_AREF(insn->chanspec);
745 if (aref == AREF_DIFF) {
747 if (chan >= s->n_chan / 2) {
748 dev_dbg(dev->class_dev,
749 "%s: differential channel number out of range 0 to %u\n",
750 __func__, (s->n_chan / 2) - 1);
756 * Use Z2-CT2 as a conversion trigger instead of the built-in
757 * software trigger, as otherwise triggering of differential channels
758 * doesn't work properly for some versions of PCI230/260. Also set
759 * FIFO mode because the ADC busy bit only works for software triggers.
761 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
762 /* Set Z2-CT2 output low to avoid any false triggers. */
763 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
764 devpriv->ai_bipolar = comedi_range_is_bipolar(s, range);
765 if (aref == AREF_DIFF) {
767 gainshift = chan * 2;
768 if (devpriv->hwver == 0) {
770 * Original PCI230/260 expects both inputs of the
771 * differential channel to be enabled.
773 adcen = 3 << gainshift;
776 * PCI230+/260+ expects only one input of the
777 * differential channel to be enabled.
779 adcen = 1 << gainshift;
781 adccon |= PCI230_ADC_IM_DIF;
785 gainshift = chan & ~1;
786 adccon |= PCI230_ADC_IM_SE;
788 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) |
789 (pci230_ai_gain[range] << gainshift);
790 if (devpriv->ai_bipolar)
791 adccon |= PCI230_ADC_IR_BIP;
793 adccon |= PCI230_ADC_IR_UNI;
796 * Enable only this channel in the scan list - otherwise by default
797 * we'll get one sample from each channel.
799 outw(adcen, devpriv->daqio + PCI230_ADCEN);
801 /* Set gain for channel. */
802 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
804 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
805 devpriv->adccon = adccon;
806 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
808 /* Convert n samples */
809 for (n = 0; n < insn->n; n++) {
811 * Trigger conversion by toggling Z2-CT2 output
812 * (finish with output high).
814 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0,
816 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0,
819 /* wait for conversion to end */
820 ret = comedi_timeout(dev, s, insn, pci230_ai_eoc, 0);
825 data[n] = pci230_ai_read(dev);
828 /* return the number of samples read/written */
832 static int pci230_ao_insn_write(struct comedi_device *dev,
833 struct comedi_subdevice *s,
834 struct comedi_insn *insn,
837 struct pci230_private *devpriv = dev->private;
838 unsigned int chan = CR_CHAN(insn->chanspec);
839 unsigned int range = CR_RANGE(insn->chanspec);
840 unsigned int val = s->readback[chan];
844 * Set range - see analogue output range table; 0 => unipolar 10V,
845 * 1 => bipolar +/-10V range scale
847 devpriv->ao_bipolar = comedi_range_is_bipolar(s, range);
848 outw(range, devpriv->daqio + PCI230_DACCON);
850 for (i = 0; i < insn->n; i++) {
852 pci230_ao_write_nofifo(dev, val, chan);
854 s->readback[chan] = val;
859 static int pci230_ao_check_chanlist(struct comedi_device *dev,
860 struct comedi_subdevice *s,
861 struct comedi_cmd *cmd)
863 unsigned int prev_chan = CR_CHAN(cmd->chanlist[0]);
864 unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
867 for (i = 1; i < cmd->chanlist_len; i++) {
868 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
869 unsigned int range = CR_RANGE(cmd->chanlist[i]);
871 if (chan < prev_chan) {
872 dev_dbg(dev->class_dev,
873 "%s: channel numbers must increase\n",
878 if (range != range0) {
879 dev_dbg(dev->class_dev,
880 "%s: channels must have the same range\n",
891 static int pci230_ao_cmdtest(struct comedi_device *dev,
892 struct comedi_subdevice *s, struct comedi_cmd *cmd)
894 const struct pci230_board *thisboard = dev->board_ptr;
895 struct pci230_private *devpriv = dev->private;
899 /* Step 1 : check if triggers are trivially valid */
901 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
903 tmp = TRIG_TIMER | TRIG_INT;
904 if (thisboard->min_hwver > 0 && devpriv->hwver >= 2) {
906 * For PCI230+ hardware version 2 onwards, allow external
907 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
909 * FIXME: The permitted scan_begin_src values shouldn't depend
910 * on devpriv->hwver (the detected card's actual hardware
911 * version). They should only depend on thisboard->min_hwver
912 * (the static capabilities of the configured card). To fix
913 * it, a new card model, e.g. "pci230+2" would have to be
914 * defined with min_hwver set to 2. It doesn't seem worth it
915 * for this alone. At the moment, please consider
916 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
921 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
923 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
924 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
925 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
930 /* Step 2a : make sure trigger sources are unique */
932 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
933 err |= cfc_check_trigger_is_unique(cmd->stop_src);
935 /* Step 2b : and mutually compatible */
940 /* Step 3: check if arguments are trivially valid */
942 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
944 #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */
946 * Comedi limit due to unsigned int cmd. Driver limit =
947 * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s
949 #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */
951 switch (cmd->scan_begin_src) {
953 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
955 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
960 * External trigger - for PCI230+ hardware version 2 onwards.
962 /* Trigger number must be 0. */
963 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
964 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
969 * The only flags allowed are CR_EDGE and CR_INVERT.
970 * The CR_EDGE flag is ignored.
972 if (cmd->scan_begin_arg & CR_FLAGS_MASK &
973 ~(CR_EDGE | CR_INVERT)) {
974 cmd->scan_begin_arg =
975 COMBINE(cmd->scan_begin_arg, 0,
976 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
981 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
985 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
987 if (cmd->stop_src == TRIG_COUNT)
988 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
990 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
995 /* Step 4: fix up any arguments */
997 if (cmd->scan_begin_src == TRIG_TIMER) {
998 tmp = cmd->scan_begin_arg;
999 pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags);
1000 if (tmp != cmd->scan_begin_arg)
1007 /* Step 5: check channel list if it exists */
1008 if (cmd->chanlist && cmd->chanlist_len > 0)
1009 err |= pci230_ao_check_chanlist(dev, s, cmd);
1017 static void pci230_ao_stop(struct comedi_device *dev,
1018 struct comedi_subdevice *s)
1020 struct pci230_private *devpriv = dev->private;
1021 unsigned long irqflags;
1022 unsigned char intsrc;
1024 struct comedi_cmd *cmd;
1026 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1027 started = devpriv->ao_cmd_started;
1028 devpriv->ao_cmd_started = false;
1029 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1032 cmd = &s->async->cmd;
1033 if (cmd->scan_begin_src == TRIG_TIMER) {
1034 /* Stop scan rate generator. */
1035 pci230_cancel_ct(dev, 1);
1037 /* Determine interrupt source. */
1038 if (devpriv->hwver < 2) {
1039 /* Not using DAC FIFO. Using CT1 interrupt. */
1040 intsrc = PCI230_INT_ZCLK_CT1;
1042 /* Using DAC FIFO interrupt. */
1043 intsrc = PCI230P2_INT_DAC;
1046 * Disable interrupt and wait for interrupt routine to finish running
1047 * unless we are called from the interrupt routine.
1049 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1050 devpriv->ier &= ~intsrc;
1051 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
1052 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1053 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1055 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1056 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1057 if (devpriv->hwver >= 2) {
1059 * Using DAC FIFO. Reset FIFO, clear underrun error,
1062 devpriv->daccon &= PCI230_DAC_OR_MASK;
1063 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET |
1064 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
1065 devpriv->daqio + PCI230_DACCON);
1067 /* Release resources. */
1068 pci230_release_all_resources(dev, OWNER_AOCMD);
1071 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
1072 struct comedi_subdevice *s)
1074 struct comedi_async *async = s->async;
1075 struct comedi_cmd *cmd = &async->cmd;
1076 unsigned short data;
1079 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
1082 for (i = 0; i < cmd->chanlist_len; i++) {
1083 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
1085 if (!comedi_buf_read_samples(s, &data, 1)) {
1086 async->events |= COMEDI_CB_OVERFLOW;
1089 pci230_ao_write_nofifo(dev, data, chan);
1090 s->readback[chan] = data;
1093 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
1094 async->events |= COMEDI_CB_EOA;
1098 * Loads DAC FIFO (if using it) from buffer.
1099 * Returns false if AO finished due to completion or error, true if still going.
1101 static bool pci230_handle_ao_fifo(struct comedi_device *dev,
1102 struct comedi_subdevice *s)
1104 struct pci230_private *devpriv = dev->private;
1105 struct comedi_async *async = s->async;
1106 struct comedi_cmd *cmd = &async->cmd;
1107 unsigned int num_scans = comedi_nscans_left(s, 0);
1109 unsigned short dacstat;
1111 unsigned int events = 0;
1113 /* Get DAC FIFO status. */
1114 dacstat = inw(devpriv->daqio + PCI230_DACCON);
1116 if (cmd->stop_src == TRIG_COUNT && num_scans == 0)
1117 events |= COMEDI_CB_EOA;
1120 /* Check for FIFO underrun. */
1121 if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
1122 dev_err(dev->class_dev, "AO FIFO underrun\n");
1123 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1126 * Check for buffer underrun if FIFO less than half full
1127 * (otherwise there will be loads of "DAC FIFO not half full"
1130 if (num_scans == 0 &&
1131 (dacstat & PCI230P2_DAC_FIFO_HALF) == 0) {
1132 dev_err(dev->class_dev, "AO buffer underrun\n");
1133 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1137 /* Determine how much room is in the FIFO (in samples). */
1138 if (dacstat & PCI230P2_DAC_FIFO_FULL)
1139 room = PCI230P2_DAC_FIFOROOM_FULL;
1140 else if (dacstat & PCI230P2_DAC_FIFO_HALF)
1141 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
1142 else if (dacstat & PCI230P2_DAC_FIFO_EMPTY)
1143 room = PCI230P2_DAC_FIFOROOM_EMPTY;
1145 room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
1146 /* Convert room to number of scans that can be added. */
1147 room /= cmd->chanlist_len;
1148 /* Determine number of scans to process. */
1149 if (num_scans > room)
1151 /* Process scans. */
1152 for (n = 0; n < num_scans; n++) {
1153 for (i = 0; i < cmd->chanlist_len; i++) {
1154 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
1155 unsigned short datum;
1157 comedi_buf_read_samples(s, &datum, 1);
1158 pci230_ao_write_fifo(dev, datum, chan);
1159 s->readback[chan] = datum;
1163 if (cmd->stop_src == TRIG_COUNT &&
1164 async->scans_done >= cmd->stop_arg) {
1166 * All data for the command has been written
1167 * to FIFO. Set FIFO interrupt trigger level
1170 devpriv->daccon &= ~PCI230P2_DAC_INT_FIFO_MASK;
1171 devpriv->daccon |= PCI230P2_DAC_INT_FIFO_EMPTY;
1172 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
1174 /* Check if FIFO underrun occurred while writing to FIFO. */
1175 dacstat = inw(devpriv->daqio + PCI230_DACCON);
1176 if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
1177 dev_err(dev->class_dev, "AO FIFO underrun\n");
1178 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1181 async->events |= events;
1182 return !(async->events & COMEDI_CB_CANCEL_MASK);
1185 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1186 struct comedi_subdevice *s,
1187 unsigned int trig_num)
1189 struct pci230_private *devpriv = dev->private;
1190 unsigned long irqflags;
1195 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1196 if (!devpriv->ao_cmd_started) {
1197 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1201 if (devpriv->hwver < 2) {
1202 /* Not using DAC FIFO. */
1203 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1204 pci230_handle_ao_nofifo(dev, s);
1205 comedi_handle_events(dev, s);
1207 /* Using DAC FIFO. */
1208 /* Read DACSWTRIG register to trigger conversion. */
1209 inw(devpriv->daqio + PCI230P2_DACSWTRIG);
1210 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1212 /* Delay. Should driver be responsible for this? */
1213 /* XXX TODO: See if DAC busy bit can be used. */
1218 static void pci230_ao_start(struct comedi_device *dev,
1219 struct comedi_subdevice *s)
1221 struct pci230_private *devpriv = dev->private;
1222 struct comedi_async *async = s->async;
1223 struct comedi_cmd *cmd = &async->cmd;
1224 unsigned long irqflags;
1226 devpriv->ao_cmd_started = true;
1228 if (devpriv->hwver >= 2) {
1229 /* Using DAC FIFO. */
1230 unsigned short scantrig;
1233 /* Preload FIFO data. */
1234 run = pci230_handle_ao_fifo(dev, s);
1235 comedi_handle_events(dev, s);
1240 /* Set scan trigger source. */
1241 switch (cmd->scan_begin_src) {
1243 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1246 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1247 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1249 scantrig = PCI230P2_DAC_TRIG_EXTP;
1252 scantrig = PCI230P2_DAC_TRIG_EXTN;
1256 scantrig = PCI230P2_DAC_TRIG_SW;
1259 /* Shouldn't get here. */
1260 scantrig = PCI230P2_DAC_TRIG_NONE;
1264 (devpriv->daccon & ~PCI230P2_DAC_TRIG_MASK) | scantrig;
1265 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
1267 switch (cmd->scan_begin_src) {
1269 if (devpriv->hwver < 2) {
1270 /* Not using DAC FIFO. */
1271 /* Enable CT1 timer interrupt. */
1272 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1273 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1274 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1275 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1278 /* Set CT1 gate high to start counting. */
1279 outb(GAT_CONFIG(1, GAT_VCC), dev->iobase + PCI230_ZGAT_SCE);
1282 async->inttrig = pci230_ao_inttrig_scan_begin;
1285 if (devpriv->hwver >= 2) {
1286 /* Using DAC FIFO. Enable DAC FIFO interrupt. */
1287 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1288 devpriv->ier |= PCI230P2_INT_DAC;
1289 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1290 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1294 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1295 struct comedi_subdevice *s,
1296 unsigned int trig_num)
1298 struct comedi_cmd *cmd = &s->async->cmd;
1300 if (trig_num != cmd->start_src)
1303 s->async->inttrig = NULL;
1304 pci230_ao_start(dev, s);
1309 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1311 struct pci230_private *devpriv = dev->private;
1312 unsigned short daccon;
1315 /* Get the command. */
1316 struct comedi_cmd *cmd = &s->async->cmd;
1318 if (cmd->scan_begin_src == TRIG_TIMER) {
1320 if (!pci230_claim_shared(dev, RES_Z2CT1, OWNER_AOCMD))
1325 * Set range - see analogue output range table; 0 => unipolar 10V,
1326 * 1 => bipolar +/-10V range scale
1328 range = CR_RANGE(cmd->chanlist[0]);
1329 devpriv->ao_bipolar = comedi_range_is_bipolar(s, range);
1330 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1331 /* Use DAC FIFO for hardware version 2 onwards. */
1332 if (devpriv->hwver >= 2) {
1333 unsigned short dacen;
1337 for (i = 0; i < cmd->chanlist_len; i++)
1338 dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1340 /* Set channel scan list. */
1341 outw(dacen, devpriv->daqio + PCI230P2_DACEN);
1344 * Set DAC scan source to 'none'.
1345 * Set DAC FIFO interrupt trigger level to 'not half full'.
1346 * Reset DAC FIFO and clear underrun.
1348 * N.B. DAC FIFO interrupts are currently disabled.
1350 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET |
1351 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR |
1352 PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1356 outw(daccon, devpriv->daqio + PCI230_DACCON);
1357 /* Preserve most of DACCON apart from write-only, transient bits. */
1358 devpriv->daccon = daccon & ~(PCI230P2_DAC_FIFO_RESET |
1359 PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1361 if (cmd->scan_begin_src == TRIG_TIMER) {
1363 * Set the counter timer 1 to the specified scan frequency.
1364 * cmd->scan_begin_arg is sampling period in ns.
1365 * Gate it off for now.
1367 outb(GAT_CONFIG(1, GAT_GND), dev->iobase + PCI230_ZGAT_SCE);
1368 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1369 cmd->scan_begin_arg,
1373 /* N.B. cmd->start_src == TRIG_INT */
1374 s->async->inttrig = pci230_ao_inttrig_start;
1379 static int pci230_ao_cancel(struct comedi_device *dev,
1380 struct comedi_subdevice *s)
1382 pci230_ao_stop(dev, s);
1386 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1388 unsigned int min_scan_period, chanlist_len;
1391 chanlist_len = cmd->chanlist_len;
1392 if (cmd->chanlist_len == 0)
1395 min_scan_period = chanlist_len * cmd->convert_arg;
1396 if (min_scan_period < chanlist_len ||
1397 min_scan_period < cmd->convert_arg) {
1398 /* Arithmetic overflow. */
1399 min_scan_period = UINT_MAX;
1402 if (cmd->scan_begin_arg < min_scan_period) {
1403 cmd->scan_begin_arg = min_scan_period;
1410 static int pci230_ai_check_chanlist(struct comedi_device *dev,
1411 struct comedi_subdevice *s,
1412 struct comedi_cmd *cmd)
1414 struct pci230_private *devpriv = dev->private;
1415 unsigned int max_diff_chan = (s->n_chan / 2) - 1;
1416 unsigned int prev_chan = 0;
1417 unsigned int prev_range = 0;
1418 unsigned int prev_aref = 0;
1419 bool prev_bipolar = false;
1420 unsigned int subseq_len = 0;
1423 for (i = 0; i < cmd->chanlist_len; i++) {
1424 unsigned int chanspec = cmd->chanlist[i];
1425 unsigned int chan = CR_CHAN(chanspec);
1426 unsigned int range = CR_RANGE(chanspec);
1427 unsigned int aref = CR_AREF(chanspec);
1428 bool bipolar = comedi_range_is_bipolar(s, range);
1430 if (aref == AREF_DIFF && chan >= max_diff_chan) {
1431 dev_dbg(dev->class_dev,
1432 "%s: differential channel number out of range 0 to %u\n",
1433 __func__, max_diff_chan);
1439 * Channel numbers must strictly increase or
1440 * subsequence must repeat exactly.
1442 if (chan <= prev_chan && subseq_len == 0)
1445 if (subseq_len > 0 &&
1446 cmd->chanlist[i % subseq_len] != chanspec) {
1447 dev_dbg(dev->class_dev,
1448 "%s: channel numbers must increase or sequence must repeat exactly\n",
1453 if (aref != prev_aref) {
1454 dev_dbg(dev->class_dev,
1455 "%s: channel sequence analogue references must be all the same (single-ended or differential)\n",
1460 if (bipolar != prev_bipolar) {
1461 dev_dbg(dev->class_dev,
1462 "%s: channel sequence ranges must be all bipolar or all unipolar\n",
1467 if (aref != AREF_DIFF && range != prev_range &&
1468 ((chan ^ prev_chan) & ~1) == 0) {
1469 dev_dbg(dev->class_dev,
1470 "%s: single-ended channel pairs must have the same range\n",
1478 prev_bipolar = bipolar;
1481 if (subseq_len == 0)
1482 subseq_len = cmd->chanlist_len;
1484 if (cmd->chanlist_len % subseq_len) {
1485 dev_dbg(dev->class_dev,
1486 "%s: sequence must repeat exactly\n", __func__);
1491 * Buggy PCI230+ or PCI260+ requires channel 0 to be (first) in the
1492 * sequence if the sequence contains more than one channel. Hardware
1493 * versions 1 and 2 have the bug. There is no hardware version 3.
1495 * Actually, there are two firmwares that report themselves as
1496 * hardware version 1 (the boards have different ADC chips with
1497 * slightly different timing requirements, which was supposed to
1498 * be invisible to software). The first one doesn't seem to have
1499 * the bug, but the second one does, and we can't tell them apart!
1501 if (devpriv->hwver > 0 && devpriv->hwver < 4) {
1502 if (subseq_len > 1 && CR_CHAN(cmd->chanlist[0])) {
1503 dev_info(dev->class_dev,
1504 "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",
1513 static int pci230_ai_cmdtest(struct comedi_device *dev,
1514 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1516 const struct pci230_board *thisboard = dev->board_ptr;
1517 struct pci230_private *devpriv = dev->private;
1521 /* Step 1 : check if triggers are trivially valid */
1523 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1525 tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1526 if (thisboard->have_dio || thisboard->min_hwver > 0) {
1528 * Unfortunately, we cannot trigger a scan off an external
1529 * source on the PCI260 board, since it uses the PPIC0 (DIO)
1530 * input, which isn't present on the PCI260. For PCI260+
1531 * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead.
1535 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
1536 err |= cfc_check_trigger_src(&cmd->convert_src,
1537 TRIG_TIMER | TRIG_INT | TRIG_EXT);
1538 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1539 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1544 /* Step 2a : make sure trigger sources are unique */
1546 err |= cfc_check_trigger_is_unique(cmd->start_src);
1547 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1548 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1549 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1551 /* Step 2b : and mutually compatible */
1554 * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1555 * set up to generate a fixed number of timed conversion pulses.
1557 if (cmd->scan_begin_src != TRIG_FOLLOW &&
1558 cmd->convert_src != TRIG_TIMER)
1564 /* Step 3: check if arguments are trivially valid */
1566 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1568 #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */
1569 #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */
1570 #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */
1572 * Comedi limit due to unsigned int cmd. Driver limit =
1573 * 2^16 (16bit * counter) * 1000000ns (1kHz onboard clock) = 65.536s
1575 #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */
1577 if (cmd->convert_src == TRIG_TIMER) {
1578 unsigned int max_speed_ai;
1580 if (devpriv->hwver == 0) {
1582 * PCI230 or PCI260. Max speed depends whether
1583 * single-ended or pseudo-differential.
1585 if (cmd->chanlist && cmd->chanlist_len > 0) {
1586 /* Peek analogue reference of first channel. */
1587 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1588 max_speed_ai = MAX_SPEED_AI_DIFF;
1590 max_speed_ai = MAX_SPEED_AI_SE;
1593 /* No channel list. Assume single-ended. */
1594 max_speed_ai = MAX_SPEED_AI_SE;
1597 /* PCI230+ or PCI260+. */
1598 max_speed_ai = MAX_SPEED_AI_PLUS;
1601 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1603 err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
1605 } else if (cmd->convert_src == TRIG_EXT) {
1609 * convert_arg == (CR_EDGE | 0)
1610 * => trigger on +ve edge.
1611 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1612 * => trigger on -ve edge.
1614 if (cmd->convert_arg & CR_FLAGS_MASK) {
1615 /* Trigger number must be 0. */
1616 if (cmd->convert_arg & ~CR_FLAGS_MASK) {
1617 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1622 * The only flags allowed are CR_INVERT and CR_EDGE.
1623 * CR_EDGE is required.
1625 if ((cmd->convert_arg & CR_FLAGS_MASK & ~CR_INVERT) !=
1627 /* Set CR_EDGE, preserve CR_INVERT. */
1629 COMBINE(cmd->start_arg, CR_EDGE | 0,
1630 CR_FLAGS_MASK & ~CR_INVERT);
1635 * Backwards compatibility with previous versions:
1636 * convert_arg == 0 => trigger on -ve edge.
1637 * convert_arg == 1 => trigger on +ve edge.
1639 err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1);
1642 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1645 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1647 if (cmd->stop_src == TRIG_COUNT)
1648 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
1649 else /* TRIG_NONE */
1650 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1652 if (cmd->scan_begin_src == TRIG_EXT) {
1654 * external "trigger" to begin each scan:
1655 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1656 * of CT2 (sample convert trigger is CT2)
1658 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
1659 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1663 /* The only flag allowed is CR_EDGE, which is ignored. */
1664 if (cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) {
1665 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1666 CR_FLAGS_MASK & ~CR_EDGE);
1669 } else if (cmd->scan_begin_src == TRIG_TIMER) {
1670 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1671 if (!pci230_ai_check_scan_period(cmd))
1675 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1681 /* Step 4: fix up any arguments */
1683 if (cmd->convert_src == TRIG_TIMER) {
1684 tmp = cmd->convert_arg;
1685 pci230_ns_to_single_timer(&cmd->convert_arg, cmd->flags);
1686 if (tmp != cmd->convert_arg)
1690 if (cmd->scan_begin_src == TRIG_TIMER) {
1691 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1692 tmp = cmd->scan_begin_arg;
1693 pci230_ns_to_single_timer(&cmd->scan_begin_arg, cmd->flags);
1694 if (!pci230_ai_check_scan_period(cmd)) {
1695 /* Was below minimum required. Round up. */
1696 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1698 pci230_ai_check_scan_period(cmd);
1700 if (tmp != cmd->scan_begin_arg)
1707 /* Step 5: check channel list if it exists */
1708 if (cmd->chanlist && cmd->chanlist_len > 0)
1709 err |= pci230_ai_check_chanlist(dev, s, cmd);
1717 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
1718 struct comedi_subdevice *s)
1720 struct pci230_private *devpriv = dev->private;
1721 struct comedi_cmd *cmd = &s->async->cmd;
1723 unsigned short triglev;
1724 unsigned short adccon;
1726 if (cmd->flags & CMDF_WAKE_EOS)
1727 wake = cmd->scan_end_arg - s->async->cur_chan;
1729 wake = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL);
1731 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
1732 triglev = PCI230_ADC_INT_FIFO_HALF;
1733 } else if (wake > 1 && devpriv->hwver > 0) {
1734 /* PCI230+/260+ programmable FIFO interrupt level. */
1735 if (devpriv->adcfifothresh != wake) {
1736 devpriv->adcfifothresh = wake;
1737 outw(wake, devpriv->daqio + PCI230P_ADCFFTH);
1739 triglev = PCI230P_ADC_INT_FIFO_THRESH;
1741 triglev = PCI230_ADC_INT_FIFO_NEMPTY;
1743 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
1744 if (adccon != devpriv->adccon) {
1745 devpriv->adccon = adccon;
1746 outw(adccon, devpriv->daqio + PCI230_ADCCON);
1750 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
1751 struct comedi_subdevice *s,
1752 unsigned int trig_num)
1754 struct pci230_private *devpriv = dev->private;
1755 unsigned long irqflags;
1756 unsigned int delayus;
1761 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1762 if (!devpriv->ai_cmd_started) {
1763 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1767 * Trigger conversion by toggling Z2-CT2 output.
1768 * Finish with output high.
1770 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
1771 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
1773 * Delay. Should driver be responsible for this? An
1774 * alternative would be to wait until conversion is complete,
1775 * but we can't tell when it's complete because the ADC busy
1776 * bit has a different meaning when FIFO enabled (and when
1777 * FIFO not enabled, it only works for software triggers).
1779 if ((devpriv->adccon & PCI230_ADC_IM_MASK) == PCI230_ADC_IM_DIF &&
1780 devpriv->hwver == 0) {
1781 /* PCI230/260 in differential mode */
1784 /* single-ended or PCI230+/260+ */
1787 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1792 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
1793 struct comedi_subdevice *s,
1794 unsigned int trig_num)
1796 struct pci230_private *devpriv = dev->private;
1797 unsigned long irqflags;
1803 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1804 if (devpriv->ai_cmd_started) {
1805 /* Trigger scan by waggling CT0 gate source. */
1806 zgat = GAT_CONFIG(0, GAT_GND);
1807 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1808 zgat = GAT_CONFIG(0, GAT_VCC);
1809 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1811 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1816 static void pci230_ai_stop(struct comedi_device *dev,
1817 struct comedi_subdevice *s)
1819 struct pci230_private *devpriv = dev->private;
1820 unsigned long irqflags;
1821 struct comedi_cmd *cmd;
1824 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1825 started = devpriv->ai_cmd_started;
1826 devpriv->ai_cmd_started = false;
1827 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1830 cmd = &s->async->cmd;
1831 if (cmd->convert_src == TRIG_TIMER) {
1832 /* Stop conversion rate generator. */
1833 pci230_cancel_ct(dev, 2);
1835 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1836 /* Stop scan period monostable. */
1837 pci230_cancel_ct(dev, 0);
1839 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1841 * Disable ADC interrupt and wait for interrupt routine to finish
1842 * running unless we are called from the interrupt routine.
1844 devpriv->ier &= ~PCI230_INT_ADC;
1845 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
1846 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1847 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1849 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1850 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1852 * Reset FIFO, disable FIFO and set start conversion source to none.
1853 * Keep se/diff and bip/uni settings.
1856 (devpriv->adccon & (PCI230_ADC_IR_MASK | PCI230_ADC_IM_MASK)) |
1857 PCI230_ADC_TRIG_NONE;
1858 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
1859 devpriv->daqio + PCI230_ADCCON);
1860 /* Release resources. */
1861 pci230_release_all_resources(dev, OWNER_AICMD);
1864 static void pci230_ai_start(struct comedi_device *dev,
1865 struct comedi_subdevice *s)
1867 struct pci230_private *devpriv = dev->private;
1868 unsigned long irqflags;
1869 unsigned short conv;
1870 struct comedi_async *async = s->async;
1871 struct comedi_cmd *cmd = &async->cmd;
1873 devpriv->ai_cmd_started = true;
1875 /* Enable ADC FIFO trigger level interrupt. */
1876 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1877 devpriv->ier |= PCI230_INT_ADC;
1878 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
1879 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1882 * Update conversion trigger source which is currently set
1883 * to CT2 output, which is currently stuck high.
1885 switch (cmd->convert_src) {
1887 conv = PCI230_ADC_TRIG_NONE;
1890 /* Using CT2 output. */
1891 conv = PCI230_ADC_TRIG_Z2CT2;
1894 if (cmd->convert_arg & CR_EDGE) {
1895 if ((cmd->convert_arg & CR_INVERT) == 0) {
1896 /* Trigger on +ve edge. */
1897 conv = PCI230_ADC_TRIG_EXTP;
1899 /* Trigger on -ve edge. */
1900 conv = PCI230_ADC_TRIG_EXTN;
1903 /* Backwards compatibility. */
1904 if (cmd->convert_arg) {
1905 /* Trigger on +ve edge. */
1906 conv = PCI230_ADC_TRIG_EXTP;
1908 /* Trigger on -ve edge. */
1909 conv = PCI230_ADC_TRIG_EXTN;
1915 * Use CT2 output for software trigger due to problems
1916 * in differential mode on PCI230/260.
1918 conv = PCI230_ADC_TRIG_Z2CT2;
1921 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) | conv;
1922 outw(devpriv->adccon, devpriv->daqio + PCI230_ADCCON);
1923 if (cmd->convert_src == TRIG_INT)
1924 async->inttrig = pci230_ai_inttrig_convert;
1927 * Update FIFO interrupt trigger level, which is currently
1930 pci230_ai_update_fifo_trigger_level(dev, s);
1931 if (cmd->convert_src == TRIG_TIMER) {
1932 /* Update timer gates. */
1935 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1937 * Conversion timer CT2 needs to be gated by
1938 * inverted output of monostable CT2.
1940 zgat = GAT_CONFIG(2, GAT_NOUTNM2);
1943 * Conversion timer CT2 needs to be gated on
1946 zgat = GAT_CONFIG(2, GAT_VCC);
1948 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1949 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1950 /* Set monostable CT0 trigger source. */
1951 switch (cmd->scan_begin_src) {
1953 zgat = GAT_CONFIG(0, GAT_VCC);
1957 * For CT0 on PCI230, the external trigger
1958 * (gate) signal comes from PPC0, which is
1959 * channel 16 of the DIO subdevice. The
1960 * application needs to configure this as an
1961 * input in order to use it as an external scan
1964 zgat = GAT_CONFIG(0, GAT_EXT);
1968 * Monostable CT0 triggered by rising edge on
1969 * inverted output of CT1 (falling edge on CT1).
1971 zgat = GAT_CONFIG(0, GAT_NOUTNM2);
1975 * Monostable CT0 is triggered by inttrig
1976 * function waggling the CT0 gate source.
1978 zgat = GAT_CONFIG(0, GAT_VCC);
1981 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1982 switch (cmd->scan_begin_src) {
1985 * Scan period timer CT1 needs to be
1986 * gated on to start counting.
1988 zgat = GAT_CONFIG(1, GAT_VCC);
1989 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
1992 async->inttrig = pci230_ai_inttrig_scan_begin;
1996 } else if (cmd->convert_src != TRIG_INT) {
1997 /* No longer need Z2-CT2. */
1998 pci230_release_shared(dev, RES_Z2CT2, OWNER_AICMD);
2002 static int pci230_ai_inttrig_start(struct comedi_device *dev,
2003 struct comedi_subdevice *s,
2004 unsigned int trig_num)
2006 struct comedi_cmd *cmd = &s->async->cmd;
2008 if (trig_num != cmd->start_arg)
2011 s->async->inttrig = NULL;
2012 pci230_ai_start(dev, s);
2017 static void pci230_handle_ai(struct comedi_device *dev,
2018 struct comedi_subdevice *s)
2020 struct pci230_private *devpriv = dev->private;
2021 struct comedi_async *async = s->async;
2022 struct comedi_cmd *cmd = &async->cmd;
2023 unsigned int status_fifo;
2026 unsigned int fifoamount;
2029 /* Determine number of samples to read. */
2030 todo = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL);
2035 for (i = 0; i < todo; i++) {
2036 if (fifoamount == 0) {
2037 /* Read FIFO state. */
2038 status_fifo = inw(devpriv->daqio + PCI230_ADCCON);
2039 if (status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) {
2041 * Report error otherwise FIFO overruns will go
2042 * unnoticed by the caller.
2044 dev_err(dev->class_dev, "AI FIFO overrun\n");
2045 async->events |= COMEDI_CB_ERROR;
2047 } else if (status_fifo & PCI230_ADC_FIFO_EMPTY) {
2050 } else if (status_fifo & PCI230_ADC_FIFO_HALF) {
2051 /* FIFO half full. */
2052 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2053 } else if (devpriv->hwver > 0) {
2054 /* Read PCI230+/260+ ADC FIFO level. */
2055 fifoamount = inw(devpriv->daqio +
2057 if (fifoamount == 0)
2058 break; /* Shouldn't happen. */
2060 /* FIFO not empty. */
2065 val = pci230_ai_read(dev);
2066 if (!comedi_buf_write_samples(s, &val, 1))
2071 if (cmd->stop_src == TRIG_COUNT &&
2072 async->scans_done >= cmd->stop_arg) {
2073 async->events |= COMEDI_CB_EOA;
2078 /* update FIFO interrupt trigger level if still running */
2079 if (!(async->events & COMEDI_CB_CANCEL_MASK))
2080 pci230_ai_update_fifo_trigger_level(dev, s);
2083 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2085 struct pci230_private *devpriv = dev->private;
2086 unsigned int i, chan, range, diff;
2087 unsigned int res_mask;
2088 unsigned short adccon, adcen;
2091 /* Get the command. */
2092 struct comedi_async *async = s->async;
2093 struct comedi_cmd *cmd = &async->cmd;
2096 * Determine which shared resources are needed.
2100 * Need Z2-CT2 to supply a conversion trigger source at a high
2101 * logic level, even if not doing timed conversions.
2103 res_mask |= RES_Z2CT2;
2104 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2105 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2106 res_mask |= RES_Z2CT0;
2107 if (cmd->scan_begin_src == TRIG_TIMER) {
2108 /* Using Z2-CT1 for scan frequency */
2109 res_mask |= RES_Z2CT1;
2112 /* Claim resources. */
2113 if (!pci230_claim_shared(dev, res_mask, OWNER_AICMD))
2118 * - Set channel scan list.
2119 * - Set channel gains.
2120 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2121 * start conversion source to point to something at a high logic
2122 * level (we use the output of counter/timer 2 for this purpose.
2123 * - PAUSE to allow things to settle down.
2124 * - Reset the FIFO again because it needs resetting twice and there
2125 * may have been a false conversion trigger on some versions of
2126 * PCI230/260 due to the start conversion source being set to a
2128 * - Enable ADC FIFO level interrupt.
2129 * - Set actual conversion trigger source and FIFO interrupt trigger
2131 * - If convert_src is TRIG_TIMER, set up the timers.
2134 adccon = PCI230_ADC_FIFO_EN;
2137 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2138 /* Differential - all channels must be differential. */
2140 adccon |= PCI230_ADC_IM_DIF;
2142 /* Single ended - all channels must be single-ended. */
2144 adccon |= PCI230_ADC_IM_SE;
2147 range = CR_RANGE(cmd->chanlist[0]);
2148 devpriv->ai_bipolar = comedi_range_is_bipolar(s, range);
2149 if (devpriv->ai_bipolar)
2150 adccon |= PCI230_ADC_IR_BIP;
2152 adccon |= PCI230_ADC_IR_UNI;
2154 for (i = 0; i < cmd->chanlist_len; i++) {
2155 unsigned int gainshift;
2157 chan = CR_CHAN(cmd->chanlist[i]);
2158 range = CR_RANGE(cmd->chanlist[i]);
2160 gainshift = 2 * chan;
2161 if (devpriv->hwver == 0) {
2163 * Original PCI230/260 expects both inputs of
2164 * the differential channel to be enabled.
2166 adcen |= 3 << gainshift;
2169 * PCI230+/260+ expects only one input of the
2170 * differential channel to be enabled.
2172 adcen |= 1 << gainshift;
2175 gainshift = chan & ~1;
2178 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) |
2179 (pci230_ai_gain[range] << gainshift);
2182 /* Set channel scan list. */
2183 outw(adcen, devpriv->daqio + PCI230_ADCEN);
2185 /* Set channel gains. */
2186 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
2189 * Set counter/timer 2 output high for use as the initial start
2190 * conversion source.
2192 i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2195 * Temporarily use CT2 output as conversion trigger source and
2196 * temporarily set FIFO interrupt trigger level to 'full'.
2198 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2201 * Enable and reset FIFO, specify FIFO trigger level full, specify
2202 * uni/bip, se/diff, and temporarily set the start conversion source
2203 * to CT2 output. Note that CT2 output is currently high, and this
2204 * will produce a false conversion trigger on some versions of the
2205 * PCI230/260, but that will be dealt with later.
2207 devpriv->adccon = adccon;
2208 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
2212 * Failure to include this will result in the first few channels'-worth
2213 * of data being corrupt, normally manifesting itself by large negative
2214 * voltages. It seems the board needs time to settle between the first
2215 * FIFO reset (above) and the second FIFO reset (below). Setting the
2216 * channel gains and scan list _before_ the first FIFO reset also
2217 * helps, though only slightly.
2219 usleep_range(25, 100);
2221 /* Reset FIFO again. */
2222 outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
2224 if (cmd->convert_src == TRIG_TIMER) {
2226 * Set up CT2 as conversion timer, but gate it off for now.
2227 * Note, counter/timer output 2 can be monitored on the
2228 * connector: PCI230 pin 21, PCI260 pin 18.
2230 zgat = GAT_CONFIG(2, GAT_GND);
2231 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
2232 /* Set counter/timer 2 to the specified conversion period. */
2233 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2235 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2237 * Set up monostable on CT0 output for scan timing. A
2238 * rising edge on the trigger (gate) input of CT0 will
2239 * trigger the monostable, causing its output to go low
2240 * for the configured period. The period depends on
2241 * the conversion period and the number of conversions
2244 * Set the trigger high before setting up the
2245 * monostable to stop it triggering. The trigger
2246 * source will be changed later.
2248 zgat = GAT_CONFIG(0, GAT_VCC);
2249 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
2250 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2251 ((uint64_t)cmd->convert_arg *
2254 if (cmd->scan_begin_src == TRIG_TIMER) {
2256 * Monostable on CT0 will be triggered by
2257 * output of CT1 at configured scan frequency.
2259 * Set up CT1 but gate it off for now.
2261 zgat = GAT_CONFIG(1, GAT_GND);
2262 outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
2263 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2264 cmd->scan_begin_arg,
2270 if (cmd->start_src == TRIG_INT)
2271 s->async->inttrig = pci230_ai_inttrig_start;
2273 pci230_ai_start(dev, s);
2278 static int pci230_ai_cancel(struct comedi_device *dev,
2279 struct comedi_subdevice *s)
2281 pci230_ai_stop(dev, s);
2285 /* Interrupt handler */
2286 static irqreturn_t pci230_interrupt(int irq, void *d)
2288 unsigned char status_int, valid_status_int, temp_ier;
2289 struct comedi_device *dev = (struct comedi_device *)d;
2290 struct pci230_private *devpriv = dev->private;
2291 struct comedi_subdevice *s_ao = dev->write_subdev;
2292 struct comedi_subdevice *s_ai = dev->read_subdev;
2293 unsigned long irqflags;
2295 /* Read interrupt status/enable register. */
2296 status_int = inb(dev->iobase + PCI230_INT_STAT);
2298 if (status_int == PCI230_INT_DISABLE)
2301 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2302 valid_status_int = devpriv->ier & status_int;
2304 * Disable triggered interrupts.
2305 * (Only those interrupts that need re-enabling, are, later in the
2308 temp_ier = devpriv->ier & ~status_int;
2309 outb(temp_ier, dev->iobase + PCI230_INT_SCE);
2310 devpriv->intr_running = true;
2311 devpriv->intr_cpuid = THISCPU;
2312 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2315 * Check the source of interrupt and handle it.
2316 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2317 * interrupts. However, at present (Comedi-0.7.60) does not allow
2318 * concurrent execution of commands, instructions or a mixture of the
2322 if (valid_status_int & PCI230_INT_ZCLK_CT1)
2323 pci230_handle_ao_nofifo(dev, s_ao);
2325 if (valid_status_int & PCI230P2_INT_DAC)
2326 pci230_handle_ao_fifo(dev, s_ao);
2328 if (valid_status_int & PCI230_INT_ADC)
2329 pci230_handle_ai(dev, s_ai);
2331 /* Reenable interrupts. */
2332 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2333 if (devpriv->ier != temp_ier)
2334 outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
2335 devpriv->intr_running = false;
2336 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2338 comedi_handle_events(dev, s_ao);
2339 comedi_handle_events(dev, s_ai);
2344 /* Check if PCI device matches a specific board. */
2345 static bool pci230_match_pci_board(const struct pci230_board *board,
2346 struct pci_dev *pci_dev)
2348 /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */
2349 if (board->id != pci_dev->device)
2351 if (board->min_hwver == 0)
2353 /* Looking for a '+' model. First check length of registers. */
2354 if (pci_resource_len(pci_dev, 3) < 32)
2355 return false; /* Not a '+' model. */
2357 * TODO: temporarily enable PCI device and read the hardware version
2358 * register. For now, assume it's okay.
2363 /* Look for board matching PCI device. */
2364 static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev)
2368 for (i = 0; i < ARRAY_SIZE(pci230_boards); i++)
2369 if (pci230_match_pci_board(&pci230_boards[i], pci_dev))
2370 return &pci230_boards[i];
2374 static int pci230_auto_attach(struct comedi_device *dev,
2375 unsigned long context_unused)
2377 struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
2378 const struct pci230_board *thisboard;
2379 struct pci230_private *devpriv;
2380 struct comedi_subdevice *s;
2383 dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
2386 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
2390 spin_lock_init(&devpriv->isr_spinlock);
2391 spin_lock_init(&devpriv->res_spinlock);
2392 spin_lock_init(&devpriv->ai_stop_spinlock);
2393 spin_lock_init(&devpriv->ao_stop_spinlock);
2395 dev->board_ptr = pci230_find_pci_board(pci_dev);
2396 if (dev->board_ptr == NULL) {
2397 dev_err(dev->class_dev,
2398 "amplc_pci230: BUG! cannot determine board type!\n");
2401 thisboard = dev->board_ptr;
2402 dev->board_name = thisboard->name;
2404 rc = comedi_pci_enable(dev);
2409 * Read base addresses of the PCI230's two I/O regions from PCI
2410 * configuration register.
2412 dev->iobase = pci_resource_start(pci_dev, 2);
2413 devpriv->daqio = pci_resource_start(pci_dev, 3);
2414 dev_dbg(dev->class_dev,
2415 "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
2416 dev->board_name, dev->iobase, devpriv->daqio);
2417 /* Read bits of DACCON register - only the output range. */
2418 devpriv->daccon = inw(devpriv->daqio + PCI230_DACCON) &
2421 * Read hardware version register and set extended function register
2424 if (pci_resource_len(pci_dev, 3) >= 32) {
2425 unsigned short extfunc = 0;
2427 devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER);
2428 if (devpriv->hwver < thisboard->min_hwver) {
2429 dev_err(dev->class_dev,
2430 "%s - bad hardware version - got %u, need %u\n",
2431 dev->board_name, devpriv->hwver,
2432 thisboard->min_hwver);
2435 if (devpriv->hwver > 0) {
2436 if (!thisboard->have_dio) {
2438 * No DIO ports. Route counters' external gates
2439 * to the EXTTRIG signal (PCI260+ pin 17).
2440 * (Otherwise, they would be routed to DIO
2441 * inputs PC0, PC1 and PC2 which don't exist
2444 extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
2446 if (thisboard->ao_bits && devpriv->hwver >= 2) {
2447 /* Enable DAC FIFO functionality. */
2448 extfunc |= PCI230P2_EXTFUNC_DACFIFO;
2451 outw(extfunc, devpriv->daqio + PCI230P_EXTFUNC);
2452 if (extfunc & PCI230P2_EXTFUNC_DACFIFO) {
2454 * Temporarily enable DAC FIFO, reset it and disable
2457 outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN |
2458 PCI230P2_DAC_FIFO_RESET,
2459 devpriv->daqio + PCI230_DACCON);
2460 /* Clear DAC FIFO channel enable register. */
2461 outw(0, devpriv->daqio + PCI230P2_DACEN);
2462 /* Disable DAC FIFO. */
2463 outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
2466 /* Disable board's interrupts. */
2467 outb(0, dev->iobase + PCI230_INT_SCE);
2468 /* Set ADC to a reasonable state. */
2470 devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE |
2472 outw(1 << 0, devpriv->daqio + PCI230_ADCEN);
2473 outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
2474 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2475 devpriv->daqio + PCI230_ADCCON);
2478 rc = request_irq(pci_dev->irq, pci230_interrupt, IRQF_SHARED,
2479 dev->board_name, dev);
2481 dev->irq = pci_dev->irq;
2484 rc = comedi_alloc_subdevices(dev, 3);
2488 s = &dev->subdevices[0];
2489 /* analog input subdevice */
2490 s->type = COMEDI_SUBD_AI;
2491 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
2493 s->maxdata = (1 << thisboard->ai_bits) - 1;
2494 s->range_table = &pci230_ai_range;
2495 s->insn_read = pci230_ai_insn_read;
2496 s->len_chanlist = 256; /* but there are restrictions. */
2498 dev->read_subdev = s;
2499 s->subdev_flags |= SDF_CMD_READ;
2500 s->do_cmd = pci230_ai_cmd;
2501 s->do_cmdtest = pci230_ai_cmdtest;
2502 s->cancel = pci230_ai_cancel;
2505 s = &dev->subdevices[1];
2506 /* analog output subdevice */
2507 if (thisboard->ao_bits) {
2508 s->type = COMEDI_SUBD_AO;
2509 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
2511 s->maxdata = (1 << thisboard->ao_bits) - 1;
2512 s->range_table = &pci230_ao_range;
2513 s->insn_write = pci230_ao_insn_write;
2514 s->len_chanlist = 2;
2516 dev->write_subdev = s;
2517 s->subdev_flags |= SDF_CMD_WRITE;
2518 s->do_cmd = pci230_ao_cmd;
2519 s->do_cmdtest = pci230_ao_cmdtest;
2520 s->cancel = pci230_ao_cancel;
2523 rc = comedi_alloc_subdev_readback(s);
2527 s->type = COMEDI_SUBD_UNUSED;
2530 s = &dev->subdevices[2];
2531 /* digital i/o subdevice */
2532 if (thisboard->have_dio) {
2533 rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE);
2537 s->type = COMEDI_SUBD_UNUSED;
2543 static struct comedi_driver amplc_pci230_driver = {
2544 .driver_name = "amplc_pci230",
2545 .module = THIS_MODULE,
2546 .auto_attach = pci230_auto_attach,
2547 .detach = comedi_pci_detach,
2550 static int amplc_pci230_pci_probe(struct pci_dev *dev,
2551 const struct pci_device_id *id)
2553 return comedi_pci_auto_config(dev, &lc_pci230_driver,
2557 static const struct pci_device_id amplc_pci230_pci_table[] = {
2558 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
2559 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
2562 MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table);
2564 static struct pci_driver amplc_pci230_pci_driver = {
2565 .name = "amplc_pci230",
2566 .id_table = amplc_pci230_pci_table,
2567 .probe = amplc_pci230_pci_probe,
2568 .remove = comedi_pci_auto_unconfig,
2570 module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
2572 MODULE_AUTHOR("Comedi http://www.comedi.org");
2573 MODULE_DESCRIPTION("Comedi driver for Amplicon PCI230(+) and PCI260(+)");
2574 MODULE_LICENSE("GPL");