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/pci.h>
188 #include <linux/delay.h>
189 #include <linux/interrupt.h>
191 #include "../comedidev.h"
193 #include "comedi_fc.h"
197 /* PCI230 PCI configuration register information */
198 #define PCI_DEVICE_ID_PCI230 0x0000
199 #define PCI_DEVICE_ID_PCI260 0x0006
200 #define PCI_DEVICE_ID_INVALID 0xffff
202 #define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */
203 #define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */
205 /* PCI230 i/o space 1 registers. */
206 #define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */
207 #define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */
208 #define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */
209 #define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */
210 #define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */
211 #define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */
212 #define PCI230_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
213 #define PCI230_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
214 #define PCI230_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
215 #define PCI230_Z2_CTC 0x17 /* 82C54 counter/timer control word */
216 #define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */
217 #define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */
218 #define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */
219 #define PCI230_INT_STAT 0x1E /* Interrupt status (r) */
221 /* PCI230 i/o space 2 registers. */
222 #define PCI230_DACCON 0x00 /* DAC control */
223 #define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */
224 #define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */
225 #define PCI230_ADCDATA 0x08 /* ADC data (r) */
226 #define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */
227 #define PCI230_ADCCON 0x0A /* ADC control */
228 #define PCI230_ADCEN 0x0C /* ADC channel enable bits */
229 #define PCI230_ADCG 0x0E /* ADC gain control bits */
230 /* PCI230+ i/o space 2 additional registers. */
231 #define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */
232 #define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */
233 #define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */
234 #define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */
235 #define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */
236 #define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */
237 #define PCI230P_EXTFUNC 0x1C /* Extended functions */
238 #define PCI230P_HWVER 0x1E /* Hardware version (r) */
239 /* PCI230+ hardware version 2 onwards. */
240 #define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */
241 #define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */
242 #define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */
244 /* Convertor related constants. */
245 #define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs */
246 /* (DAC itself is 1µs nominally). */
247 #define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs */
248 /* (ADC itself is 1.6µs nominally but we poll
250 #define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS */
251 /* - 10µs for se, 20µs de. */
253 /* DACCON read-write values. */
254 #define PCI230_DAC_OR_UNI (0<<0) /* Output range unipolar */
255 #define PCI230_DAC_OR_BIP (1<<0) /* Output range bipolar */
256 #define PCI230_DAC_OR_MASK (1<<0)
257 /* The following applies only if DAC FIFO support is enabled in the EXTFUNC
258 * register (and only for PCI230+ hardware version 2 onwards). */
259 #define PCI230P2_DAC_FIFO_EN (1<<8) /* FIFO enable */
260 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
261 * hardware version 2 onwards). */
262 #define PCI230P2_DAC_TRIG_NONE (0<<2) /* No trigger */
263 #define PCI230P2_DAC_TRIG_SW (1<<2) /* Software trigger trigger */
264 #define PCI230P2_DAC_TRIG_EXTP (2<<2) /* EXTTRIG +ve edge trigger */
265 #define PCI230P2_DAC_TRIG_EXTN (3<<2) /* EXTTRIG -ve edge trigger */
266 #define PCI230P2_DAC_TRIG_Z2CT0 (4<<2) /* CT0-OUT +ve edge trigger */
267 #define PCI230P2_DAC_TRIG_Z2CT1 (5<<2) /* CT1-OUT +ve edge trigger */
268 #define PCI230P2_DAC_TRIG_Z2CT2 (6<<2) /* CT2-OUT +ve edge trigger */
269 #define PCI230P2_DAC_TRIG_MASK (7<<2)
270 #define PCI230P2_DAC_FIFO_WRAP (1<<7) /* FIFO wraparound mode */
271 #define PCI230P2_DAC_INT_FIFO_EMPTY (0<<9) /* FIFO interrupt empty */
272 #define PCI230P2_DAC_INT_FIFO_NEMPTY (1<<9)
273 #define PCI230P2_DAC_INT_FIFO_NHALF (2<<9) /* FIFO intr not half full */
274 #define PCI230P2_DAC_INT_FIFO_HALF (3<<9)
275 #define PCI230P2_DAC_INT_FIFO_NFULL (4<<9) /* FIFO interrupt not full */
276 #define PCI230P2_DAC_INT_FIFO_FULL (5<<9)
277 #define PCI230P2_DAC_INT_FIFO_MASK (7<<9)
279 /* DACCON read-only values. */
280 #define PCI230_DAC_BUSY (1<<1) /* DAC busy. */
281 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
282 * 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 */
288 /* DACCON write-only, transient values. */
289 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
290 * hardware version 2 onwards). */
291 #define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1<<5) /* Clear underrun */
292 #define PCI230P2_DAC_FIFO_RESET (1<<12) /* FIFO reset */
294 /* PCI230+ hardware version 2 DAC FIFO levels. */
295 #define PCI230P2_DAC_FIFOLEVEL_HALF 512
296 #define PCI230P2_DAC_FIFOLEVEL_FULL 1024
297 /* Free space in DAC FIFO. */
298 #define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL
299 #define PCI230P2_DAC_FIFOROOM_ONETOHALF \
300 (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
301 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1
302 #define PCI230P2_DAC_FIFOROOM_FULL 0
304 /* ADCCON read/write values. */
305 #define PCI230_ADC_TRIG_NONE (0<<0) /* No trigger */
306 #define PCI230_ADC_TRIG_SW (1<<0) /* Software trigger trigger */
307 #define PCI230_ADC_TRIG_EXTP (2<<0) /* EXTTRIG +ve edge trigger */
308 #define PCI230_ADC_TRIG_EXTN (3<<0) /* EXTTRIG -ve edge trigger */
309 #define PCI230_ADC_TRIG_Z2CT0 (4<<0) /* CT0-OUT +ve edge trigger */
310 #define PCI230_ADC_TRIG_Z2CT1 (5<<0) /* CT1-OUT +ve edge trigger */
311 #define PCI230_ADC_TRIG_Z2CT2 (6<<0) /* CT2-OUT +ve edge trigger */
312 #define PCI230_ADC_TRIG_MASK (7<<0)
313 #define PCI230_ADC_IR_UNI (0<<3) /* Input range unipolar */
314 #define PCI230_ADC_IR_BIP (1<<3) /* Input range bipolar */
315 #define PCI230_ADC_IR_MASK (1<<3)
316 #define PCI230_ADC_IM_SE (0<<4) /* Input mode single ended */
317 #define PCI230_ADC_IM_DIF (1<<4) /* Input mode differential */
318 #define PCI230_ADC_IM_MASK (1<<4)
319 #define PCI230_ADC_FIFO_EN (1<<8) /* FIFO enable */
320 #define PCI230_ADC_INT_FIFO_EMPTY (0<<9)
321 #define PCI230_ADC_INT_FIFO_NEMPTY (1<<9) /* FIFO interrupt not empty */
322 #define PCI230_ADC_INT_FIFO_NHALF (2<<9)
323 #define PCI230_ADC_INT_FIFO_HALF (3<<9) /* FIFO interrupt half full */
324 #define PCI230_ADC_INT_FIFO_NFULL (4<<9)
325 #define PCI230_ADC_INT_FIFO_FULL (5<<9) /* FIFO interrupt full */
326 #define PCI230P_ADC_INT_FIFO_THRESH (7<<9) /* FIFO interrupt threshold */
327 #define PCI230_ADC_INT_FIFO_MASK (7<<9)
329 /* ADCCON write-only, transient values. */
330 #define PCI230_ADC_FIFO_RESET (1<<12) /* FIFO reset */
331 #define PCI230_ADC_GLOB_RESET (1<<13) /* Global reset */
333 /* ADCCON read-only values. */
334 #define PCI230_ADC_BUSY (1<<15) /* ADC busy */
335 #define PCI230_ADC_FIFO_EMPTY (1<<12) /* FIFO empty */
336 #define PCI230_ADC_FIFO_FULL (1<<13) /* FIFO full */
337 #define PCI230_ADC_FIFO_HALF (1<<14) /* FIFO half full */
338 #define PCI230_ADC_FIFO_FULL_LATCHED (1<<5) /* Indicates overrun occurred */
340 /* PCI230 ADC FIFO levels. */
341 #define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */
342 #define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */
344 /* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
345 * mode. Can be anything. */
346 #define PCI230_ADC_CONV 0xffff
348 /* PCI230+ EXTFUNC values. */
349 #define PCI230P_EXTFUNC_GAT_EXTTRIG (1<<0)
350 /* Route EXTTRIG pin to external gate inputs. */
351 /* PCI230+ hardware version 2 values. */
352 #define PCI230P2_EXTFUNC_DACFIFO (1<<1)
353 /* Allow DAC FIFO to be enabled. */
356 * Counter/timer clock input configuration sources.
358 #define CLK_CLK 0 /* reserved (channel-specific clock) */
359 #define CLK_10MHZ 1 /* internal 10 MHz clock */
360 #define CLK_1MHZ 2 /* internal 1 MHz clock */
361 #define CLK_100KHZ 3 /* internal 100 kHz clock */
362 #define CLK_10KHZ 4 /* internal 10 kHz clock */
363 #define CLK_1KHZ 5 /* internal 1 kHz clock */
364 #define CLK_OUTNM1 6 /* output of channel-1 modulo total */
365 #define CLK_EXT 7 /* external clock */
366 /* Macro to construct clock input configuration register value. */
367 #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
368 /* Timebases in ns. */
369 #define TIMEBASE_10MHZ 100
370 #define TIMEBASE_1MHZ 1000
371 #define TIMEBASE_100KHZ 10000
372 #define TIMEBASE_10KHZ 100000
373 #define TIMEBASE_1KHZ 1000000
376 * Counter/timer gate input configuration sources.
378 #define GAT_VCC 0 /* VCC (i.e. enabled) */
379 #define GAT_GND 1 /* GND (i.e. disabled) */
380 #define GAT_EXT 2 /* external gate input (PPCn on PCI230) */
381 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
382 /* Macro to construct gate input configuration register value. */
383 #define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
386 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
388 * Channel's Channel's
389 * clock input gate input
390 * Channel CLK_OUTNM1 GAT_NOUTNM2
391 * ------- ---------- -----------
392 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
393 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
394 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
397 /* Interrupt enables/status register values. */
398 #define PCI230_INT_DISABLE 0
399 #define PCI230_INT_PPI_C0 (1<<0)
400 #define PCI230_INT_PPI_C3 (1<<1)
401 #define PCI230_INT_ADC (1<<2)
402 #define PCI230_INT_ZCLK_CT1 (1<<5)
403 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
404 #define PCI230P2_INT_DAC (1<<4)
406 #define PCI230_TEST_BIT(val, n) ((val>>n)&1)
407 /* Assumes bits numbered with zero offset, ie. 0-15 */
409 /* (Potentially) shared resources and their owners */
411 RES_Z2CT0, /* Z2-CT0 */
412 RES_Z2CT1, /* Z2-CT1 */
413 RES_Z2CT2, /* Z2-CT2 */
414 NUM_RESOURCES /* Number of (potentially) shared resources. */
418 OWNER_NONE, /* Not owned */
419 OWNER_AICMD, /* Owned by AI command */
420 OWNER_AOCMD /* Owned by AO command */
427 /* Combine old and new bits. */
428 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
430 /* Current CPU. XXX should this be hard_smp_processor_id()? */
431 #define THISCPU smp_processor_id()
433 /* State flags for atomic bit operations */
434 #define AI_CMD_STARTED 0
435 #define AO_CMD_STARTED 1
438 * Board descriptions for the two boards supported.
441 struct pci230_board {
449 unsigned int min_hwver; /* Minimum hardware version supported. */
451 static const struct pci230_board pci230_boards[] = {
454 .id = PCI_DEVICE_ID_PCI230,
464 .id = PCI_DEVICE_ID_PCI260,
474 .id = PCI_DEVICE_ID_PCI230,
483 .id = PCI_DEVICE_ID_PCI260,
491 .name = "amplc_pci230", /* Wildcard matches any above */
492 .id = PCI_DEVICE_ID_INVALID,
496 /* this structure is for data unique to this hardware driver. If
497 several hardware drivers keep similar information in this structure,
498 feel free to suggest moving the variable to the struct comedi_device struct. */
499 struct pci230_private {
500 spinlock_t isr_spinlock; /* Interrupt spin lock */
501 spinlock_t res_spinlock; /* Shared resources spin lock */
502 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
503 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
504 unsigned long state; /* State flags */
505 unsigned long iobase1; /* PCI230's I/O space 1 */
506 unsigned int ao_readback[2]; /* Used for AO readback */
507 unsigned int ai_scan_count; /* Number of analogue input scans
509 unsigned int ai_scan_pos; /* Current position within analogue
511 unsigned int ao_scan_count; /* Number of analogue output scans
513 int intr_cpuid; /* ID of CPU running interrupt routine. */
514 unsigned short hwver; /* Hardware version (for '+' models). */
515 unsigned short adccon; /* ADCCON register value. */
516 unsigned short daccon; /* DACCON register value. */
517 unsigned short adcfifothresh; /* ADC FIFO programmable interrupt
518 * level threshold (PCI230+/260+). */
519 unsigned short adcg; /* ADCG register value. */
520 unsigned char int_en; /* Interrupt enables bits. */
521 unsigned char ai_continuous; /* Flag set when cmd->stop_src ==
522 * TRIG_NONE - user chooses to stop
523 * continuous conversion by
525 unsigned char ao_continuous; /* Flag set when cmd->stop_src ==
526 * TRIG_NONE - user chooses to stop
527 * continuous conversion by
529 unsigned char ai_bipolar; /* Set if bipolar input range so we
530 * know to mangle it. */
531 unsigned char ao_bipolar; /* Set if bipolar output range so we
532 * know to mangle it. */
533 unsigned char ier; /* Copy of interrupt enables/status register. */
534 unsigned char intr_running; /* Flag set in interrupt routine. */
535 unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */
538 /* PCI230 clock source periods in ns */
539 static const unsigned int pci230_timebase[8] = {
540 [CLK_10MHZ] = TIMEBASE_10MHZ,
541 [CLK_1MHZ] = TIMEBASE_1MHZ,
542 [CLK_100KHZ] = TIMEBASE_100KHZ,
543 [CLK_10KHZ] = TIMEBASE_10KHZ,
544 [CLK_1KHZ] = TIMEBASE_1KHZ,
547 /* PCI230 analogue input range table */
548 static const struct comedi_lrange pci230_ai_range = { 7, {
559 /* PCI230 analogue gain bits for each input range. */
560 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
562 /* PCI230 adccon bipolar flag for each analogue input range. */
563 static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
565 /* PCI230 analogue output range table */
566 static const struct comedi_lrange pci230_ao_range = { 2, {
572 /* PCI230 daccon bipolar flag for each analogue output range. */
573 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
575 static short pci230_ai_read(struct comedi_device *dev)
577 const struct pci230_board *thisboard = comedi_board(dev);
578 struct pci230_private *devpriv = dev->private;
582 data = (short)inw(dev->iobase + PCI230_ADCDATA);
583 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
584 * four bits reserved for expansion). */
585 /* PCI230+ is 16 bit AI. */
586 data = data >> (16 - thisboard->ai_bits);
588 /* If a bipolar range was specified, mangle it (twos
589 * complement->straight binary). */
590 if (devpriv->ai_bipolar)
591 data ^= 1 << (thisboard->ai_bits - 1);
596 static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
599 const struct pci230_board *thisboard = comedi_board(dev);
600 struct pci230_private *devpriv = dev->private;
602 /* If a bipolar range was specified, mangle it (straight binary->twos
604 if (devpriv->ao_bipolar)
605 datum ^= 1 << (thisboard->ao_bits - 1);
607 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
608 * four bits reserved for expansion). */
609 /* PCI230+ is also 12 bit AO. */
610 datum <<= (16 - thisboard->ao_bits);
611 return (unsigned short)datum;
614 static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
615 short datum, unsigned int chan)
617 struct pci230_private *devpriv = dev->private;
619 /* Store unmangled datum to be read back later. */
620 devpriv->ao_readback[chan] = datum;
622 /* Write mangled datum to appropriate DACOUT register. */
623 outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
629 static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
632 struct pci230_private *devpriv = dev->private;
634 /* Store unmangled datum to be read back later. */
635 devpriv->ao_readback[chan] = datum;
637 /* Write mangled datum to appropriate DACDATA register. */
638 outw(pci230_ao_mangle_datum(dev, datum),
639 dev->iobase + PCI230P2_DACDATA);
642 static int get_resources(struct comedi_device *dev, unsigned int res_mask,
645 struct pci230_private *devpriv = dev->private;
649 unsigned int claimed;
650 unsigned long irqflags;
654 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
655 for (b = 1, i = 0; (i < NUM_RESOURCES)
656 && (res_mask != 0); b <<= 1, i++) {
657 if ((res_mask & b) != 0) {
659 if (devpriv->res_owner[i] == OWNER_NONE) {
660 devpriv->res_owner[i] = owner;
662 } else if (devpriv->res_owner[i] != owner) {
663 for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
664 if ((claimed & b) != 0) {
665 devpriv->res_owner[i]
675 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
679 static inline int get_one_resource(struct comedi_device *dev,
680 unsigned int resource, unsigned char owner)
682 return get_resources(dev, (1U << resource), owner);
685 static void put_resources(struct comedi_device *dev, unsigned int res_mask,
688 struct pci230_private *devpriv = dev->private;
691 unsigned long irqflags;
693 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
694 for (b = 1, i = 0; (i < NUM_RESOURCES)
695 && (res_mask != 0); b <<= 1, i++) {
696 if ((res_mask & b) != 0) {
698 if (devpriv->res_owner[i] == owner)
699 devpriv->res_owner[i] = OWNER_NONE;
703 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
706 static inline void put_one_resource(struct comedi_device *dev,
707 unsigned int resource, unsigned char owner)
709 put_resources(dev, (1U << resource), owner);
712 static inline void put_all_resources(struct comedi_device *dev,
715 put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
718 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
719 unsigned int round_mode)
725 rem = do_div(div, timebase);
726 round_mode &= TRIG_ROUND_MASK;
727 switch (round_mode) {
729 case TRIG_ROUND_NEAREST:
730 div += (rem + (timebase / 2)) / timebase;
732 case TRIG_ROUND_DOWN:
735 div += (rem + timebase - 1) / timebase;
738 return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
741 /* Given desired period in ns, returns the required internal clock source
742 * and gets the initial count. */
743 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
744 unsigned int round_mode)
746 unsigned int clk_src, cnt;
748 for (clk_src = CLK_10MHZ;; clk_src++) {
749 cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
750 if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
758 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
761 unsigned int clk_src;
763 clk_src = pci230_choose_clk_count(*ns, &count, round);
764 *ns = count * pci230_timebase[clk_src];
768 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
769 unsigned int mode, uint64_t ns,
772 struct pci230_private *devpriv = dev->private;
773 unsigned int clk_src;
777 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
778 /* Determine clock source and count. */
779 clk_src = pci230_choose_clk_count(ns, &count, round);
780 /* Program clock source. */
781 outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
782 /* Set initial count. */
786 i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
789 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
791 struct pci230_private *devpriv = dev->private;
793 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
795 /* Counter ct, 8254 mode 1, initial count not written. */
799 * COMEDI_SUBD_AI instruction;
801 static int pci230_ai_rinsn(struct comedi_device *dev,
802 struct comedi_subdevice *s, struct comedi_insn *insn,
805 struct pci230_private *devpriv = dev->private;
807 unsigned int chan, range, aref;
808 unsigned int gainshift;
810 unsigned short adccon, adcen;
812 /* Unpack channel and range. */
813 chan = CR_CHAN(insn->chanspec);
814 range = CR_RANGE(insn->chanspec);
815 aref = CR_AREF(insn->chanspec);
816 if (aref == AREF_DIFF) {
818 if (chan >= s->n_chan / 2) {
819 DPRINTK("comedi%d: amplc_pci230: ai_rinsn: "
820 "differential channel number out of range "
821 "0 to %u\n", dev->minor, (s->n_chan / 2) - 1);
826 /* Use Z2-CT2 as a conversion trigger instead of the built-in
827 * software trigger, as otherwise triggering of differential channels
828 * doesn't work properly for some versions of PCI230/260. Also set
829 * FIFO mode because the ADC busy bit only works for software triggers.
831 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
832 /* Set Z2-CT2 output low to avoid any false triggers. */
833 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
834 devpriv->ai_bipolar = pci230_ai_bipolar[range];
835 if (aref == AREF_DIFF) {
837 gainshift = chan * 2;
838 if (devpriv->hwver == 0) {
839 /* Original PCI230/260 expects both inputs of the
840 * differential channel to be enabled. */
841 adcen = 3 << gainshift;
843 /* PCI230+/260+ expects only one input of the
844 * differential channel to be enabled. */
845 adcen = 1 << gainshift;
847 adccon |= PCI230_ADC_IM_DIF;
851 gainshift = chan & ~1;
852 adccon |= PCI230_ADC_IM_SE;
854 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
855 | (pci230_ai_gain[range] << gainshift);
856 if (devpriv->ai_bipolar)
857 adccon |= PCI230_ADC_IR_BIP;
859 adccon |= PCI230_ADC_IR_UNI;
862 /* Enable only this channel in the scan list - otherwise by default
863 * we'll get one sample from each channel. */
864 outw(adcen, dev->iobase + PCI230_ADCEN);
866 /* Set gain for channel. */
867 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
869 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
870 devpriv->adccon = adccon;
871 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
873 /* Convert n samples */
874 for (n = 0; n < insn->n; n++) {
875 /* Trigger conversion by toggling Z2-CT2 output (finish with
877 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
879 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
883 /* wait for conversion to end */
884 for (i = 0; i < TIMEOUT; i++) {
885 status = inw(dev->iobase + PCI230_ADCCON);
886 if (!(status & PCI230_ADC_FIFO_EMPTY))
891 dev_err(dev->class_dev, "timeout\n");
896 data[n] = pci230_ai_read(dev);
899 /* return the number of samples read/written */
904 * COMEDI_SUBD_AO instructions;
906 static int pci230_ao_winsn(struct comedi_device *dev,
907 struct comedi_subdevice *s, struct comedi_insn *insn,
910 struct pci230_private *devpriv = dev->private;
914 /* Unpack channel and range. */
915 chan = CR_CHAN(insn->chanspec);
916 range = CR_RANGE(insn->chanspec);
918 /* Set range - see analogue output range table; 0 => unipolar 10V,
919 * 1 => bipolar +/-10V range scale */
920 devpriv->ao_bipolar = pci230_ao_bipolar[range];
921 outw(range, dev->iobase + PCI230_DACCON);
923 /* Writing a list of values to an AO channel is probably not
924 * very useful, but that's how the interface is defined. */
925 for (i = 0; i < insn->n; i++) {
926 /* Write value to DAC and store it. */
927 pci230_ao_write_nofifo(dev, data[i], chan);
930 /* return the number of samples read/written */
934 /* AO subdevices should have a read insn as well as a write insn.
935 * Usually this means copying a value stored in devpriv. */
936 static int pci230_ao_rinsn(struct comedi_device *dev,
937 struct comedi_subdevice *s, struct comedi_insn *insn,
940 struct pci230_private *devpriv = dev->private;
942 int chan = CR_CHAN(insn->chanspec);
944 for (i = 0; i < insn->n; i++)
945 data[i] = devpriv->ao_readback[chan];
950 static int pci230_ao_cmdtest(struct comedi_device *dev,
951 struct comedi_subdevice *s, struct comedi_cmd *cmd)
953 const struct pci230_board *thisboard = comedi_board(dev);
954 struct pci230_private *devpriv = dev->private;
958 /* Step 1 : check if triggers are trivially valid */
960 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
962 tmp = TRIG_TIMER | TRIG_INT;
963 if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
965 * For PCI230+ hardware version 2 onwards, allow external
966 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
968 * FIXME: The permitted scan_begin_src values shouldn't depend
969 * on devpriv->hwver (the detected card's actual hardware
970 * version). They should only depend on thisboard->min_hwver
971 * (the static capabilities of the configured card). To fix
972 * it, a new card model, e.g. "pci230+2" would have to be
973 * defined with min_hwver set to 2. It doesn't seem worth it
974 * for this alone. At the moment, please consider
975 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
980 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
982 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
983 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
984 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
989 /* Step 2a : make sure trigger sources are unique */
991 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
992 err |= cfc_check_trigger_is_unique(cmd->stop_src);
994 /* Step 2b : and mutually compatible */
999 /* Step 3: check if arguments are trivially valid */
1001 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1003 #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */
1004 #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */
1005 /*- Comedi limit due to unsigned int cmd. Driver limit
1006 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1007 * clock) = 65.536s */
1009 switch (cmd->scan_begin_src) {
1011 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1013 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
1017 /* External trigger - for PCI230+ hardware version 2 onwards. */
1018 /* Trigger number must be 0. */
1019 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1020 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1024 /* The only flags allowed are CR_EDGE and CR_INVERT. The
1025 * CR_EDGE flag is ignored. */
1026 if ((cmd->scan_begin_arg
1027 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1028 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1030 ~(CR_EDGE | CR_INVERT));
1035 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1039 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1041 if (cmd->stop_src == TRIG_NONE)
1042 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1047 /* Step 4: fix up any arguments.
1048 * "argument conflict" returned by comedilib to user mode process
1051 if (cmd->scan_begin_src == TRIG_TIMER) {
1052 tmp = cmd->scan_begin_arg;
1053 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1054 cmd->flags & TRIG_ROUND_MASK);
1055 if (tmp != cmd->scan_begin_arg)
1062 /* Step 5: check channel list if it exists. */
1064 if (cmd->chanlist && cmd->chanlist_len > 0) {
1067 range_err = (1 << 1)
1069 unsigned int errors;
1071 unsigned int chan, prev_chan;
1072 unsigned int range, first_range;
1074 prev_chan = CR_CHAN(cmd->chanlist[0]);
1075 first_range = CR_RANGE(cmd->chanlist[0]);
1077 for (n = 1; n < cmd->chanlist_len; n++) {
1078 chan = CR_CHAN(cmd->chanlist[n]);
1079 range = CR_RANGE(cmd->chanlist[n]);
1080 /* Channel numbers must strictly increase. */
1081 if (chan < prev_chan)
1084 /* Ranges must be the same. */
1085 if (range != first_range)
1086 errors |= range_err;
1092 if ((errors & seq_err) != 0) {
1093 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1094 "channel numbers must increase\n",
1097 if ((errors & range_err) != 0) {
1098 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1099 "channels must have the same range\n",
1111 static void pci230_ao_stop(struct comedi_device *dev,
1112 struct comedi_subdevice *s)
1114 struct pci230_private *devpriv = dev->private;
1115 unsigned long irqflags;
1116 unsigned char intsrc;
1118 struct comedi_cmd *cmd;
1120 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1121 started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
1122 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1125 cmd = &s->async->cmd;
1126 if (cmd->scan_begin_src == TRIG_TIMER) {
1127 /* Stop scan rate generator. */
1128 pci230_cancel_ct(dev, 1);
1130 /* Determine interrupt source. */
1131 if (devpriv->hwver < 2) {
1132 /* Not using DAC FIFO. Using CT1 interrupt. */
1133 intsrc = PCI230_INT_ZCLK_CT1;
1135 /* Using DAC FIFO interrupt. */
1136 intsrc = PCI230P2_INT_DAC;
1138 /* Disable interrupt and wait for interrupt routine to finish running
1139 * unless we are called from the interrupt routine. */
1140 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1141 devpriv->int_en &= ~intsrc;
1142 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
1143 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1144 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1146 if (devpriv->ier != devpriv->int_en) {
1147 devpriv->ier = devpriv->int_en;
1148 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1150 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1151 if (devpriv->hwver >= 2) {
1152 /* Using DAC FIFO. Reset FIFO, clear underrun error,
1154 devpriv->daccon &= PCI230_DAC_OR_MASK;
1155 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
1156 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
1157 dev->iobase + PCI230_DACCON);
1159 /* Release resources. */
1160 put_all_resources(dev, OWNER_AOCMD);
1163 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
1164 struct comedi_subdevice *s)
1166 struct pci230_private *devpriv = dev->private;
1169 struct comedi_async *async = s->async;
1170 struct comedi_cmd *cmd = &async->cmd;
1172 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
1174 for (i = 0; i < cmd->chanlist_len; i++) {
1175 /* Read sample from Comedi's circular buffer. */
1176 ret = comedi_buf_get(s->async, &data);
1178 s->async->events |= COMEDI_CB_OVERFLOW;
1179 pci230_ao_stop(dev, s);
1180 comedi_error(dev, "AO buffer underrun");
1183 /* Write value to DAC. */
1184 pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
1186 async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
1187 if (!devpriv->ao_continuous) {
1188 devpriv->ao_scan_count--;
1189 if (devpriv->ao_scan_count == 0) {
1190 /* End of acquisition. */
1191 async->events |= COMEDI_CB_EOA;
1192 pci230_ao_stop(dev, s);
1197 /* Loads DAC FIFO (if using it) from buffer. */
1198 /* Returns 0 if AO finished due to completion or error, 1 if still going. */
1199 static int pci230_handle_ao_fifo(struct comedi_device *dev,
1200 struct comedi_subdevice *s)
1202 struct pci230_private *devpriv = dev->private;
1203 struct comedi_async *async = s->async;
1204 struct comedi_cmd *cmd = &async->cmd;
1205 unsigned int num_scans;
1207 unsigned short dacstat;
1209 unsigned int bytes_per_scan;
1210 unsigned int events = 0;
1213 /* Get DAC FIFO status. */
1214 dacstat = inw(dev->iobase + PCI230_DACCON);
1215 /* Determine number of scans available in buffer. */
1216 bytes_per_scan = cmd->chanlist_len * sizeof(short);
1217 num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
1218 if (!devpriv->ao_continuous) {
1219 /* Fixed number of scans. */
1220 if (num_scans > devpriv->ao_scan_count)
1221 num_scans = devpriv->ao_scan_count;
1222 if (devpriv->ao_scan_count == 0) {
1223 /* End of acquisition. */
1224 events |= COMEDI_CB_EOA;
1228 /* Check for FIFO underrun. */
1229 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
1230 comedi_error(dev, "AO FIFO underrun");
1231 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1233 /* Check for buffer underrun if FIFO less than half full
1234 * (otherwise there will be loads of "DAC FIFO not half full"
1236 if ((num_scans == 0)
1237 && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
1238 comedi_error(dev, "AO buffer underrun");
1239 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1243 /* Determine how much room is in the FIFO (in samples). */
1244 if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
1245 room = PCI230P2_DAC_FIFOROOM_FULL;
1246 else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
1247 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
1248 else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
1249 room = PCI230P2_DAC_FIFOROOM_EMPTY;
1251 room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
1252 /* Convert room to number of scans that can be added. */
1253 room /= cmd->chanlist_len;
1254 /* Determine number of scans to process. */
1255 if (num_scans > room)
1257 /* Process scans. */
1258 for (n = 0; n < num_scans; n++) {
1259 for (i = 0; i < cmd->chanlist_len; i++) {
1262 comedi_buf_get(async, &datum);
1263 pci230_ao_write_fifo(dev, datum,
1264 CR_CHAN(cmd->chanlist[i]));
1267 events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
1268 if (!devpriv->ao_continuous) {
1269 devpriv->ao_scan_count -= num_scans;
1270 if (devpriv->ao_scan_count == 0) {
1271 /* All data for the command has been written
1272 * to FIFO. Set FIFO interrupt trigger level
1274 devpriv->daccon = (devpriv->daccon
1276 ~PCI230P2_DAC_INT_FIFO_MASK)
1277 | PCI230P2_DAC_INT_FIFO_EMPTY;
1278 outw(devpriv->daccon,
1279 dev->iobase + PCI230_DACCON);
1282 /* Check if FIFO underrun occurred while writing to FIFO. */
1283 dacstat = inw(dev->iobase + PCI230_DACCON);
1284 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
1285 comedi_error(dev, "AO FIFO underrun");
1286 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1289 if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
1291 /* Stopping AO due to completion or error. */
1292 pci230_ao_stop(dev, s);
1297 async->events |= events;
1301 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1302 struct comedi_subdevice *s,
1303 unsigned int trig_num)
1305 struct pci230_private *devpriv = dev->private;
1306 unsigned long irqflags;
1311 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1312 if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
1314 if (devpriv->hwver < 2) {
1315 /* Not using DAC FIFO. */
1316 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1318 pci230_handle_ao_nofifo(dev, s);
1319 comedi_event(dev, s);
1321 /* Using DAC FIFO. */
1322 /* Read DACSWTRIG register to trigger conversion. */
1323 inw(dev->iobase + PCI230P2_DACSWTRIG);
1324 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1327 /* Delay. Should driver be responsible for this? */
1328 /* XXX TODO: See if DAC busy bit can be used. */
1331 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1337 static void pci230_ao_start(struct comedi_device *dev,
1338 struct comedi_subdevice *s)
1340 struct pci230_private *devpriv = dev->private;
1341 struct comedi_async *async = s->async;
1342 struct comedi_cmd *cmd = &async->cmd;
1343 unsigned long irqflags;
1345 set_bit(AO_CMD_STARTED, &devpriv->state);
1346 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1347 /* An empty acquisition! */
1348 async->events |= COMEDI_CB_EOA;
1349 pci230_ao_stop(dev, s);
1350 comedi_event(dev, s);
1352 if (devpriv->hwver >= 2) {
1353 /* Using DAC FIFO. */
1354 unsigned short scantrig;
1357 /* Preload FIFO data. */
1358 run = pci230_handle_ao_fifo(dev, s);
1359 comedi_event(dev, s);
1364 /* Set scan trigger source. */
1365 switch (cmd->scan_begin_src) {
1367 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1370 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1371 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1373 scantrig = PCI230P2_DAC_TRIG_EXTP;
1376 scantrig = PCI230P2_DAC_TRIG_EXTN;
1380 scantrig = PCI230P2_DAC_TRIG_SW;
1383 /* Shouldn't get here. */
1384 scantrig = PCI230P2_DAC_TRIG_NONE;
1387 devpriv->daccon = (devpriv->daccon
1388 & ~PCI230P2_DAC_TRIG_MASK) |
1390 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1393 switch (cmd->scan_begin_src) {
1395 if (devpriv->hwver < 2) {
1396 /* Not using DAC FIFO. */
1397 /* Enable CT1 timer interrupt. */
1398 spin_lock_irqsave(&devpriv->isr_spinlock,
1400 devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1401 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1403 devpriv->iobase1 + PCI230_INT_SCE);
1404 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1407 /* Set CT1 gate high to start counting. */
1408 outb(GAT_CONFIG(1, GAT_VCC),
1409 devpriv->iobase1 + PCI230_ZGAT_SCE);
1412 async->inttrig = pci230_ao_inttrig_scan_begin;
1415 if (devpriv->hwver >= 2) {
1416 /* Using DAC FIFO. Enable DAC FIFO interrupt. */
1417 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1418 devpriv->int_en |= PCI230P2_INT_DAC;
1419 devpriv->ier |= PCI230P2_INT_DAC;
1420 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1421 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1427 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1428 struct comedi_subdevice *s,
1429 unsigned int trig_num)
1434 s->async->inttrig = NULL;
1435 pci230_ao_start(dev, s);
1440 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1442 struct pci230_private *devpriv = dev->private;
1443 unsigned short daccon;
1446 /* Get the command. */
1447 struct comedi_cmd *cmd = &s->async->cmd;
1449 if (cmd->scan_begin_src == TRIG_TIMER) {
1451 if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
1456 /* Get number of scans required. */
1457 if (cmd->stop_src == TRIG_COUNT) {
1458 devpriv->ao_scan_count = cmd->stop_arg;
1459 devpriv->ao_continuous = 0;
1461 /* TRIG_NONE, user calls cancel. */
1462 devpriv->ao_scan_count = 0;
1463 devpriv->ao_continuous = 1;
1466 /* Set range - see analogue output range table; 0 => unipolar 10V,
1467 * 1 => bipolar +/-10V range scale */
1468 range = CR_RANGE(cmd->chanlist[0]);
1469 devpriv->ao_bipolar = pci230_ao_bipolar[range];
1470 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1471 /* Use DAC FIFO for hardware version 2 onwards. */
1472 if (devpriv->hwver >= 2) {
1473 unsigned short dacen;
1477 for (i = 0; i < cmd->chanlist_len; i++)
1478 dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1480 /* Set channel scan list. */
1481 outw(dacen, dev->iobase + PCI230P2_DACEN);
1484 * Set DAC scan source to 'none'.
1485 * Set DAC FIFO interrupt trigger level to 'not half full'.
1486 * Reset DAC FIFO and clear underrun.
1488 * N.B. DAC FIFO interrupts are currently disabled.
1490 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1491 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1492 | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1496 outw(daccon, dev->iobase + PCI230_DACCON);
1497 /* Preserve most of DACCON apart from write-only, transient bits. */
1498 devpriv->daccon = daccon
1499 & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1501 if (cmd->scan_begin_src == TRIG_TIMER) {
1502 /* Set the counter timer 1 to the specified scan frequency. */
1503 /* cmd->scan_begin_arg is sampling period in ns */
1504 /* gate it off for now. */
1505 outb(GAT_CONFIG(1, GAT_GND),
1506 devpriv->iobase1 + PCI230_ZGAT_SCE);
1507 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1508 cmd->scan_begin_arg,
1509 cmd->flags & TRIG_ROUND_MASK);
1512 /* N.B. cmd->start_src == TRIG_INT */
1513 s->async->inttrig = pci230_ao_inttrig_start;
1518 static int pci230_ao_cancel(struct comedi_device *dev,
1519 struct comedi_subdevice *s)
1521 pci230_ao_stop(dev, s);
1525 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1527 unsigned int min_scan_period, chanlist_len;
1530 chanlist_len = cmd->chanlist_len;
1531 if (cmd->chanlist_len == 0)
1534 min_scan_period = chanlist_len * cmd->convert_arg;
1535 if ((min_scan_period < chanlist_len)
1536 || (min_scan_period < cmd->convert_arg)) {
1537 /* Arithmetic overflow. */
1538 min_scan_period = UINT_MAX;
1541 if (cmd->scan_begin_arg < min_scan_period) {
1542 cmd->scan_begin_arg = min_scan_period;
1549 static int pci230_ai_cmdtest(struct comedi_device *dev,
1550 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1552 const struct pci230_board *thisboard = comedi_board(dev);
1553 struct pci230_private *devpriv = dev->private;
1557 /* Step 1 : check if triggers are trivially valid */
1559 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1561 tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1562 if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1564 * Unfortunately, we cannot trigger a scan off an external
1565 * source on the PCI260 board, since it uses the PPIC0 (DIO)
1566 * input, which isn't present on the PCI260. For PCI260+
1567 * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead.
1571 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
1572 err |= cfc_check_trigger_src(&cmd->convert_src,
1573 TRIG_TIMER | TRIG_INT | TRIG_EXT);
1574 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1575 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1580 /* Step 2a : make sure trigger sources are unique */
1582 err |= cfc_check_trigger_is_unique(cmd->start_src);
1583 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1584 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1585 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1587 /* Step 2b : and mutually compatible */
1590 * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1591 * set up to generate a fixed number of timed conversion pulses.
1593 if ((cmd->scan_begin_src != TRIG_FOLLOW)
1594 && (cmd->convert_src != TRIG_TIMER))
1600 /* Step 3: check if arguments are trivially valid */
1602 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1604 #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */
1605 #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */
1606 #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */
1607 #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */
1608 /*- Comedi limit due to unsigned int cmd. Driver limit
1609 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1610 * clock) = 65.536s */
1612 if (cmd->convert_src == TRIG_TIMER) {
1613 unsigned int max_speed_ai;
1615 if (devpriv->hwver == 0) {
1616 /* PCI230 or PCI260. Max speed depends whether
1617 * single-ended or pseudo-differential. */
1618 if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1619 /* Peek analogue reference of first channel. */
1620 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1621 max_speed_ai = MAX_SPEED_AI_DIFF;
1623 max_speed_ai = MAX_SPEED_AI_SE;
1626 /* No channel list. Assume single-ended. */
1627 max_speed_ai = MAX_SPEED_AI_SE;
1630 /* PCI230+ or PCI260+. */
1631 max_speed_ai = MAX_SPEED_AI_PLUS;
1634 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1636 err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
1638 } else if (cmd->convert_src == TRIG_EXT) {
1642 * convert_arg == (CR_EDGE | 0)
1643 * => trigger on +ve edge.
1644 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1645 * => trigger on -ve edge.
1647 if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1648 /* Trigger number must be 0. */
1649 if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1650 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1654 /* The only flags allowed are CR_INVERT and CR_EDGE.
1655 * CR_EDGE is required. */
1656 if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1658 /* Set CR_EDGE, preserve CR_INVERT. */
1659 cmd->convert_arg = COMBINE(cmd->start_arg,
1666 /* Backwards compatibility with previous versions. */
1667 /* convert_arg == 0 => trigger on -ve edge. */
1668 /* convert_arg == 1 => trigger on +ve edge. */
1669 err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1);
1672 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1675 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1677 if (cmd->stop_src == TRIG_NONE)
1678 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1680 if (cmd->scan_begin_src == TRIG_EXT) {
1681 /* external "trigger" to begin each scan
1682 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1683 * of CT2 (sample convert trigger is CT2) */
1684 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1685 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1689 /* The only flag allowed is CR_EDGE, which is ignored. */
1690 if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1691 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1692 CR_FLAGS_MASK & ~CR_EDGE);
1695 } else if (cmd->scan_begin_src == TRIG_TIMER) {
1696 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1697 if (!pci230_ai_check_scan_period(cmd))
1701 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1707 /* Step 4: fix up any arguments.
1708 * "argument conflict" returned by comedilib to user mode process
1711 if (cmd->convert_src == TRIG_TIMER) {
1712 tmp = cmd->convert_arg;
1713 pci230_ns_to_single_timer(&cmd->convert_arg,
1714 cmd->flags & TRIG_ROUND_MASK);
1715 if (tmp != cmd->convert_arg)
1719 if (cmd->scan_begin_src == TRIG_TIMER) {
1720 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1721 tmp = cmd->scan_begin_arg;
1722 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1723 cmd->flags & TRIG_ROUND_MASK);
1724 if (!pci230_ai_check_scan_period(cmd)) {
1725 /* Was below minimum required. Round up. */
1726 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1728 pci230_ai_check_scan_period(cmd);
1730 if (tmp != cmd->scan_begin_arg)
1737 /* Step 5: check channel list if it exists. */
1739 if (cmd->chanlist && cmd->chanlist_len > 0) {
1742 rangepair_err = 1 << 1,
1743 polarity_err = 1 << 2,
1745 diffchan_err = 1 << 4,
1746 buggy_chan0_err = 1 << 5
1748 unsigned int errors;
1749 unsigned int chan, prev_chan;
1750 unsigned int range, prev_range;
1751 unsigned int polarity, prev_polarity;
1752 unsigned int aref, prev_aref;
1753 unsigned int subseq_len;
1758 prev_chan = prev_aref = prev_range = prev_polarity = 0;
1759 for (n = 0; n < cmd->chanlist_len; n++) {
1760 chan = CR_CHAN(cmd->chanlist[n]);
1761 range = CR_RANGE(cmd->chanlist[n]);
1762 aref = CR_AREF(cmd->chanlist[n]);
1763 polarity = pci230_ai_bipolar[range];
1764 /* Only the first half of the channels are available if
1765 * differential. (These are remapped in software. In
1766 * hardware, only the even channels are available.) */
1767 if ((aref == AREF_DIFF)
1768 && (chan >= (s->n_chan / 2))) {
1769 errors |= diffchan_err;
1772 /* Channel numbers must strictly increase or
1773 * subsequence must repeat exactly. */
1774 if ((chan <= prev_chan)
1775 && (subseq_len == 0)) {
1778 if ((subseq_len > 0)
1779 && (cmd->chanlist[n] !=
1780 cmd->chanlist[n % subseq_len])) {
1783 /* Channels must have same AREF. */
1784 if (aref != prev_aref)
1787 /* Channel ranges must have same polarity. */
1788 if (polarity != prev_polarity)
1789 errors |= polarity_err;
1791 /* Single-ended channel pairs must have same
1793 if ((aref != AREF_DIFF)
1794 && (((chan ^ prev_chan) & ~1) == 0)
1795 && (range != prev_range)) {
1796 errors |= rangepair_err;
1802 prev_polarity = polarity;
1804 if (subseq_len == 0) {
1805 /* Subsequence is whole sequence. */
1808 /* If channel list is a repeating subsequence, need a whole
1809 * number of repeats. */
1810 if ((n % subseq_len) != 0)
1813 if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
1815 * Buggy PCI230+ or PCI260+ requires channel 0 to be
1816 * (first) in the sequence if the sequence contains
1817 * more than one channel. Hardware versions 1 and 2
1818 * have the bug. There is no hardware version 3.
1820 * Actually, there are two firmwares that report
1821 * themselves as hardware version 1 (the boards
1822 * have different ADC chips with slightly different
1823 * timing requirements, which was supposed to be
1824 * invisible to software). The first one doesn't
1825 * seem to have the bug, but the second one
1826 * does, and we can't tell them apart!
1828 if ((subseq_len > 1)
1829 && (CR_CHAN(cmd->chanlist[0]) != 0)) {
1830 errors |= buggy_chan0_err;
1835 if ((errors & seq_err) != 0) {
1836 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1837 "channel numbers must increase or "
1838 "sequence must repeat exactly\n",
1841 if ((errors & rangepair_err) != 0) {
1842 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1843 "single-ended channel pairs must "
1844 "have the same range\n", dev->minor);
1846 if ((errors & polarity_err) != 0) {
1847 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1848 "channel sequence ranges must be all "
1849 "bipolar or all unipolar\n",
1852 if ((errors & aref_err) != 0) {
1853 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1854 "channel sequence analogue references "
1855 "must be all the same (single-ended "
1856 "or differential)\n", dev->minor);
1858 if ((errors & diffchan_err) != 0) {
1859 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1860 "differential channel number out of "
1861 "range 0 to %u\n", dev->minor,
1862 (s->n_chan / 2) - 1);
1864 if ((errors & buggy_chan0_err) != 0) {
1865 dev_info(dev->class_dev,
1866 "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",
1878 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
1879 struct comedi_subdevice *s)
1881 struct pci230_private *devpriv = dev->private;
1882 struct comedi_cmd *cmd = &s->async->cmd;
1883 unsigned int scanlen = cmd->scan_end_arg;
1885 unsigned short triglev;
1886 unsigned short adccon;
1888 if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
1889 /* Wake at end of scan. */
1890 wake = scanlen - devpriv->ai_scan_pos;
1892 if (devpriv->ai_continuous
1893 || (devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL)
1894 || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
1895 wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
1897 wake = (devpriv->ai_scan_count * scanlen)
1898 - devpriv->ai_scan_pos;
1901 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
1902 triglev = PCI230_ADC_INT_FIFO_HALF;
1904 if ((wake > 1) && (devpriv->hwver > 0)) {
1905 /* PCI230+/260+ programmable FIFO interrupt level. */
1906 if (devpriv->adcfifothresh != wake) {
1907 devpriv->adcfifothresh = wake;
1908 outw(wake, dev->iobase + PCI230P_ADCFFTH);
1910 triglev = PCI230P_ADC_INT_FIFO_THRESH;
1912 triglev = PCI230_ADC_INT_FIFO_NEMPTY;
1915 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
1916 if (adccon != devpriv->adccon) {
1917 devpriv->adccon = adccon;
1918 outw(adccon, dev->iobase + PCI230_ADCCON);
1922 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
1923 struct comedi_subdevice *s,
1924 unsigned int trig_num)
1926 struct pci230_private *devpriv = dev->private;
1927 unsigned long irqflags;
1932 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1933 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1934 unsigned int delayus;
1936 /* Trigger conversion by toggling Z2-CT2 output. Finish
1937 * with output high. */
1938 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1940 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1942 /* Delay. Should driver be responsible for this? An
1943 * alternative would be to wait until conversion is complete,
1944 * but we can't tell when it's complete because the ADC busy
1945 * bit has a different meaning when FIFO enabled (and when
1946 * FIFO not enabled, it only works for software triggers). */
1947 if (((devpriv->adccon & PCI230_ADC_IM_MASK)
1948 == PCI230_ADC_IM_DIF)
1949 && (devpriv->hwver == 0)) {
1950 /* PCI230/260 in differential mode */
1953 /* single-ended or PCI230+/260+ */
1956 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1959 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1965 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
1966 struct comedi_subdevice *s,
1967 unsigned int trig_num)
1969 struct pci230_private *devpriv = dev->private;
1970 unsigned long irqflags;
1976 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1977 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1978 /* Trigger scan by waggling CT0 gate source. */
1979 zgat = GAT_CONFIG(0, GAT_GND);
1980 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1981 zgat = GAT_CONFIG(0, GAT_VCC);
1982 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1984 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1989 static void pci230_ai_stop(struct comedi_device *dev,
1990 struct comedi_subdevice *s)
1992 struct pci230_private *devpriv = dev->private;
1993 unsigned long irqflags;
1994 struct comedi_cmd *cmd;
1997 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1998 started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
1999 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2002 cmd = &s->async->cmd;
2003 if (cmd->convert_src == TRIG_TIMER) {
2004 /* Stop conversion rate generator. */
2005 pci230_cancel_ct(dev, 2);
2007 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2008 /* Stop scan period monostable. */
2009 pci230_cancel_ct(dev, 0);
2011 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2012 /* Disable ADC interrupt and wait for interrupt routine to finish
2013 * running unless we are called from the interrupt routine. */
2014 devpriv->int_en &= ~PCI230_INT_ADC;
2015 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2016 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2017 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2019 if (devpriv->ier != devpriv->int_en) {
2020 devpriv->ier = devpriv->int_en;
2021 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2023 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2024 /* Reset FIFO, disable FIFO and set start conversion source to none.
2025 * Keep se/diff and bip/uni settings */
2026 devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
2027 | PCI230_ADC_IM_MASK)) |
2028 PCI230_ADC_TRIG_NONE;
2029 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2030 dev->iobase + PCI230_ADCCON);
2031 /* Release resources. */
2032 put_all_resources(dev, OWNER_AICMD);
2035 static void pci230_ai_start(struct comedi_device *dev,
2036 struct comedi_subdevice *s)
2038 struct pci230_private *devpriv = dev->private;
2039 unsigned long irqflags;
2040 unsigned short conv;
2041 struct comedi_async *async = s->async;
2042 struct comedi_cmd *cmd = &async->cmd;
2044 set_bit(AI_CMD_STARTED, &devpriv->state);
2045 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2046 /* An empty acquisition! */
2047 async->events |= COMEDI_CB_EOA;
2048 pci230_ai_stop(dev, s);
2049 comedi_event(dev, s);
2051 /* Enable ADC FIFO trigger level interrupt. */
2052 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2053 devpriv->int_en |= PCI230_INT_ADC;
2054 devpriv->ier |= PCI230_INT_ADC;
2055 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2056 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2058 /* Update conversion trigger source which is currently set
2059 * to CT2 output, which is currently stuck high. */
2060 switch (cmd->convert_src) {
2062 conv = PCI230_ADC_TRIG_NONE;
2065 /* Using CT2 output. */
2066 conv = PCI230_ADC_TRIG_Z2CT2;
2069 if ((cmd->convert_arg & CR_EDGE) != 0) {
2070 if ((cmd->convert_arg & CR_INVERT) == 0) {
2071 /* Trigger on +ve edge. */
2072 conv = PCI230_ADC_TRIG_EXTP;
2074 /* Trigger on -ve edge. */
2075 conv = PCI230_ADC_TRIG_EXTN;
2078 /* Backwards compatibility. */
2079 if (cmd->convert_arg != 0) {
2080 /* Trigger on +ve edge. */
2081 conv = PCI230_ADC_TRIG_EXTP;
2083 /* Trigger on -ve edge. */
2084 conv = PCI230_ADC_TRIG_EXTN;
2089 /* Use CT2 output for software trigger due to problems
2090 * in differential mode on PCI230/260. */
2091 conv = PCI230_ADC_TRIG_Z2CT2;
2094 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
2096 outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
2097 if (cmd->convert_src == TRIG_INT)
2098 async->inttrig = pci230_ai_inttrig_convert;
2100 /* Update FIFO interrupt trigger level, which is currently
2102 pci230_ai_update_fifo_trigger_level(dev, s);
2103 if (cmd->convert_src == TRIG_TIMER) {
2104 /* Update timer gates. */
2107 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2108 /* Conversion timer CT2 needs to be gated by
2109 * inverted output of monostable CT2. */
2110 zgat = GAT_CONFIG(2, GAT_NOUTNM2);
2112 /* Conversion timer CT2 needs to be gated on
2114 zgat = GAT_CONFIG(2, GAT_VCC);
2116 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2117 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2118 /* Set monostable CT0 trigger source. */
2119 switch (cmd->scan_begin_src) {
2121 zgat = GAT_CONFIG(0, GAT_VCC);
2125 * For CT0 on PCI230, the external
2126 * trigger (gate) signal comes from
2127 * PPC0, which is channel 16 of the DIO
2128 * subdevice. The application needs to
2129 * configure this as an input in order
2130 * to use it as an external scan
2133 zgat = GAT_CONFIG(0, GAT_EXT);
2137 * Monostable CT0 triggered by rising
2138 * edge on inverted output of CT1
2139 * (falling edge on CT1).
2141 zgat = GAT_CONFIG(0, GAT_NOUTNM2);
2145 * Monostable CT0 is triggered by
2146 * inttrig function waggling the CT0
2149 zgat = GAT_CONFIG(0, GAT_VCC);
2152 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2153 switch (cmd->scan_begin_src) {
2155 /* Scan period timer CT1 needs to be
2156 * gated on to start counting. */
2157 zgat = GAT_CONFIG(1, GAT_VCC);
2158 outb(zgat, devpriv->iobase1
2163 pci230_ai_inttrig_scan_begin;
2167 } else if (cmd->convert_src != TRIG_INT) {
2168 /* No longer need Z2-CT2. */
2169 put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
2174 static int pci230_ai_inttrig_start(struct comedi_device *dev,
2175 struct comedi_subdevice *s,
2176 unsigned int trig_num)
2181 s->async->inttrig = NULL;
2182 pci230_ai_start(dev, s);
2187 static void pci230_handle_ai(struct comedi_device *dev,
2188 struct comedi_subdevice *s)
2190 struct pci230_private *devpriv = dev->private;
2191 unsigned int events = 0;
2192 unsigned int status_fifo;
2195 unsigned int fifoamount;
2196 struct comedi_async *async = s->async;
2197 unsigned int scanlen = async->cmd.scan_end_arg;
2199 /* Determine number of samples to read. */
2200 if (devpriv->ai_continuous) {
2201 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2202 } else if (devpriv->ai_scan_count == 0) {
2204 } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2205 || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2206 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2208 todo = (devpriv->ai_scan_count * scanlen)
2209 - devpriv->ai_scan_pos;
2210 if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
2211 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2216 for (i = 0; i < todo; i++) {
2217 if (fifoamount == 0) {
2218 /* Read FIFO state. */
2219 status_fifo = inw(dev->iobase + PCI230_ADCCON);
2220 if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2221 /* Report error otherwise FIFO overruns will go
2222 * unnoticed by the caller. */
2223 comedi_error(dev, "AI FIFO overrun");
2224 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2226 } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2229 } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2230 /* FIFO half full. */
2231 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2233 /* FIFO not empty. */
2234 if (devpriv->hwver > 0) {
2235 /* Read PCI230+/260+ ADC FIFO level. */
2236 fifoamount = inw(dev->iobase
2237 + PCI230P_ADCFFLEV);
2238 if (fifoamount == 0) {
2239 /* Shouldn't happen. */
2247 /* Read sample and store in Comedi's circular buffer. */
2248 if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2249 events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2250 comedi_error(dev, "AI buffer overflow");
2254 devpriv->ai_scan_pos++;
2255 if (devpriv->ai_scan_pos == scanlen) {
2257 devpriv->ai_scan_pos = 0;
2258 devpriv->ai_scan_count--;
2259 async->events |= COMEDI_CB_EOS;
2262 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2263 /* End of acquisition. */
2264 events |= COMEDI_CB_EOA;
2266 /* More samples required, tell Comedi to block. */
2267 events |= COMEDI_CB_BLOCK;
2269 async->events |= events;
2270 if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2271 COMEDI_CB_OVERFLOW)) != 0) {
2272 /* disable hardware conversions */
2273 pci230_ai_stop(dev, s);
2275 /* update FIFO interrupt trigger level */
2276 pci230_ai_update_fifo_trigger_level(dev, s);
2280 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2282 struct pci230_private *devpriv = dev->private;
2283 unsigned int i, chan, range, diff;
2284 unsigned int res_mask;
2285 unsigned short adccon, adcen;
2288 /* Get the command. */
2289 struct comedi_async *async = s->async;
2290 struct comedi_cmd *cmd = &async->cmd;
2293 * Determine which shared resources are needed.
2296 /* Need Z2-CT2 to supply a conversion trigger source at a high
2297 * logic level, even if not doing timed conversions. */
2298 res_mask |= (1U << RES_Z2CT2);
2299 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2300 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2301 res_mask |= (1U << RES_Z2CT0);
2302 if (cmd->scan_begin_src == TRIG_TIMER) {
2303 /* Using Z2-CT1 for scan frequency */
2304 res_mask |= (1U << RES_Z2CT1);
2307 /* Claim resources. */
2308 if (!get_resources(dev, res_mask, OWNER_AICMD))
2312 /* Get number of scans required. */
2313 if (cmd->stop_src == TRIG_COUNT) {
2314 devpriv->ai_scan_count = cmd->stop_arg;
2315 devpriv->ai_continuous = 0;
2317 /* TRIG_NONE, user calls cancel. */
2318 devpriv->ai_scan_count = 0;
2319 devpriv->ai_continuous = 1;
2321 devpriv->ai_scan_pos = 0; /* Position within scan. */
2324 * - Set channel scan list.
2325 * - Set channel gains.
2326 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2327 * start conversion source to point to something at a high logic
2328 * level (we use the output of counter/timer 2 for this purpose.
2329 * - PAUSE to allow things to settle down.
2330 * - Reset the FIFO again because it needs resetting twice and there
2331 * may have been a false conversion trigger on some versions of
2332 * PCI230/260 due to the start conversion source being set to a
2334 * - Enable ADC FIFO level interrupt.
2335 * - Set actual conversion trigger source and FIFO interrupt trigger
2337 * - If convert_src is TRIG_TIMER, set up the timers.
2340 adccon = PCI230_ADC_FIFO_EN;
2343 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2344 /* Differential - all channels must be differential. */
2346 adccon |= PCI230_ADC_IM_DIF;
2348 /* Single ended - all channels must be single-ended. */
2350 adccon |= PCI230_ADC_IM_SE;
2353 range = CR_RANGE(cmd->chanlist[0]);
2354 devpriv->ai_bipolar = pci230_ai_bipolar[range];
2355 if (devpriv->ai_bipolar)
2356 adccon |= PCI230_ADC_IR_BIP;
2358 adccon |= PCI230_ADC_IR_UNI;
2360 for (i = 0; i < cmd->chanlist_len; i++) {
2361 unsigned int gainshift;
2363 chan = CR_CHAN(cmd->chanlist[i]);
2364 range = CR_RANGE(cmd->chanlist[i]);
2366 gainshift = 2 * chan;
2367 if (devpriv->hwver == 0) {
2368 /* Original PCI230/260 expects both inputs of
2369 * the differential channel to be enabled. */
2370 adcen |= 3 << gainshift;
2372 /* PCI230+/260+ expects only one input of the
2373 * differential channel to be enabled. */
2374 adcen |= 1 << gainshift;
2377 gainshift = (chan & ~1);
2380 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2381 | (pci230_ai_gain[range] << gainshift);
2384 /* Set channel scan list. */
2385 outw(adcen, dev->iobase + PCI230_ADCEN);
2387 /* Set channel gains. */
2388 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2390 /* Set counter/timer 2 output high for use as the initial start
2391 * conversion source. */
2392 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2394 /* Temporarily use CT2 output as conversion trigger source and
2395 * temporarily set FIFO interrupt trigger level to 'full'. */
2396 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2398 /* Enable and reset FIFO, specify FIFO trigger level full, specify
2399 * uni/bip, se/diff, and temporarily set the start conversion source
2400 * to CT2 output. Note that CT2 output is currently high, and this
2401 * will produce a false conversion trigger on some versions of the
2402 * PCI230/260, but that will be dealt with later. */
2403 devpriv->adccon = adccon;
2404 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2407 /* Failure to include this will result in the first few channels'-worth
2408 * of data being corrupt, normally manifesting itself by large negative
2409 * voltages. It seems the board needs time to settle between the first
2410 * FIFO reset (above) and the second FIFO reset (below). Setting the
2411 * channel gains and scan list _before_ the first FIFO reset also
2412 * helps, though only slightly. */
2415 /* Reset FIFO again. */
2416 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2418 if (cmd->convert_src == TRIG_TIMER) {
2419 /* Set up CT2 as conversion timer, but gate it off for now.
2420 * Note, counter/timer output 2 can be monitored on the
2421 * connector: PCI230 pin 21, PCI260 pin 18. */
2422 zgat = GAT_CONFIG(2, GAT_GND);
2423 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2424 /* Set counter/timer 2 to the specified conversion period. */
2425 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2426 cmd->flags & TRIG_ROUND_MASK);
2427 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2429 * Set up monostable on CT0 output for scan timing. A
2430 * rising edge on the trigger (gate) input of CT0 will
2431 * trigger the monostable, causing its output to go low
2432 * for the configured period. The period depends on
2433 * the conversion period and the number of conversions
2436 * Set the trigger high before setting up the
2437 * monostable to stop it triggering. The trigger
2438 * source will be changed later.
2440 zgat = GAT_CONFIG(0, GAT_VCC);
2441 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2442 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2443 ((uint64_t) cmd->convert_arg
2444 * cmd->scan_end_arg),
2446 if (cmd->scan_begin_src == TRIG_TIMER) {
2448 * Monostable on CT0 will be triggered by
2449 * output of CT1 at configured scan frequency.
2451 * Set up CT1 but gate it off for now.
2453 zgat = GAT_CONFIG(1, GAT_GND);
2454 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2455 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2456 cmd->scan_begin_arg,
2464 if (cmd->start_src == TRIG_INT) {
2465 s->async->inttrig = pci230_ai_inttrig_start;
2468 pci230_ai_start(dev, s);
2474 static int pci230_ai_cancel(struct comedi_device *dev,
2475 struct comedi_subdevice *s)
2477 pci230_ai_stop(dev, s);
2481 /* Interrupt handler */
2482 static irqreturn_t pci230_interrupt(int irq, void *d)
2484 unsigned char status_int, valid_status_int;
2485 struct comedi_device *dev = (struct comedi_device *)d;
2486 struct pci230_private *devpriv = dev->private;
2487 struct comedi_subdevice *s;
2488 unsigned long irqflags;
2490 /* Read interrupt status/enable register. */
2491 status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2493 if (status_int == PCI230_INT_DISABLE)
2497 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2498 valid_status_int = devpriv->int_en & status_int;
2499 /* Disable triggered interrupts.
2500 * (Only those interrupts that need re-enabling, are, later in the
2502 devpriv->ier = devpriv->int_en & ~status_int;
2503 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2504 devpriv->intr_running = 1;
2505 devpriv->intr_cpuid = THISCPU;
2506 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2509 * Check the source of interrupt and handle it.
2510 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2511 * interrupts. However, at present (Comedi-0.7.60) does not allow
2512 * concurrent execution of commands, instructions or a mixture of the
2516 if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2517 s = dev->write_subdev;
2518 pci230_handle_ao_nofifo(dev, s);
2519 comedi_event(dev, s);
2522 if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2523 s = dev->write_subdev;
2524 pci230_handle_ao_fifo(dev, s);
2525 comedi_event(dev, s);
2528 if ((valid_status_int & PCI230_INT_ADC) != 0) {
2529 s = dev->read_subdev;
2530 pci230_handle_ai(dev, s);
2531 comedi_event(dev, s);
2534 /* Reenable interrupts. */
2535 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2536 if (devpriv->ier != devpriv->int_en) {
2537 devpriv->ier = devpriv->int_en;
2538 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2540 devpriv->intr_running = 0;
2541 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2546 /* Check if PCI device matches a specific board. */
2547 static bool pci230_match_pci_board(const struct pci230_board *board,
2548 struct pci_dev *pci_dev)
2550 /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */
2551 if (board->id != pci_dev->device)
2553 if (board->min_hwver == 0)
2555 /* Looking for a '+' model. First check length of registers. */
2556 if (pci_resource_len(pci_dev, 3) < 32)
2557 return false; /* Not a '+' model. */
2558 /* TODO: temporarily enable PCI device and read the hardware version
2559 * register. For now, assume it's okay. */
2563 /* Look for board matching PCI device. */
2564 static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev)
2568 for (i = 0; i < ARRAY_SIZE(pci230_boards); i++)
2569 if (pci230_match_pci_board(&pci230_boards[i], pci_dev))
2570 return &pci230_boards[i];
2574 /* Look for PCI device matching requested board name, bus and slot. */
2575 static struct pci_dev *pci230_find_pci_dev(struct comedi_device *dev,
2576 struct comedi_devconfig *it)
2578 const struct pci230_board *thisboard = comedi_board(dev);
2579 struct pci_dev *pci_dev = NULL;
2580 int bus = it->options[0];
2581 int slot = it->options[1];
2583 for_each_pci_dev(pci_dev) {
2584 /* Check vendor ID (same for all supported PCI boards). */
2585 if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
2587 /* If bus/slot specified, check them. */
2588 if ((bus || slot) &&
2589 (bus != pci_dev->bus->number ||
2590 slot != PCI_SLOT(pci_dev->devfn)))
2592 if (thisboard->id == PCI_DEVICE_ID_INVALID) {
2593 /* Wildcard board matches any supported PCI board. */
2594 const struct pci230_board *foundboard;
2596 foundboard = pci230_find_pci_board(pci_dev);
2597 if (foundboard == NULL)
2599 /* Replace wildcard board_ptr. */
2600 dev->board_ptr = foundboard;
2602 /* Need to match a specific board. */
2603 if (!pci230_match_pci_board(thisboard, pci_dev))
2608 dev_err(dev->class_dev,
2609 "No supported board found! (req. bus %d, slot %d)\n",
2614 static int pci230_alloc_private(struct comedi_device *dev)
2616 struct pci230_private *devpriv;
2618 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
2621 dev->private = 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");