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 Description: Amplicon PCI230, PCI260 Multifunction I/O boards
23 Author: Allan Willcox <allanwillcox@ozemail.com.au>,
24 Steve D Sharples <steve.sharples@nottingham.ac.uk>,
25 Ian Abbott <abbotti@mev.co.uk>
26 Updated: Wed, 22 Oct 2008 12:34:49 +0100
27 Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
28 PCI230+ (pci230+ or amplc_pci230),
29 PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
32 Configuration options:
33 [0] - PCI bus of device (optional).
34 [1] - PCI slot of device (optional).
35 If bus/slot is not specified, the first available PCI device
38 Configuring a "amplc_pci230" will match any supported card and it will
39 choose the best match, picking the "+" models if possible. Configuring
40 a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
41 a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card
42 and it will be treated as a PCI260. Configuring a "pci230+" will match
43 a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card.
56 The AI subdevice has 16 single-ended channels or 8 differential
59 The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and
60 PCI260+ cards have 16-bit resolution.
62 For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
63 inputs 14 and 15 for channel 7). If the card is physically a PCI230
64 or PCI260 then it actually uses a "pseudo-differential" mode where the
65 inputs are sampled a few microseconds apart. The PCI230+ and PCI260+
66 use true differential sampling. Another difference is that if the
67 card is physically a PCI230 or PCI260, the inverting input is 2N,
68 whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a
69 PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
70 PCI260+) and differential mode is used, the differential inputs need
71 to be physically swapped on the connector.
73 The following input ranges are supported:
85 +=========+==============+===========+============+==========+
86 |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
87 +=========+==============+===========+============+==========+
88 |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
89 |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT|
91 | |--------------|-----------| | |
92 | | TRIG_TIMER(1)|TRIG_TIMER | | |
93 | | TRIG_EXT(2) | | | |
95 +---------+--------------+-----------+------------+----------+
97 Note 1: If AI command and AO command are used simultaneously, only
98 one may have scan_begin_src == TRIG_TIMER.
100 Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
101 DIO channel 16 (pin 49) which will need to be configured as
102 a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input
103 (pin 17) is used instead. For PCI230, scan_begin_src ==
104 TRIG_EXT is not supported. The trigger is a rising edge
107 Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
108 (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The
109 convert_arg value is interpreted as follows:
111 convert_arg == (CR_EDGE | 0) => rising edge
112 convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
113 convert_arg == 0 => falling edge (backwards compatibility)
114 convert_arg == 1 => rising edge (backwards compatibility)
116 All entries in the channel list must use the same analogue reference.
117 If the analogue reference is not AREF_DIFF (not differential) each
118 pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
119 input range. The input ranges used in the sequence must be all
120 bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel
121 sequence must consist of 1 or more identical subsequences. Within the
122 subsequence, channels must be in ascending order with no repeated
123 channels. For example, the following sequences are valid: 0 1 2 3
124 (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
125 subsequence), 1 1 1 1 (repeated valid subsequence). The following
126 sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
127 (incompletely repeated subsequence). Some versions of the PCI230+ and
128 PCI260+ have a bug that requires a subsequence longer than one entry
129 long to include channel 0.
133 The AO subdevice has 2 channels with 12-bit resolution.
135 The following output ranges are supported:
142 +=========+==============+===========+============+==========+
143 |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
144 +=========+==============+===========+============+==========+
145 |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE |
146 | | TRIG_EXT(2) | | |TRIG_COUNT|
148 +---------+--------------+-----------+------------+----------+
150 Note 1: If AI command and AO command are used simultaneously, only
151 one may have scan_begin_src == TRIG_TIMER.
153 Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
154 configured as a PCI230+ and is only supported on later
155 versions of the card. As a card configured as a PCI230+ is
156 not guaranteed to support external triggering, please consider
157 this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK
158 input (PCI230+ pin 25). Triggering will be on the rising edge
159 unless the CR_INVERT flag is set in scan_begin_arg.
161 The channels in the channel sequence must be in ascending order with
162 no repeats. All entries in the channel sequence must use the same
167 The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO
168 channels are configurable as inputs or outputs in four groups:
170 Port A - channels 0 to 7
171 Port B - channels 8 to 15
172 Port CL - channels 16 to 19
173 Port CH - channels 20 to 23
175 Only mode 0 of the 8255 chip is supported.
177 Bit 0 of port C (DIO channel 16) is also used as an external scan
178 trigger input for AI commands on PCI230 and PCI230+, so would need to
179 be configured as an input to use it for that purpose.
182 Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples.
183 Support for PCI230+/260+, more triggered scan functionality, and workarounds
184 for (or detection of) various hardware problems added by Ian Abbott.
187 #include <linux/module.h>
188 #include <linux/pci.h>
189 #include <linux/delay.h>
190 #include <linux/interrupt.h>
192 #include "../comedidev.h"
194 #include "comedi_fc.h"
198 /* PCI230 PCI configuration register information */
199 #define PCI_DEVICE_ID_PCI230 0x0000
200 #define PCI_DEVICE_ID_PCI260 0x0006
201 #define PCI_DEVICE_ID_INVALID 0xffff
203 #define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */
204 #define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */
206 /* PCI230 i/o space 1 registers. */
207 #define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */
208 #define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */
209 #define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */
210 #define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */
211 #define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */
212 #define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */
213 #define PCI230_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
214 #define PCI230_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
215 #define PCI230_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
216 #define PCI230_Z2_CTC 0x17 /* 82C54 counter/timer control word */
217 #define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */
218 #define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */
219 #define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */
220 #define PCI230_INT_STAT 0x1E /* Interrupt status (r) */
222 /* PCI230 i/o space 2 registers. */
223 #define PCI230_DACCON 0x00 /* DAC control */
224 #define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */
225 #define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */
226 #define PCI230_ADCDATA 0x08 /* ADC data (r) */
227 #define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */
228 #define PCI230_ADCCON 0x0A /* ADC control */
229 #define PCI230_ADCEN 0x0C /* ADC channel enable bits */
230 #define PCI230_ADCG 0x0E /* ADC gain control bits */
231 /* PCI230+ i/o space 2 additional registers. */
232 #define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */
233 #define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */
234 #define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */
235 #define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */
236 #define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */
237 #define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */
238 #define PCI230P_EXTFUNC 0x1C /* Extended functions */
239 #define PCI230P_HWVER 0x1E /* Hardware version (r) */
240 /* PCI230+ hardware version 2 onwards. */
241 #define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */
242 #define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */
243 #define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */
245 /* Convertor related constants. */
246 #define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs */
247 /* (DAC itself is 1µs nominally). */
248 #define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs */
249 /* (ADC itself is 1.6µs nominally but we poll
251 #define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS */
252 /* - 10µs for se, 20µs de. */
254 /* DACCON read-write values. */
255 #define PCI230_DAC_OR_UNI (0<<0) /* Output range unipolar */
256 #define PCI230_DAC_OR_BIP (1<<0) /* Output range bipolar */
257 #define PCI230_DAC_OR_MASK (1<<0)
258 /* The following applies only if DAC FIFO support is enabled in the EXTFUNC
259 * register (and only for PCI230+ hardware version 2 onwards). */
260 #define PCI230P2_DAC_FIFO_EN (1<<8) /* FIFO enable */
261 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
262 * hardware version 2 onwards). */
263 #define PCI230P2_DAC_TRIG_NONE (0<<2) /* No trigger */
264 #define PCI230P2_DAC_TRIG_SW (1<<2) /* Software trigger trigger */
265 #define PCI230P2_DAC_TRIG_EXTP (2<<2) /* EXTTRIG +ve edge trigger */
266 #define PCI230P2_DAC_TRIG_EXTN (3<<2) /* EXTTRIG -ve edge trigger */
267 #define PCI230P2_DAC_TRIG_Z2CT0 (4<<2) /* CT0-OUT +ve edge trigger */
268 #define PCI230P2_DAC_TRIG_Z2CT1 (5<<2) /* CT1-OUT +ve edge trigger */
269 #define PCI230P2_DAC_TRIG_Z2CT2 (6<<2) /* CT2-OUT +ve edge trigger */
270 #define PCI230P2_DAC_TRIG_MASK (7<<2)
271 #define PCI230P2_DAC_FIFO_WRAP (1<<7) /* FIFO wraparound mode */
272 #define PCI230P2_DAC_INT_FIFO_EMPTY (0<<9) /* FIFO interrupt empty */
273 #define PCI230P2_DAC_INT_FIFO_NEMPTY (1<<9)
274 #define PCI230P2_DAC_INT_FIFO_NHALF (2<<9) /* FIFO intr not half full */
275 #define PCI230P2_DAC_INT_FIFO_HALF (3<<9)
276 #define PCI230P2_DAC_INT_FIFO_NFULL (4<<9) /* FIFO interrupt not full */
277 #define PCI230P2_DAC_INT_FIFO_FULL (5<<9)
278 #define PCI230P2_DAC_INT_FIFO_MASK (7<<9)
280 /* DACCON read-only values. */
281 #define PCI230_DAC_BUSY (1<<1) /* DAC busy. */
282 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
283 * hardware version 2 onwards). */
284 #define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1<<5) /* Underrun error */
285 #define PCI230P2_DAC_FIFO_EMPTY (1<<13) /* FIFO empty */
286 #define PCI230P2_DAC_FIFO_FULL (1<<14) /* FIFO full */
287 #define PCI230P2_DAC_FIFO_HALF (1<<15) /* FIFO half full */
289 /* DACCON write-only, transient values. */
290 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
291 * hardware version 2 onwards). */
292 #define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1<<5) /* Clear underrun */
293 #define PCI230P2_DAC_FIFO_RESET (1<<12) /* FIFO reset */
295 /* PCI230+ hardware version 2 DAC FIFO levels. */
296 #define PCI230P2_DAC_FIFOLEVEL_HALF 512
297 #define PCI230P2_DAC_FIFOLEVEL_FULL 1024
298 /* Free space in DAC FIFO. */
299 #define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL
300 #define PCI230P2_DAC_FIFOROOM_ONETOHALF \
301 (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
302 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1
303 #define PCI230P2_DAC_FIFOROOM_FULL 0
305 /* ADCCON read/write values. */
306 #define PCI230_ADC_TRIG_NONE (0<<0) /* No trigger */
307 #define PCI230_ADC_TRIG_SW (1<<0) /* Software trigger trigger */
308 #define PCI230_ADC_TRIG_EXTP (2<<0) /* EXTTRIG +ve edge trigger */
309 #define PCI230_ADC_TRIG_EXTN (3<<0) /* EXTTRIG -ve edge trigger */
310 #define PCI230_ADC_TRIG_Z2CT0 (4<<0) /* CT0-OUT +ve edge trigger */
311 #define PCI230_ADC_TRIG_Z2CT1 (5<<0) /* CT1-OUT +ve edge trigger */
312 #define PCI230_ADC_TRIG_Z2CT2 (6<<0) /* CT2-OUT +ve edge trigger */
313 #define PCI230_ADC_TRIG_MASK (7<<0)
314 #define PCI230_ADC_IR_UNI (0<<3) /* Input range unipolar */
315 #define PCI230_ADC_IR_BIP (1<<3) /* Input range bipolar */
316 #define PCI230_ADC_IR_MASK (1<<3)
317 #define PCI230_ADC_IM_SE (0<<4) /* Input mode single ended */
318 #define PCI230_ADC_IM_DIF (1<<4) /* Input mode differential */
319 #define PCI230_ADC_IM_MASK (1<<4)
320 #define PCI230_ADC_FIFO_EN (1<<8) /* FIFO enable */
321 #define PCI230_ADC_INT_FIFO_EMPTY (0<<9)
322 #define PCI230_ADC_INT_FIFO_NEMPTY (1<<9) /* FIFO interrupt not empty */
323 #define PCI230_ADC_INT_FIFO_NHALF (2<<9)
324 #define PCI230_ADC_INT_FIFO_HALF (3<<9) /* FIFO interrupt half full */
325 #define PCI230_ADC_INT_FIFO_NFULL (4<<9)
326 #define PCI230_ADC_INT_FIFO_FULL (5<<9) /* FIFO interrupt full */
327 #define PCI230P_ADC_INT_FIFO_THRESH (7<<9) /* FIFO interrupt threshold */
328 #define PCI230_ADC_INT_FIFO_MASK (7<<9)
330 /* ADCCON write-only, transient values. */
331 #define PCI230_ADC_FIFO_RESET (1<<12) /* FIFO reset */
332 #define PCI230_ADC_GLOB_RESET (1<<13) /* Global reset */
334 /* ADCCON read-only values. */
335 #define PCI230_ADC_BUSY (1<<15) /* ADC busy */
336 #define PCI230_ADC_FIFO_EMPTY (1<<12) /* FIFO empty */
337 #define PCI230_ADC_FIFO_FULL (1<<13) /* FIFO full */
338 #define PCI230_ADC_FIFO_HALF (1<<14) /* FIFO half full */
339 #define PCI230_ADC_FIFO_FULL_LATCHED (1<<5) /* Indicates overrun occurred */
341 /* PCI230 ADC FIFO levels. */
342 #define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */
343 #define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */
345 /* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
346 * mode. Can be anything. */
347 #define PCI230_ADC_CONV 0xffff
349 /* PCI230+ EXTFUNC values. */
350 #define PCI230P_EXTFUNC_GAT_EXTTRIG (1<<0)
351 /* Route EXTTRIG pin to external gate inputs. */
352 /* PCI230+ hardware version 2 values. */
353 #define PCI230P2_EXTFUNC_DACFIFO (1<<1)
354 /* Allow DAC FIFO to be enabled. */
357 * Counter/timer clock input configuration sources.
359 #define CLK_CLK 0 /* reserved (channel-specific clock) */
360 #define CLK_10MHZ 1 /* internal 10 MHz clock */
361 #define CLK_1MHZ 2 /* internal 1 MHz clock */
362 #define CLK_100KHZ 3 /* internal 100 kHz clock */
363 #define CLK_10KHZ 4 /* internal 10 kHz clock */
364 #define CLK_1KHZ 5 /* internal 1 kHz clock */
365 #define CLK_OUTNM1 6 /* output of channel-1 modulo total */
366 #define CLK_EXT 7 /* external clock */
367 /* Macro to construct clock input configuration register value. */
368 #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
369 /* Timebases in ns. */
370 #define TIMEBASE_10MHZ 100
371 #define TIMEBASE_1MHZ 1000
372 #define TIMEBASE_100KHZ 10000
373 #define TIMEBASE_10KHZ 100000
374 #define TIMEBASE_1KHZ 1000000
377 * Counter/timer gate input configuration sources.
379 #define GAT_VCC 0 /* VCC (i.e. enabled) */
380 #define GAT_GND 1 /* GND (i.e. disabled) */
381 #define GAT_EXT 2 /* external gate input (PPCn on PCI230) */
382 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
383 /* Macro to construct gate input configuration register value. */
384 #define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
387 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
389 * Channel's Channel's
390 * clock input gate input
391 * Channel CLK_OUTNM1 GAT_NOUTNM2
392 * ------- ---------- -----------
393 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
394 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
395 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
398 /* Interrupt enables/status register values. */
399 #define PCI230_INT_DISABLE 0
400 #define PCI230_INT_PPI_C0 (1<<0)
401 #define PCI230_INT_PPI_C3 (1<<1)
402 #define PCI230_INT_ADC (1<<2)
403 #define PCI230_INT_ZCLK_CT1 (1<<5)
404 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
405 #define PCI230P2_INT_DAC (1<<4)
407 #define PCI230_TEST_BIT(val, n) ((val>>n)&1)
408 /* Assumes bits numbered with zero offset, ie. 0-15 */
410 /* (Potentially) shared resources and their owners */
412 RES_Z2CT0, /* Z2-CT0 */
413 RES_Z2CT1, /* Z2-CT1 */
414 RES_Z2CT2, /* Z2-CT2 */
415 NUM_RESOURCES /* Number of (potentially) shared resources. */
419 OWNER_NONE, /* Not owned */
420 OWNER_AICMD, /* Owned by AI command */
421 OWNER_AOCMD /* Owned by AO command */
428 /* Combine old and new bits. */
429 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
431 /* Current CPU. XXX should this be hard_smp_processor_id()? */
432 #define THISCPU smp_processor_id()
434 /* State flags for atomic bit operations */
435 #define AI_CMD_STARTED 0
436 #define AO_CMD_STARTED 1
439 * Board descriptions for the two boards supported.
442 struct pci230_board {
450 unsigned int min_hwver; /* Minimum hardware version supported. */
452 static const struct pci230_board pci230_boards[] = {
455 .id = PCI_DEVICE_ID_PCI230,
465 .id = PCI_DEVICE_ID_PCI260,
475 .id = PCI_DEVICE_ID_PCI230,
484 .id = PCI_DEVICE_ID_PCI260,
492 .name = "amplc_pci230", /* Wildcard matches any above */
493 .id = PCI_DEVICE_ID_INVALID,
497 /* this structure is for data unique to this hardware driver. If
498 several hardware drivers keep similar information in this structure,
499 feel free to suggest moving the variable to the struct comedi_device struct. */
500 struct pci230_private {
501 spinlock_t isr_spinlock; /* Interrupt spin lock */
502 spinlock_t res_spinlock; /* Shared resources spin lock */
503 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
504 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
505 unsigned long state; /* State flags */
506 unsigned long iobase1; /* PCI230's I/O space 1 */
507 unsigned int ao_readback[2]; /* Used for AO readback */
508 unsigned int ai_scan_count; /* Number of analogue input scans
510 unsigned int ai_scan_pos; /* Current position within analogue
512 unsigned int ao_scan_count; /* Number of analogue output scans
514 int intr_cpuid; /* ID of CPU running interrupt routine. */
515 unsigned short hwver; /* Hardware version (for '+' models). */
516 unsigned short adccon; /* ADCCON register value. */
517 unsigned short daccon; /* DACCON register value. */
518 unsigned short adcfifothresh; /* ADC FIFO programmable interrupt
519 * level threshold (PCI230+/260+). */
520 unsigned short adcg; /* ADCG register value. */
521 unsigned char int_en; /* Interrupt enables bits. */
522 unsigned char ai_continuous; /* Flag set when cmd->stop_src ==
523 * TRIG_NONE - user chooses to stop
524 * continuous conversion by
526 unsigned char ao_continuous; /* Flag set when cmd->stop_src ==
527 * TRIG_NONE - user chooses to stop
528 * continuous conversion by
530 unsigned char ai_bipolar; /* Set if bipolar input range so we
531 * know to mangle it. */
532 unsigned char ao_bipolar; /* Set if bipolar output range so we
533 * know to mangle it. */
534 unsigned char ier; /* Copy of interrupt enables/status register. */
535 unsigned char intr_running; /* Flag set in interrupt routine. */
536 unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */
539 /* PCI230 clock source periods in ns */
540 static const unsigned int pci230_timebase[8] = {
541 [CLK_10MHZ] = TIMEBASE_10MHZ,
542 [CLK_1MHZ] = TIMEBASE_1MHZ,
543 [CLK_100KHZ] = TIMEBASE_100KHZ,
544 [CLK_10KHZ] = TIMEBASE_10KHZ,
545 [CLK_1KHZ] = TIMEBASE_1KHZ,
548 /* PCI230 analogue input range table */
549 static const struct comedi_lrange pci230_ai_range = { 7, {
560 /* PCI230 analogue gain bits for each input range. */
561 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
563 /* PCI230 adccon bipolar flag for each analogue input range. */
564 static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
566 /* PCI230 analogue output range table */
567 static const struct comedi_lrange pci230_ao_range = { 2, {
573 /* PCI230 daccon bipolar flag for each analogue output range. */
574 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
576 static short pci230_ai_read(struct comedi_device *dev)
578 const struct pci230_board *thisboard = comedi_board(dev);
579 struct pci230_private *devpriv = dev->private;
583 data = (short)inw(dev->iobase + PCI230_ADCDATA);
584 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
585 * four bits reserved for expansion). */
586 /* PCI230+ is 16 bit AI. */
587 data = data >> (16 - thisboard->ai_bits);
589 /* If a bipolar range was specified, mangle it (twos
590 * complement->straight binary). */
591 if (devpriv->ai_bipolar)
592 data ^= 1 << (thisboard->ai_bits - 1);
597 static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
600 const struct pci230_board *thisboard = comedi_board(dev);
601 struct pci230_private *devpriv = dev->private;
603 /* If a bipolar range was specified, mangle it (straight binary->twos
605 if (devpriv->ao_bipolar)
606 datum ^= 1 << (thisboard->ao_bits - 1);
608 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
609 * four bits reserved for expansion). */
610 /* PCI230+ is also 12 bit AO. */
611 datum <<= (16 - thisboard->ao_bits);
612 return (unsigned short)datum;
615 static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
616 short datum, unsigned int chan)
618 struct pci230_private *devpriv = dev->private;
620 /* Store unmangled datum to be read back later. */
621 devpriv->ao_readback[chan] = datum;
623 /* Write mangled datum to appropriate DACOUT register. */
624 outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
630 static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
633 struct pci230_private *devpriv = dev->private;
635 /* Store unmangled datum to be read back later. */
636 devpriv->ao_readback[chan] = datum;
638 /* Write mangled datum to appropriate DACDATA register. */
639 outw(pci230_ao_mangle_datum(dev, datum),
640 dev->iobase + PCI230P2_DACDATA);
643 static int get_resources(struct comedi_device *dev, unsigned int res_mask,
646 struct pci230_private *devpriv = dev->private;
650 unsigned int claimed;
651 unsigned long irqflags;
655 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
656 for (b = 1, i = 0; (i < NUM_RESOURCES)
657 && (res_mask != 0); b <<= 1, i++) {
658 if ((res_mask & b) != 0) {
660 if (devpriv->res_owner[i] == OWNER_NONE) {
661 devpriv->res_owner[i] = owner;
663 } else if (devpriv->res_owner[i] != owner) {
664 for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
665 if ((claimed & b) != 0) {
666 devpriv->res_owner[i]
676 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
680 static inline int get_one_resource(struct comedi_device *dev,
681 unsigned int resource, unsigned char owner)
683 return get_resources(dev, (1U << resource), owner);
686 static void put_resources(struct comedi_device *dev, unsigned int res_mask,
689 struct pci230_private *devpriv = dev->private;
692 unsigned long irqflags;
694 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
695 for (b = 1, i = 0; (i < NUM_RESOURCES)
696 && (res_mask != 0); b <<= 1, i++) {
697 if ((res_mask & b) != 0) {
699 if (devpriv->res_owner[i] == owner)
700 devpriv->res_owner[i] = OWNER_NONE;
704 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
707 static inline void put_one_resource(struct comedi_device *dev,
708 unsigned int resource, unsigned char owner)
710 put_resources(dev, (1U << resource), owner);
713 static inline void put_all_resources(struct comedi_device *dev,
716 put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
719 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
720 unsigned int round_mode)
726 rem = do_div(div, timebase);
727 round_mode &= TRIG_ROUND_MASK;
728 switch (round_mode) {
730 case TRIG_ROUND_NEAREST:
731 div += (rem + (timebase / 2)) / timebase;
733 case TRIG_ROUND_DOWN:
736 div += (rem + timebase - 1) / timebase;
739 return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
742 /* Given desired period in ns, returns the required internal clock source
743 * and gets the initial count. */
744 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
745 unsigned int round_mode)
747 unsigned int clk_src, cnt;
749 for (clk_src = CLK_10MHZ;; clk_src++) {
750 cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
751 if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
759 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
762 unsigned int clk_src;
764 clk_src = pci230_choose_clk_count(*ns, &count, round);
765 *ns = count * pci230_timebase[clk_src];
769 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
770 unsigned int mode, uint64_t ns,
773 struct pci230_private *devpriv = dev->private;
774 unsigned int clk_src;
778 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
779 /* Determine clock source and count. */
780 clk_src = pci230_choose_clk_count(ns, &count, round);
781 /* Program clock source. */
782 outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
783 /* Set initial count. */
787 i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
790 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
792 struct pci230_private *devpriv = dev->private;
794 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
796 /* Counter ct, 8254 mode 1, initial count not written. */
800 * COMEDI_SUBD_AI instruction;
802 static int pci230_ai_rinsn(struct comedi_device *dev,
803 struct comedi_subdevice *s, struct comedi_insn *insn,
806 struct pci230_private *devpriv = dev->private;
808 unsigned int chan, range, aref;
809 unsigned int gainshift;
811 unsigned short adccon, adcen;
813 /* Unpack channel and range. */
814 chan = CR_CHAN(insn->chanspec);
815 range = CR_RANGE(insn->chanspec);
816 aref = CR_AREF(insn->chanspec);
817 if (aref == AREF_DIFF) {
819 if (chan >= s->n_chan / 2) {
820 DPRINTK("comedi%d: amplc_pci230: ai_rinsn: "
821 "differential channel number out of range "
822 "0 to %u\n", dev->minor, (s->n_chan / 2) - 1);
827 /* Use Z2-CT2 as a conversion trigger instead of the built-in
828 * software trigger, as otherwise triggering of differential channels
829 * doesn't work properly for some versions of PCI230/260. Also set
830 * FIFO mode because the ADC busy bit only works for software triggers.
832 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
833 /* Set Z2-CT2 output low to avoid any false triggers. */
834 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
835 devpriv->ai_bipolar = pci230_ai_bipolar[range];
836 if (aref == AREF_DIFF) {
838 gainshift = chan * 2;
839 if (devpriv->hwver == 0) {
840 /* Original PCI230/260 expects both inputs of the
841 * differential channel to be enabled. */
842 adcen = 3 << gainshift;
844 /* PCI230+/260+ expects only one input of the
845 * differential channel to be enabled. */
846 adcen = 1 << gainshift;
848 adccon |= PCI230_ADC_IM_DIF;
852 gainshift = chan & ~1;
853 adccon |= PCI230_ADC_IM_SE;
855 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
856 | (pci230_ai_gain[range] << gainshift);
857 if (devpriv->ai_bipolar)
858 adccon |= PCI230_ADC_IR_BIP;
860 adccon |= PCI230_ADC_IR_UNI;
863 /* Enable only this channel in the scan list - otherwise by default
864 * we'll get one sample from each channel. */
865 outw(adcen, dev->iobase + PCI230_ADCEN);
867 /* Set gain for channel. */
868 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
870 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
871 devpriv->adccon = adccon;
872 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
874 /* Convert n samples */
875 for (n = 0; n < insn->n; n++) {
876 /* Trigger conversion by toggling Z2-CT2 output (finish with
878 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
880 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
884 /* wait for conversion to end */
885 for (i = 0; i < TIMEOUT; i++) {
886 status = inw(dev->iobase + PCI230_ADCCON);
887 if (!(status & PCI230_ADC_FIFO_EMPTY))
892 dev_err(dev->class_dev, "timeout\n");
897 data[n] = pci230_ai_read(dev);
900 /* return the number of samples read/written */
905 * COMEDI_SUBD_AO instructions;
907 static int pci230_ao_winsn(struct comedi_device *dev,
908 struct comedi_subdevice *s, struct comedi_insn *insn,
911 struct pci230_private *devpriv = dev->private;
915 /* Unpack channel and range. */
916 chan = CR_CHAN(insn->chanspec);
917 range = CR_RANGE(insn->chanspec);
919 /* Set range - see analogue output range table; 0 => unipolar 10V,
920 * 1 => bipolar +/-10V range scale */
921 devpriv->ao_bipolar = pci230_ao_bipolar[range];
922 outw(range, dev->iobase + PCI230_DACCON);
924 /* Writing a list of values to an AO channel is probably not
925 * very useful, but that's how the interface is defined. */
926 for (i = 0; i < insn->n; i++) {
927 /* Write value to DAC and store it. */
928 pci230_ao_write_nofifo(dev, data[i], chan);
931 /* return the number of samples read/written */
935 /* AO subdevices should have a read insn as well as a write insn.
936 * Usually this means copying a value stored in devpriv. */
937 static int pci230_ao_rinsn(struct comedi_device *dev,
938 struct comedi_subdevice *s, struct comedi_insn *insn,
941 struct pci230_private *devpriv = dev->private;
943 int chan = CR_CHAN(insn->chanspec);
945 for (i = 0; i < insn->n; i++)
946 data[i] = devpriv->ao_readback[chan];
951 static int pci230_ao_cmdtest(struct comedi_device *dev,
952 struct comedi_subdevice *s, struct comedi_cmd *cmd)
954 const struct pci230_board *thisboard = comedi_board(dev);
955 struct pci230_private *devpriv = dev->private;
959 /* Step 1 : check if triggers are trivially valid */
961 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
963 tmp = TRIG_TIMER | TRIG_INT;
964 if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
966 * For PCI230+ hardware version 2 onwards, allow external
967 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
969 * FIXME: The permitted scan_begin_src values shouldn't depend
970 * on devpriv->hwver (the detected card's actual hardware
971 * version). They should only depend on thisboard->min_hwver
972 * (the static capabilities of the configured card). To fix
973 * it, a new card model, e.g. "pci230+2" would have to be
974 * defined with min_hwver set to 2. It doesn't seem worth it
975 * for this alone. At the moment, please consider
976 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
981 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
983 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
984 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
985 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
990 /* Step 2a : make sure trigger sources are unique */
992 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
993 err |= cfc_check_trigger_is_unique(cmd->stop_src);
995 /* Step 2b : and mutually compatible */
1000 /* Step 3: check if arguments are trivially valid */
1002 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1004 #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */
1005 #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */
1006 /*- Comedi limit due to unsigned int cmd. Driver limit
1007 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1008 * clock) = 65.536s */
1010 switch (cmd->scan_begin_src) {
1012 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1014 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
1018 /* External trigger - for PCI230+ hardware version 2 onwards. */
1019 /* Trigger number must be 0. */
1020 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1021 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1025 /* The only flags allowed are CR_EDGE and CR_INVERT. The
1026 * CR_EDGE flag is ignored. */
1027 if ((cmd->scan_begin_arg
1028 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1029 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1031 ~(CR_EDGE | CR_INVERT));
1036 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1040 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1042 if (cmd->stop_src == TRIG_NONE)
1043 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1048 /* Step 4: fix up any arguments.
1049 * "argument conflict" returned by comedilib to user mode process
1052 if (cmd->scan_begin_src == TRIG_TIMER) {
1053 tmp = cmd->scan_begin_arg;
1054 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1055 cmd->flags & TRIG_ROUND_MASK);
1056 if (tmp != cmd->scan_begin_arg)
1063 /* Step 5: check channel list if it exists. */
1065 if (cmd->chanlist && cmd->chanlist_len > 0) {
1068 range_err = (1 << 1)
1070 unsigned int errors;
1072 unsigned int chan, prev_chan;
1073 unsigned int range, first_range;
1075 prev_chan = CR_CHAN(cmd->chanlist[0]);
1076 first_range = CR_RANGE(cmd->chanlist[0]);
1078 for (n = 1; n < cmd->chanlist_len; n++) {
1079 chan = CR_CHAN(cmd->chanlist[n]);
1080 range = CR_RANGE(cmd->chanlist[n]);
1081 /* Channel numbers must strictly increase. */
1082 if (chan < prev_chan)
1085 /* Ranges must be the same. */
1086 if (range != first_range)
1087 errors |= range_err;
1093 if ((errors & seq_err) != 0) {
1094 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1095 "channel numbers must increase\n",
1098 if ((errors & range_err) != 0) {
1099 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1100 "channels must have the same range\n",
1112 static void pci230_ao_stop(struct comedi_device *dev,
1113 struct comedi_subdevice *s)
1115 struct pci230_private *devpriv = dev->private;
1116 unsigned long irqflags;
1117 unsigned char intsrc;
1119 struct comedi_cmd *cmd;
1121 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1122 started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
1123 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1126 cmd = &s->async->cmd;
1127 if (cmd->scan_begin_src == TRIG_TIMER) {
1128 /* Stop scan rate generator. */
1129 pci230_cancel_ct(dev, 1);
1131 /* Determine interrupt source. */
1132 if (devpriv->hwver < 2) {
1133 /* Not using DAC FIFO. Using CT1 interrupt. */
1134 intsrc = PCI230_INT_ZCLK_CT1;
1136 /* Using DAC FIFO interrupt. */
1137 intsrc = PCI230P2_INT_DAC;
1139 /* Disable interrupt and wait for interrupt routine to finish running
1140 * unless we are called from the interrupt routine. */
1141 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1142 devpriv->int_en &= ~intsrc;
1143 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
1144 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1145 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1147 if (devpriv->ier != devpriv->int_en) {
1148 devpriv->ier = devpriv->int_en;
1149 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1151 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1152 if (devpriv->hwver >= 2) {
1153 /* Using DAC FIFO. Reset FIFO, clear underrun error,
1155 devpriv->daccon &= PCI230_DAC_OR_MASK;
1156 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
1157 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
1158 dev->iobase + PCI230_DACCON);
1160 /* Release resources. */
1161 put_all_resources(dev, OWNER_AOCMD);
1164 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
1165 struct comedi_subdevice *s)
1167 struct pci230_private *devpriv = dev->private;
1170 struct comedi_async *async = s->async;
1171 struct comedi_cmd *cmd = &async->cmd;
1173 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
1175 for (i = 0; i < cmd->chanlist_len; i++) {
1176 /* Read sample from Comedi's circular buffer. */
1177 ret = comedi_buf_get(s->async, &data);
1179 s->async->events |= COMEDI_CB_OVERFLOW;
1180 pci230_ao_stop(dev, s);
1181 comedi_error(dev, "AO buffer underrun");
1184 /* Write value to DAC. */
1185 pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
1187 async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
1188 if (!devpriv->ao_continuous) {
1189 devpriv->ao_scan_count--;
1190 if (devpriv->ao_scan_count == 0) {
1191 /* End of acquisition. */
1192 async->events |= COMEDI_CB_EOA;
1193 pci230_ao_stop(dev, s);
1198 /* Loads DAC FIFO (if using it) from buffer. */
1199 /* Returns 0 if AO finished due to completion or error, 1 if still going. */
1200 static int pci230_handle_ao_fifo(struct comedi_device *dev,
1201 struct comedi_subdevice *s)
1203 struct pci230_private *devpriv = dev->private;
1204 struct comedi_async *async = s->async;
1205 struct comedi_cmd *cmd = &async->cmd;
1206 unsigned int num_scans;
1208 unsigned short dacstat;
1210 unsigned int bytes_per_scan;
1211 unsigned int events = 0;
1214 /* Get DAC FIFO status. */
1215 dacstat = inw(dev->iobase + PCI230_DACCON);
1216 /* Determine number of scans available in buffer. */
1217 bytes_per_scan = cmd->chanlist_len * sizeof(short);
1218 num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
1219 if (!devpriv->ao_continuous) {
1220 /* Fixed number of scans. */
1221 if (num_scans > devpriv->ao_scan_count)
1222 num_scans = devpriv->ao_scan_count;
1223 if (devpriv->ao_scan_count == 0) {
1224 /* End of acquisition. */
1225 events |= COMEDI_CB_EOA;
1229 /* Check for FIFO underrun. */
1230 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
1231 comedi_error(dev, "AO FIFO underrun");
1232 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1234 /* Check for buffer underrun if FIFO less than half full
1235 * (otherwise there will be loads of "DAC FIFO not half full"
1237 if ((num_scans == 0)
1238 && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
1239 comedi_error(dev, "AO buffer underrun");
1240 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1244 /* Determine how much room is in the FIFO (in samples). */
1245 if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
1246 room = PCI230P2_DAC_FIFOROOM_FULL;
1247 else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
1248 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
1249 else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
1250 room = PCI230P2_DAC_FIFOROOM_EMPTY;
1252 room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
1253 /* Convert room to number of scans that can be added. */
1254 room /= cmd->chanlist_len;
1255 /* Determine number of scans to process. */
1256 if (num_scans > room)
1258 /* Process scans. */
1259 for (n = 0; n < num_scans; n++) {
1260 for (i = 0; i < cmd->chanlist_len; i++) {
1263 comedi_buf_get(async, &datum);
1264 pci230_ao_write_fifo(dev, datum,
1265 CR_CHAN(cmd->chanlist[i]));
1268 events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
1269 if (!devpriv->ao_continuous) {
1270 devpriv->ao_scan_count -= num_scans;
1271 if (devpriv->ao_scan_count == 0) {
1272 /* All data for the command has been written
1273 * to FIFO. Set FIFO interrupt trigger level
1275 devpriv->daccon = (devpriv->daccon
1277 ~PCI230P2_DAC_INT_FIFO_MASK)
1278 | PCI230P2_DAC_INT_FIFO_EMPTY;
1279 outw(devpriv->daccon,
1280 dev->iobase + PCI230_DACCON);
1283 /* Check if FIFO underrun occurred while writing to FIFO. */
1284 dacstat = inw(dev->iobase + PCI230_DACCON);
1285 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
1286 comedi_error(dev, "AO FIFO underrun");
1287 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1290 if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
1292 /* Stopping AO due to completion or error. */
1293 pci230_ao_stop(dev, s);
1298 async->events |= events;
1302 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1303 struct comedi_subdevice *s,
1304 unsigned int trig_num)
1306 struct pci230_private *devpriv = dev->private;
1307 unsigned long irqflags;
1312 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1313 if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
1315 if (devpriv->hwver < 2) {
1316 /* Not using DAC FIFO. */
1317 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1319 pci230_handle_ao_nofifo(dev, s);
1320 comedi_event(dev, s);
1322 /* Using DAC FIFO. */
1323 /* Read DACSWTRIG register to trigger conversion. */
1324 inw(dev->iobase + PCI230P2_DACSWTRIG);
1325 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1328 /* Delay. Should driver be responsible for this? */
1329 /* XXX TODO: See if DAC busy bit can be used. */
1332 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1338 static void pci230_ao_start(struct comedi_device *dev,
1339 struct comedi_subdevice *s)
1341 struct pci230_private *devpriv = dev->private;
1342 struct comedi_async *async = s->async;
1343 struct comedi_cmd *cmd = &async->cmd;
1344 unsigned long irqflags;
1346 set_bit(AO_CMD_STARTED, &devpriv->state);
1347 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1348 /* An empty acquisition! */
1349 async->events |= COMEDI_CB_EOA;
1350 pci230_ao_stop(dev, s);
1351 comedi_event(dev, s);
1353 if (devpriv->hwver >= 2) {
1354 /* Using DAC FIFO. */
1355 unsigned short scantrig;
1358 /* Preload FIFO data. */
1359 run = pci230_handle_ao_fifo(dev, s);
1360 comedi_event(dev, s);
1365 /* Set scan trigger source. */
1366 switch (cmd->scan_begin_src) {
1368 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1371 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1372 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1374 scantrig = PCI230P2_DAC_TRIG_EXTP;
1377 scantrig = PCI230P2_DAC_TRIG_EXTN;
1381 scantrig = PCI230P2_DAC_TRIG_SW;
1384 /* Shouldn't get here. */
1385 scantrig = PCI230P2_DAC_TRIG_NONE;
1388 devpriv->daccon = (devpriv->daccon
1389 & ~PCI230P2_DAC_TRIG_MASK) |
1391 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1394 switch (cmd->scan_begin_src) {
1396 if (devpriv->hwver < 2) {
1397 /* Not using DAC FIFO. */
1398 /* Enable CT1 timer interrupt. */
1399 spin_lock_irqsave(&devpriv->isr_spinlock,
1401 devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1402 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1404 devpriv->iobase1 + PCI230_INT_SCE);
1405 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1408 /* Set CT1 gate high to start counting. */
1409 outb(GAT_CONFIG(1, GAT_VCC),
1410 devpriv->iobase1 + PCI230_ZGAT_SCE);
1413 async->inttrig = pci230_ao_inttrig_scan_begin;
1416 if (devpriv->hwver >= 2) {
1417 /* Using DAC FIFO. Enable DAC FIFO interrupt. */
1418 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1419 devpriv->int_en |= PCI230P2_INT_DAC;
1420 devpriv->ier |= PCI230P2_INT_DAC;
1421 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1422 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1428 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1429 struct comedi_subdevice *s,
1430 unsigned int trig_num)
1435 s->async->inttrig = NULL;
1436 pci230_ao_start(dev, s);
1441 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1443 struct pci230_private *devpriv = dev->private;
1444 unsigned short daccon;
1447 /* Get the command. */
1448 struct comedi_cmd *cmd = &s->async->cmd;
1450 if (cmd->scan_begin_src == TRIG_TIMER) {
1452 if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
1457 /* Get number of scans required. */
1458 if (cmd->stop_src == TRIG_COUNT) {
1459 devpriv->ao_scan_count = cmd->stop_arg;
1460 devpriv->ao_continuous = 0;
1462 /* TRIG_NONE, user calls cancel. */
1463 devpriv->ao_scan_count = 0;
1464 devpriv->ao_continuous = 1;
1467 /* Set range - see analogue output range table; 0 => unipolar 10V,
1468 * 1 => bipolar +/-10V range scale */
1469 range = CR_RANGE(cmd->chanlist[0]);
1470 devpriv->ao_bipolar = pci230_ao_bipolar[range];
1471 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1472 /* Use DAC FIFO for hardware version 2 onwards. */
1473 if (devpriv->hwver >= 2) {
1474 unsigned short dacen;
1478 for (i = 0; i < cmd->chanlist_len; i++)
1479 dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1481 /* Set channel scan list. */
1482 outw(dacen, dev->iobase + PCI230P2_DACEN);
1485 * Set DAC scan source to 'none'.
1486 * Set DAC FIFO interrupt trigger level to 'not half full'.
1487 * Reset DAC FIFO and clear underrun.
1489 * N.B. DAC FIFO interrupts are currently disabled.
1491 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1492 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1493 | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1497 outw(daccon, dev->iobase + PCI230_DACCON);
1498 /* Preserve most of DACCON apart from write-only, transient bits. */
1499 devpriv->daccon = daccon
1500 & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1502 if (cmd->scan_begin_src == TRIG_TIMER) {
1503 /* Set the counter timer 1 to the specified scan frequency. */
1504 /* cmd->scan_begin_arg is sampling period in ns */
1505 /* gate it off for now. */
1506 outb(GAT_CONFIG(1, GAT_GND),
1507 devpriv->iobase1 + PCI230_ZGAT_SCE);
1508 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1509 cmd->scan_begin_arg,
1510 cmd->flags & TRIG_ROUND_MASK);
1513 /* N.B. cmd->start_src == TRIG_INT */
1514 s->async->inttrig = pci230_ao_inttrig_start;
1519 static int pci230_ao_cancel(struct comedi_device *dev,
1520 struct comedi_subdevice *s)
1522 pci230_ao_stop(dev, s);
1526 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1528 unsigned int min_scan_period, chanlist_len;
1531 chanlist_len = cmd->chanlist_len;
1532 if (cmd->chanlist_len == 0)
1535 min_scan_period = chanlist_len * cmd->convert_arg;
1536 if ((min_scan_period < chanlist_len)
1537 || (min_scan_period < cmd->convert_arg)) {
1538 /* Arithmetic overflow. */
1539 min_scan_period = UINT_MAX;
1542 if (cmd->scan_begin_arg < min_scan_period) {
1543 cmd->scan_begin_arg = min_scan_period;
1550 static int pci230_ai_cmdtest(struct comedi_device *dev,
1551 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1553 const struct pci230_board *thisboard = comedi_board(dev);
1554 struct pci230_private *devpriv = dev->private;
1558 /* Step 1 : check if triggers are trivially valid */
1560 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1562 tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1563 if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1565 * Unfortunately, we cannot trigger a scan off an external
1566 * source on the PCI260 board, since it uses the PPIC0 (DIO)
1567 * input, which isn't present on the PCI260. For PCI260+
1568 * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead.
1572 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
1573 err |= cfc_check_trigger_src(&cmd->convert_src,
1574 TRIG_TIMER | TRIG_INT | TRIG_EXT);
1575 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1576 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1581 /* Step 2a : make sure trigger sources are unique */
1583 err |= cfc_check_trigger_is_unique(cmd->start_src);
1584 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1585 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1586 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1588 /* Step 2b : and mutually compatible */
1591 * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1592 * set up to generate a fixed number of timed conversion pulses.
1594 if ((cmd->scan_begin_src != TRIG_FOLLOW)
1595 && (cmd->convert_src != TRIG_TIMER))
1601 /* Step 3: check if arguments are trivially valid */
1603 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1605 #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */
1606 #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */
1607 #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */
1608 #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */
1609 /*- Comedi limit due to unsigned int cmd. Driver limit
1610 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1611 * clock) = 65.536s */
1613 if (cmd->convert_src == TRIG_TIMER) {
1614 unsigned int max_speed_ai;
1616 if (devpriv->hwver == 0) {
1617 /* PCI230 or PCI260. Max speed depends whether
1618 * single-ended or pseudo-differential. */
1619 if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1620 /* Peek analogue reference of first channel. */
1621 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1622 max_speed_ai = MAX_SPEED_AI_DIFF;
1624 max_speed_ai = MAX_SPEED_AI_SE;
1627 /* No channel list. Assume single-ended. */
1628 max_speed_ai = MAX_SPEED_AI_SE;
1631 /* PCI230+ or PCI260+. */
1632 max_speed_ai = MAX_SPEED_AI_PLUS;
1635 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1637 err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
1639 } else if (cmd->convert_src == TRIG_EXT) {
1643 * convert_arg == (CR_EDGE | 0)
1644 * => trigger on +ve edge.
1645 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1646 * => trigger on -ve edge.
1648 if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1649 /* Trigger number must be 0. */
1650 if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1651 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1655 /* The only flags allowed are CR_INVERT and CR_EDGE.
1656 * CR_EDGE is required. */
1657 if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1659 /* Set CR_EDGE, preserve CR_INVERT. */
1660 cmd->convert_arg = COMBINE(cmd->start_arg,
1667 /* Backwards compatibility with previous versions. */
1668 /* convert_arg == 0 => trigger on -ve edge. */
1669 /* convert_arg == 1 => trigger on +ve edge. */
1670 err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1);
1673 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1676 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1678 if (cmd->stop_src == TRIG_NONE)
1679 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1681 if (cmd->scan_begin_src == TRIG_EXT) {
1682 /* external "trigger" to begin each scan
1683 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1684 * of CT2 (sample convert trigger is CT2) */
1685 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1686 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1690 /* The only flag allowed is CR_EDGE, which is ignored. */
1691 if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1692 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1693 CR_FLAGS_MASK & ~CR_EDGE);
1696 } else if (cmd->scan_begin_src == TRIG_TIMER) {
1697 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1698 if (!pci230_ai_check_scan_period(cmd))
1702 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1708 /* Step 4: fix up any arguments.
1709 * "argument conflict" returned by comedilib to user mode process
1712 if (cmd->convert_src == TRIG_TIMER) {
1713 tmp = cmd->convert_arg;
1714 pci230_ns_to_single_timer(&cmd->convert_arg,
1715 cmd->flags & TRIG_ROUND_MASK);
1716 if (tmp != cmd->convert_arg)
1720 if (cmd->scan_begin_src == TRIG_TIMER) {
1721 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1722 tmp = cmd->scan_begin_arg;
1723 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1724 cmd->flags & TRIG_ROUND_MASK);
1725 if (!pci230_ai_check_scan_period(cmd)) {
1726 /* Was below minimum required. Round up. */
1727 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1729 pci230_ai_check_scan_period(cmd);
1731 if (tmp != cmd->scan_begin_arg)
1738 /* Step 5: check channel list if it exists. */
1740 if (cmd->chanlist && cmd->chanlist_len > 0) {
1743 rangepair_err = 1 << 1,
1744 polarity_err = 1 << 2,
1746 diffchan_err = 1 << 4,
1747 buggy_chan0_err = 1 << 5
1749 unsigned int errors;
1750 unsigned int chan, prev_chan;
1751 unsigned int range, prev_range;
1752 unsigned int polarity, prev_polarity;
1753 unsigned int aref, prev_aref;
1754 unsigned int subseq_len;
1759 prev_chan = prev_aref = prev_range = prev_polarity = 0;
1760 for (n = 0; n < cmd->chanlist_len; n++) {
1761 chan = CR_CHAN(cmd->chanlist[n]);
1762 range = CR_RANGE(cmd->chanlist[n]);
1763 aref = CR_AREF(cmd->chanlist[n]);
1764 polarity = pci230_ai_bipolar[range];
1765 /* Only the first half of the channels are available if
1766 * differential. (These are remapped in software. In
1767 * hardware, only the even channels are available.) */
1768 if ((aref == AREF_DIFF)
1769 && (chan >= (s->n_chan / 2))) {
1770 errors |= diffchan_err;
1773 /* Channel numbers must strictly increase or
1774 * subsequence must repeat exactly. */
1775 if ((chan <= prev_chan)
1776 && (subseq_len == 0)) {
1779 if ((subseq_len > 0)
1780 && (cmd->chanlist[n] !=
1781 cmd->chanlist[n % subseq_len])) {
1784 /* Channels must have same AREF. */
1785 if (aref != prev_aref)
1788 /* Channel ranges must have same polarity. */
1789 if (polarity != prev_polarity)
1790 errors |= polarity_err;
1792 /* Single-ended channel pairs must have same
1794 if ((aref != AREF_DIFF)
1795 && (((chan ^ prev_chan) & ~1) == 0)
1796 && (range != prev_range)) {
1797 errors |= rangepair_err;
1803 prev_polarity = polarity;
1805 if (subseq_len == 0) {
1806 /* Subsequence is whole sequence. */
1809 /* If channel list is a repeating subsequence, need a whole
1810 * number of repeats. */
1811 if ((n % subseq_len) != 0)
1814 if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
1816 * Buggy PCI230+ or PCI260+ requires channel 0 to be
1817 * (first) in the sequence if the sequence contains
1818 * more than one channel. Hardware versions 1 and 2
1819 * have the bug. There is no hardware version 3.
1821 * Actually, there are two firmwares that report
1822 * themselves as hardware version 1 (the boards
1823 * have different ADC chips with slightly different
1824 * timing requirements, which was supposed to be
1825 * invisible to software). The first one doesn't
1826 * seem to have the bug, but the second one
1827 * does, and we can't tell them apart!
1829 if ((subseq_len > 1)
1830 && (CR_CHAN(cmd->chanlist[0]) != 0)) {
1831 errors |= buggy_chan0_err;
1836 if ((errors & seq_err) != 0) {
1837 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1838 "channel numbers must increase or "
1839 "sequence must repeat exactly\n",
1842 if ((errors & rangepair_err) != 0) {
1843 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1844 "single-ended channel pairs must "
1845 "have the same range\n", dev->minor);
1847 if ((errors & polarity_err) != 0) {
1848 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1849 "channel sequence ranges must be all "
1850 "bipolar or all unipolar\n",
1853 if ((errors & aref_err) != 0) {
1854 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1855 "channel sequence analogue references "
1856 "must be all the same (single-ended "
1857 "or differential)\n", dev->minor);
1859 if ((errors & diffchan_err) != 0) {
1860 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1861 "differential channel number out of "
1862 "range 0 to %u\n", dev->minor,
1863 (s->n_chan / 2) - 1);
1865 if ((errors & buggy_chan0_err) != 0) {
1866 dev_info(dev->class_dev,
1867 "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",
1879 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
1880 struct comedi_subdevice *s)
1882 struct pci230_private *devpriv = dev->private;
1883 struct comedi_cmd *cmd = &s->async->cmd;
1884 unsigned int scanlen = cmd->scan_end_arg;
1886 unsigned short triglev;
1887 unsigned short adccon;
1889 if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
1890 /* Wake at end of scan. */
1891 wake = scanlen - devpriv->ai_scan_pos;
1893 if (devpriv->ai_continuous
1894 || (devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL)
1895 || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
1896 wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
1898 wake = (devpriv->ai_scan_count * scanlen)
1899 - devpriv->ai_scan_pos;
1902 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
1903 triglev = PCI230_ADC_INT_FIFO_HALF;
1905 if ((wake > 1) && (devpriv->hwver > 0)) {
1906 /* PCI230+/260+ programmable FIFO interrupt level. */
1907 if (devpriv->adcfifothresh != wake) {
1908 devpriv->adcfifothresh = wake;
1909 outw(wake, dev->iobase + PCI230P_ADCFFTH);
1911 triglev = PCI230P_ADC_INT_FIFO_THRESH;
1913 triglev = PCI230_ADC_INT_FIFO_NEMPTY;
1916 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
1917 if (adccon != devpriv->adccon) {
1918 devpriv->adccon = adccon;
1919 outw(adccon, dev->iobase + PCI230_ADCCON);
1923 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
1924 struct comedi_subdevice *s,
1925 unsigned int trig_num)
1927 struct pci230_private *devpriv = dev->private;
1928 unsigned long irqflags;
1933 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1934 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1935 unsigned int delayus;
1937 /* Trigger conversion by toggling Z2-CT2 output. Finish
1938 * with output high. */
1939 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1941 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1943 /* Delay. Should driver be responsible for this? An
1944 * alternative would be to wait until conversion is complete,
1945 * but we can't tell when it's complete because the ADC busy
1946 * bit has a different meaning when FIFO enabled (and when
1947 * FIFO not enabled, it only works for software triggers). */
1948 if (((devpriv->adccon & PCI230_ADC_IM_MASK)
1949 == PCI230_ADC_IM_DIF)
1950 && (devpriv->hwver == 0)) {
1951 /* PCI230/260 in differential mode */
1954 /* single-ended or PCI230+/260+ */
1957 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1960 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1966 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
1967 struct comedi_subdevice *s,
1968 unsigned int trig_num)
1970 struct pci230_private *devpriv = dev->private;
1971 unsigned long irqflags;
1977 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1978 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1979 /* Trigger scan by waggling CT0 gate source. */
1980 zgat = GAT_CONFIG(0, GAT_GND);
1981 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1982 zgat = GAT_CONFIG(0, GAT_VCC);
1983 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1985 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1990 static void pci230_ai_stop(struct comedi_device *dev,
1991 struct comedi_subdevice *s)
1993 struct pci230_private *devpriv = dev->private;
1994 unsigned long irqflags;
1995 struct comedi_cmd *cmd;
1998 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1999 started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
2000 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2003 cmd = &s->async->cmd;
2004 if (cmd->convert_src == TRIG_TIMER) {
2005 /* Stop conversion rate generator. */
2006 pci230_cancel_ct(dev, 2);
2008 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2009 /* Stop scan period monostable. */
2010 pci230_cancel_ct(dev, 0);
2012 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2013 /* Disable ADC interrupt and wait for interrupt routine to finish
2014 * running unless we are called from the interrupt routine. */
2015 devpriv->int_en &= ~PCI230_INT_ADC;
2016 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2017 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2018 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2020 if (devpriv->ier != devpriv->int_en) {
2021 devpriv->ier = devpriv->int_en;
2022 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2024 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2025 /* Reset FIFO, disable FIFO and set start conversion source to none.
2026 * Keep se/diff and bip/uni settings */
2027 devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
2028 | PCI230_ADC_IM_MASK)) |
2029 PCI230_ADC_TRIG_NONE;
2030 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2031 dev->iobase + PCI230_ADCCON);
2032 /* Release resources. */
2033 put_all_resources(dev, OWNER_AICMD);
2036 static void pci230_ai_start(struct comedi_device *dev,
2037 struct comedi_subdevice *s)
2039 struct pci230_private *devpriv = dev->private;
2040 unsigned long irqflags;
2041 unsigned short conv;
2042 struct comedi_async *async = s->async;
2043 struct comedi_cmd *cmd = &async->cmd;
2045 set_bit(AI_CMD_STARTED, &devpriv->state);
2046 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2047 /* An empty acquisition! */
2048 async->events |= COMEDI_CB_EOA;
2049 pci230_ai_stop(dev, s);
2050 comedi_event(dev, s);
2052 /* Enable ADC FIFO trigger level interrupt. */
2053 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2054 devpriv->int_en |= PCI230_INT_ADC;
2055 devpriv->ier |= PCI230_INT_ADC;
2056 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2057 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2059 /* Update conversion trigger source which is currently set
2060 * to CT2 output, which is currently stuck high. */
2061 switch (cmd->convert_src) {
2063 conv = PCI230_ADC_TRIG_NONE;
2066 /* Using CT2 output. */
2067 conv = PCI230_ADC_TRIG_Z2CT2;
2070 if ((cmd->convert_arg & CR_EDGE) != 0) {
2071 if ((cmd->convert_arg & CR_INVERT) == 0) {
2072 /* Trigger on +ve edge. */
2073 conv = PCI230_ADC_TRIG_EXTP;
2075 /* Trigger on -ve edge. */
2076 conv = PCI230_ADC_TRIG_EXTN;
2079 /* Backwards compatibility. */
2080 if (cmd->convert_arg != 0) {
2081 /* Trigger on +ve edge. */
2082 conv = PCI230_ADC_TRIG_EXTP;
2084 /* Trigger on -ve edge. */
2085 conv = PCI230_ADC_TRIG_EXTN;
2090 /* Use CT2 output for software trigger due to problems
2091 * in differential mode on PCI230/260. */
2092 conv = PCI230_ADC_TRIG_Z2CT2;
2095 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
2097 outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
2098 if (cmd->convert_src == TRIG_INT)
2099 async->inttrig = pci230_ai_inttrig_convert;
2101 /* Update FIFO interrupt trigger level, which is currently
2103 pci230_ai_update_fifo_trigger_level(dev, s);
2104 if (cmd->convert_src == TRIG_TIMER) {
2105 /* Update timer gates. */
2108 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2109 /* Conversion timer CT2 needs to be gated by
2110 * inverted output of monostable CT2. */
2111 zgat = GAT_CONFIG(2, GAT_NOUTNM2);
2113 /* Conversion timer CT2 needs to be gated on
2115 zgat = GAT_CONFIG(2, GAT_VCC);
2117 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2118 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2119 /* Set monostable CT0 trigger source. */
2120 switch (cmd->scan_begin_src) {
2122 zgat = GAT_CONFIG(0, GAT_VCC);
2126 * For CT0 on PCI230, the external
2127 * trigger (gate) signal comes from
2128 * PPC0, which is channel 16 of the DIO
2129 * subdevice. The application needs to
2130 * configure this as an input in order
2131 * to use it as an external scan
2134 zgat = GAT_CONFIG(0, GAT_EXT);
2138 * Monostable CT0 triggered by rising
2139 * edge on inverted output of CT1
2140 * (falling edge on CT1).
2142 zgat = GAT_CONFIG(0, GAT_NOUTNM2);
2146 * Monostable CT0 is triggered by
2147 * inttrig function waggling the CT0
2150 zgat = GAT_CONFIG(0, GAT_VCC);
2153 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2154 switch (cmd->scan_begin_src) {
2156 /* Scan period timer CT1 needs to be
2157 * gated on to start counting. */
2158 zgat = GAT_CONFIG(1, GAT_VCC);
2159 outb(zgat, devpriv->iobase1
2164 pci230_ai_inttrig_scan_begin;
2168 } else if (cmd->convert_src != TRIG_INT) {
2169 /* No longer need Z2-CT2. */
2170 put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
2175 static int pci230_ai_inttrig_start(struct comedi_device *dev,
2176 struct comedi_subdevice *s,
2177 unsigned int trig_num)
2182 s->async->inttrig = NULL;
2183 pci230_ai_start(dev, s);
2188 static void pci230_handle_ai(struct comedi_device *dev,
2189 struct comedi_subdevice *s)
2191 struct pci230_private *devpriv = dev->private;
2192 unsigned int events = 0;
2193 unsigned int status_fifo;
2196 unsigned int fifoamount;
2197 struct comedi_async *async = s->async;
2198 unsigned int scanlen = async->cmd.scan_end_arg;
2200 /* Determine number of samples to read. */
2201 if (devpriv->ai_continuous) {
2202 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2203 } else if (devpriv->ai_scan_count == 0) {
2205 } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2206 || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2207 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2209 todo = (devpriv->ai_scan_count * scanlen)
2210 - devpriv->ai_scan_pos;
2211 if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
2212 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2217 for (i = 0; i < todo; i++) {
2218 if (fifoamount == 0) {
2219 /* Read FIFO state. */
2220 status_fifo = inw(dev->iobase + PCI230_ADCCON);
2221 if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2222 /* Report error otherwise FIFO overruns will go
2223 * unnoticed by the caller. */
2224 comedi_error(dev, "AI FIFO overrun");
2225 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2227 } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2230 } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2231 /* FIFO half full. */
2232 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2234 /* FIFO not empty. */
2235 if (devpriv->hwver > 0) {
2236 /* Read PCI230+/260+ ADC FIFO level. */
2237 fifoamount = inw(dev->iobase
2238 + PCI230P_ADCFFLEV);
2239 if (fifoamount == 0) {
2240 /* Shouldn't happen. */
2248 /* Read sample and store in Comedi's circular buffer. */
2249 if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2250 events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2251 comedi_error(dev, "AI buffer overflow");
2255 devpriv->ai_scan_pos++;
2256 if (devpriv->ai_scan_pos == scanlen) {
2258 devpriv->ai_scan_pos = 0;
2259 devpriv->ai_scan_count--;
2260 async->events |= COMEDI_CB_EOS;
2263 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2264 /* End of acquisition. */
2265 events |= COMEDI_CB_EOA;
2267 /* More samples required, tell Comedi to block. */
2268 events |= COMEDI_CB_BLOCK;
2270 async->events |= events;
2271 if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2272 COMEDI_CB_OVERFLOW)) != 0) {
2273 /* disable hardware conversions */
2274 pci230_ai_stop(dev, s);
2276 /* update FIFO interrupt trigger level */
2277 pci230_ai_update_fifo_trigger_level(dev, s);
2281 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2283 struct pci230_private *devpriv = dev->private;
2284 unsigned int i, chan, range, diff;
2285 unsigned int res_mask;
2286 unsigned short adccon, adcen;
2289 /* Get the command. */
2290 struct comedi_async *async = s->async;
2291 struct comedi_cmd *cmd = &async->cmd;
2294 * Determine which shared resources are needed.
2297 /* Need Z2-CT2 to supply a conversion trigger source at a high
2298 * logic level, even if not doing timed conversions. */
2299 res_mask |= (1U << RES_Z2CT2);
2300 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2301 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2302 res_mask |= (1U << RES_Z2CT0);
2303 if (cmd->scan_begin_src == TRIG_TIMER) {
2304 /* Using Z2-CT1 for scan frequency */
2305 res_mask |= (1U << RES_Z2CT1);
2308 /* Claim resources. */
2309 if (!get_resources(dev, res_mask, OWNER_AICMD))
2313 /* Get number of scans required. */
2314 if (cmd->stop_src == TRIG_COUNT) {
2315 devpriv->ai_scan_count = cmd->stop_arg;
2316 devpriv->ai_continuous = 0;
2318 /* TRIG_NONE, user calls cancel. */
2319 devpriv->ai_scan_count = 0;
2320 devpriv->ai_continuous = 1;
2322 devpriv->ai_scan_pos = 0; /* Position within scan. */
2325 * - Set channel scan list.
2326 * - Set channel gains.
2327 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2328 * start conversion source to point to something at a high logic
2329 * level (we use the output of counter/timer 2 for this purpose.
2330 * - PAUSE to allow things to settle down.
2331 * - Reset the FIFO again because it needs resetting twice and there
2332 * may have been a false conversion trigger on some versions of
2333 * PCI230/260 due to the start conversion source being set to a
2335 * - Enable ADC FIFO level interrupt.
2336 * - Set actual conversion trigger source and FIFO interrupt trigger
2338 * - If convert_src is TRIG_TIMER, set up the timers.
2341 adccon = PCI230_ADC_FIFO_EN;
2344 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2345 /* Differential - all channels must be differential. */
2347 adccon |= PCI230_ADC_IM_DIF;
2349 /* Single ended - all channels must be single-ended. */
2351 adccon |= PCI230_ADC_IM_SE;
2354 range = CR_RANGE(cmd->chanlist[0]);
2355 devpriv->ai_bipolar = pci230_ai_bipolar[range];
2356 if (devpriv->ai_bipolar)
2357 adccon |= PCI230_ADC_IR_BIP;
2359 adccon |= PCI230_ADC_IR_UNI;
2361 for (i = 0; i < cmd->chanlist_len; i++) {
2362 unsigned int gainshift;
2364 chan = CR_CHAN(cmd->chanlist[i]);
2365 range = CR_RANGE(cmd->chanlist[i]);
2367 gainshift = 2 * chan;
2368 if (devpriv->hwver == 0) {
2369 /* Original PCI230/260 expects both inputs of
2370 * the differential channel to be enabled. */
2371 adcen |= 3 << gainshift;
2373 /* PCI230+/260+ expects only one input of the
2374 * differential channel to be enabled. */
2375 adcen |= 1 << gainshift;
2378 gainshift = (chan & ~1);
2381 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2382 | (pci230_ai_gain[range] << gainshift);
2385 /* Set channel scan list. */
2386 outw(adcen, dev->iobase + PCI230_ADCEN);
2388 /* Set channel gains. */
2389 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2391 /* Set counter/timer 2 output high for use as the initial start
2392 * conversion source. */
2393 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2395 /* Temporarily use CT2 output as conversion trigger source and
2396 * temporarily set FIFO interrupt trigger level to 'full'. */
2397 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2399 /* Enable and reset FIFO, specify FIFO trigger level full, specify
2400 * uni/bip, se/diff, and temporarily set the start conversion source
2401 * to CT2 output. Note that CT2 output is currently high, and this
2402 * will produce a false conversion trigger on some versions of the
2403 * PCI230/260, but that will be dealt with later. */
2404 devpriv->adccon = adccon;
2405 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2408 /* Failure to include this will result in the first few channels'-worth
2409 * of data being corrupt, normally manifesting itself by large negative
2410 * voltages. It seems the board needs time to settle between the first
2411 * FIFO reset (above) and the second FIFO reset (below). Setting the
2412 * channel gains and scan list _before_ the first FIFO reset also
2413 * helps, though only slightly. */
2416 /* Reset FIFO again. */
2417 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2419 if (cmd->convert_src == TRIG_TIMER) {
2420 /* Set up CT2 as conversion timer, but gate it off for now.
2421 * Note, counter/timer output 2 can be monitored on the
2422 * connector: PCI230 pin 21, PCI260 pin 18. */
2423 zgat = GAT_CONFIG(2, GAT_GND);
2424 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2425 /* Set counter/timer 2 to the specified conversion period. */
2426 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2427 cmd->flags & TRIG_ROUND_MASK);
2428 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2430 * Set up monostable on CT0 output for scan timing. A
2431 * rising edge on the trigger (gate) input of CT0 will
2432 * trigger the monostable, causing its output to go low
2433 * for the configured period. The period depends on
2434 * the conversion period and the number of conversions
2437 * Set the trigger high before setting up the
2438 * monostable to stop it triggering. The trigger
2439 * source will be changed later.
2441 zgat = GAT_CONFIG(0, GAT_VCC);
2442 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2443 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2444 ((uint64_t) cmd->convert_arg
2445 * cmd->scan_end_arg),
2447 if (cmd->scan_begin_src == TRIG_TIMER) {
2449 * Monostable on CT0 will be triggered by
2450 * output of CT1 at configured scan frequency.
2452 * Set up CT1 but gate it off for now.
2454 zgat = GAT_CONFIG(1, GAT_GND);
2455 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2456 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2457 cmd->scan_begin_arg,
2465 if (cmd->start_src == TRIG_INT) {
2466 s->async->inttrig = pci230_ai_inttrig_start;
2469 pci230_ai_start(dev, s);
2475 static int pci230_ai_cancel(struct comedi_device *dev,
2476 struct comedi_subdevice *s)
2478 pci230_ai_stop(dev, s);
2482 /* Interrupt handler */
2483 static irqreturn_t pci230_interrupt(int irq, void *d)
2485 unsigned char status_int, valid_status_int;
2486 struct comedi_device *dev = (struct comedi_device *)d;
2487 struct pci230_private *devpriv = dev->private;
2488 struct comedi_subdevice *s;
2489 unsigned long irqflags;
2491 /* Read interrupt status/enable register. */
2492 status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2494 if (status_int == PCI230_INT_DISABLE)
2498 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2499 valid_status_int = devpriv->int_en & status_int;
2500 /* Disable triggered interrupts.
2501 * (Only those interrupts that need re-enabling, are, later in the
2503 devpriv->ier = devpriv->int_en & ~status_int;
2504 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2505 devpriv->intr_running = 1;
2506 devpriv->intr_cpuid = THISCPU;
2507 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2510 * Check the source of interrupt and handle it.
2511 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2512 * interrupts. However, at present (Comedi-0.7.60) does not allow
2513 * concurrent execution of commands, instructions or a mixture of the
2517 if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2518 s = dev->write_subdev;
2519 pci230_handle_ao_nofifo(dev, s);
2520 comedi_event(dev, s);
2523 if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2524 s = dev->write_subdev;
2525 pci230_handle_ao_fifo(dev, s);
2526 comedi_event(dev, s);
2529 if ((valid_status_int & PCI230_INT_ADC) != 0) {
2530 s = dev->read_subdev;
2531 pci230_handle_ai(dev, s);
2532 comedi_event(dev, s);
2535 /* Reenable interrupts. */
2536 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2537 if (devpriv->ier != devpriv->int_en) {
2538 devpriv->ier = devpriv->int_en;
2539 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2541 devpriv->intr_running = 0;
2542 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2547 /* Check if PCI device matches a specific board. */
2548 static bool pci230_match_pci_board(const struct pci230_board *board,
2549 struct pci_dev *pci_dev)
2551 /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */
2552 if (board->id != pci_dev->device)
2554 if (board->min_hwver == 0)
2556 /* Looking for a '+' model. First check length of registers. */
2557 if (pci_resource_len(pci_dev, 3) < 32)
2558 return false; /* Not a '+' model. */
2559 /* TODO: temporarily enable PCI device and read the hardware version
2560 * register. For now, assume it's okay. */
2564 /* Look for board matching PCI device. */
2565 static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev)
2569 for (i = 0; i < ARRAY_SIZE(pci230_boards); i++)
2570 if (pci230_match_pci_board(&pci230_boards[i], pci_dev))
2571 return &pci230_boards[i];
2575 /* Look for PCI device matching requested board name, bus and slot. */
2576 static struct pci_dev *pci230_find_pci_dev(struct comedi_device *dev,
2577 struct comedi_devconfig *it)
2579 const struct pci230_board *thisboard = comedi_board(dev);
2580 struct pci_dev *pci_dev = NULL;
2581 int bus = it->options[0];
2582 int slot = it->options[1];
2584 for_each_pci_dev(pci_dev) {
2585 /* Check vendor ID (same for all supported PCI boards). */
2586 if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
2588 /* If bus/slot specified, check them. */
2589 if ((bus || slot) &&
2590 (bus != pci_dev->bus->number ||
2591 slot != PCI_SLOT(pci_dev->devfn)))
2593 if (thisboard->id == PCI_DEVICE_ID_INVALID) {
2594 /* Wildcard board matches any supported PCI board. */
2595 const struct pci230_board *foundboard;
2597 foundboard = pci230_find_pci_board(pci_dev);
2598 if (foundboard == NULL)
2600 /* Replace wildcard board_ptr. */
2601 dev->board_ptr = foundboard;
2603 /* Need to match a specific board. */
2604 if (!pci230_match_pci_board(thisboard, pci_dev))
2609 dev_err(dev->class_dev,
2610 "No supported board found! (req. bus %d, slot %d)\n",
2615 static int pci230_alloc_private(struct comedi_device *dev)
2617 struct pci230_private *devpriv;
2619 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
2623 spin_lock_init(&devpriv->isr_spinlock);
2624 spin_lock_init(&devpriv->res_spinlock);
2625 spin_lock_init(&devpriv->ai_stop_spinlock);
2626 spin_lock_init(&devpriv->ao_stop_spinlock);
2630 /* Common part of attach and auto_attach. */
2631 static int pci230_attach_common(struct comedi_device *dev,
2632 struct pci_dev *pci_dev)
2634 const struct pci230_board *thisboard = comedi_board(dev);
2635 struct pci230_private *devpriv = dev->private;
2636 struct comedi_subdevice *s;
2637 unsigned long iobase1, iobase2;
2638 /* PCI230's I/O spaces 1 and 2 respectively. */
2641 comedi_set_hw_dev(dev, &pci_dev->dev);
2643 dev->board_name = thisboard->name;
2645 rc = comedi_pci_enable(dev);
2649 /* Read base addresses of the PCI230's two I/O regions from PCI
2650 * configuration register. */
2651 iobase1 = pci_resource_start(pci_dev, 2);
2652 iobase2 = pci_resource_start(pci_dev, 3);
2653 dev_dbg(dev->class_dev,
2654 "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
2655 dev->board_name, iobase1, iobase2);
2656 devpriv->iobase1 = iobase1;
2657 dev->iobase = iobase2;
2658 /* Read bits of DACCON register - only the output range. */
2659 devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
2660 /* Read hardware version register and set extended function register
2662 if (pci_resource_len(pci_dev, 3) >= 32) {
2663 unsigned short extfunc = 0;
2665 devpriv->hwver = inw(dev->iobase + PCI230P_HWVER);
2666 if (devpriv->hwver < thisboard->min_hwver) {
2667 dev_err(dev->class_dev,
2668 "%s - bad hardware version - got %u, need %u\n",
2669 dev->board_name, devpriv->hwver,
2670 thisboard->min_hwver);
2673 if (devpriv->hwver > 0) {
2674 if (!thisboard->have_dio) {
2675 /* No DIO ports. Route counters' external gates
2676 * to the EXTTRIG signal (PCI260+ pin 17).
2677 * (Otherwise, they would be routed to DIO
2678 * inputs PC0, PC1 and PC2 which don't exist
2680 extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
2682 if ((thisboard->ao_chans > 0)
2683 && (devpriv->hwver >= 2)) {
2684 /* Enable DAC FIFO functionality. */
2685 extfunc |= PCI230P2_EXTFUNC_DACFIFO;
2688 outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
2689 if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) {
2690 /* Temporarily enable DAC FIFO, reset it and disable
2691 * FIFO wraparound. */
2692 outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN
2693 | PCI230P2_DAC_FIFO_RESET,
2694 dev->iobase + PCI230_DACCON);
2695 /* Clear DAC FIFO channel enable register. */
2696 outw(0, dev->iobase + PCI230P2_DACEN);
2697 /* Disable DAC FIFO. */
2698 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
2701 /* Disable board's interrupts. */
2702 outb(0, devpriv->iobase1 + PCI230_INT_SCE);
2703 /* Set ADC to a reasonable state. */
2705 devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE
2706 | PCI230_ADC_IR_BIP;
2707 outw(1 << 0, dev->iobase + PCI230_ADCEN);
2708 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2709 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2710 dev->iobase + PCI230_ADCCON);
2711 /* Register the interrupt handler. */
2712 irq_hdl = request_irq(pci_dev->irq, pci230_interrupt,
2713 IRQF_SHARED, "amplc_pci230", dev);
2715 dev_warn(dev->class_dev,
2716 "unable to register irq %u, commands will not be available\n",
2719 dev->irq = pci_dev->irq;
2720 dev_dbg(dev->class_dev, "registered irq %u\n", pci_dev->irq);
2723 rc = comedi_alloc_subdevices(dev, 3);
2727 s = &dev->subdevices[0];
2728 /* analog input subdevice */
2729 s->type = COMEDI_SUBD_AI;
2730 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
2731 s->n_chan = thisboard->ai_chans;
2732 s->maxdata = (1 << thisboard->ai_bits) - 1;
2733 s->range_table = &pci230_ai_range;
2734 s->insn_read = &pci230_ai_rinsn;
2735 s->len_chanlist = 256; /* but there are restrictions. */
2736 /* Only register commands if the interrupt handler is installed. */
2738 dev->read_subdev = s;
2739 s->subdev_flags |= SDF_CMD_READ;
2740 s->do_cmd = &pci230_ai_cmd;
2741 s->do_cmdtest = &pci230_ai_cmdtest;
2742 s->cancel = pci230_ai_cancel;
2744 s = &dev->subdevices[1];
2745 /* analog output subdevice */
2746 if (thisboard->ao_chans > 0) {
2747 s->type = COMEDI_SUBD_AO;
2748 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
2749 s->n_chan = thisboard->ao_chans;
2750 s->maxdata = (1 << thisboard->ao_bits) - 1;
2751 s->range_table = &pci230_ao_range;
2752 s->insn_write = &pci230_ao_winsn;
2753 s->insn_read = &pci230_ao_rinsn;
2754 s->len_chanlist = thisboard->ao_chans;
2755 /* Only register commands if the interrupt handler is
2758 dev->write_subdev = s;
2759 s->subdev_flags |= SDF_CMD_WRITE;
2760 s->do_cmd = &pci230_ao_cmd;
2761 s->do_cmdtest = &pci230_ao_cmdtest;
2762 s->cancel = pci230_ao_cancel;
2765 s->type = COMEDI_SUBD_UNUSED;
2767 s = &dev->subdevices[2];
2768 /* digital i/o subdevice */
2769 if (thisboard->have_dio) {
2770 rc = subdev_8255_init(dev, s, NULL,
2771 (devpriv->iobase1 + PCI230_PPI_X_BASE));
2775 s->type = COMEDI_SUBD_UNUSED;
2777 dev_info(dev->class_dev, "attached\n");
2781 static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2783 const struct pci230_board *thisboard = comedi_board(dev);
2784 struct pci_dev *pci_dev;
2787 dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n",
2788 thisboard->name, it->options[0], it->options[1]);
2790 rc = pci230_alloc_private(dev);
2794 pci_dev = pci230_find_pci_dev(dev, it);
2797 return pci230_attach_common(dev, pci_dev);
2800 static int pci230_auto_attach(struct comedi_device *dev,
2801 unsigned long context_unused)
2803 struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
2806 dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
2809 rc = pci230_alloc_private(dev);
2813 dev->board_ptr = pci230_find_pci_board(pci_dev);
2814 if (dev->board_ptr == NULL) {
2815 dev_err(dev->class_dev,
2816 "amplc_pci230: BUG! cannot determine board type!\n");
2820 * Need to 'get' the PCI device to match the 'put' in pci230_detach().
2821 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
2822 * support for manual attachment of PCI devices via pci230_attach()
2825 pci_dev_get(pci_dev);
2826 return pci230_attach_common(dev, pci_dev);
2829 static void pci230_detach(struct comedi_device *dev)
2831 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2834 free_irq(dev->irq, dev);
2835 comedi_pci_disable(dev);
2837 pci_dev_put(pcidev);
2840 static struct comedi_driver amplc_pci230_driver = {
2841 .driver_name = "amplc_pci230",
2842 .module = THIS_MODULE,
2843 .attach = pci230_attach,
2844 .auto_attach = pci230_auto_attach,
2845 .detach = pci230_detach,
2846 .board_name = &pci230_boards[0].name,
2847 .offset = sizeof(pci230_boards[0]),
2848 .num_names = ARRAY_SIZE(pci230_boards),
2851 static int amplc_pci230_pci_probe(struct pci_dev *dev,
2852 const struct pci_device_id *id)
2854 return comedi_pci_auto_config(dev, &lc_pci230_driver,
2858 static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = {
2859 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
2860 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
2863 MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table);
2865 static struct pci_driver amplc_pci230_pci_driver = {
2866 .name = "amplc_pci230",
2867 .id_table = amplc_pci230_pci_table,
2868 .probe = amplc_pci230_pci_probe,
2869 .remove = comedi_pci_auto_unconfig,
2871 module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
2873 MODULE_AUTHOR("Comedi http://www.comedi.org");
2874 MODULE_DESCRIPTION("Comedi low-level driver");
2875 MODULE_LICENSE("GPL");