2 comedi/drivers/amplc_pci230.c
3 Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
5 Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
7 COMEDI - Linux Control and Measurement Device Interface
8 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 Description: Amplicon PCI230, PCI260 Multifunction I/O boards
27 Author: Allan Willcox <allanwillcox@ozemail.com.au>,
28 Steve D Sharples <steve.sharples@nottingham.ac.uk>,
29 Ian Abbott <abbotti@mev.co.uk>
30 Updated: Wed, 22 Oct 2008 12:34:49 +0100
31 Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
32 PCI230+ (pci230+ or amplc_pci230),
33 PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
36 Configuration options:
37 [0] - PCI bus of device (optional).
38 [1] - PCI slot of device (optional).
39 If bus/slot is not specified, the first available PCI device
42 Configuring a "amplc_pci230" will match any supported card and it will
43 choose the best match, picking the "+" models if possible. Configuring
44 a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
45 a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card
46 and it will be treated as a PCI260. Configuring a "pci230+" will match
47 a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card.
60 The AI subdevice has 16 single-ended channels or 8 differential
63 The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and
64 PCI260+ cards have 16-bit resolution.
66 For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
67 inputs 14 and 15 for channel 7). If the card is physically a PCI230
68 or PCI260 then it actually uses a "pseudo-differential" mode where the
69 inputs are sampled a few microseconds apart. The PCI230+ and PCI260+
70 use true differential sampling. Another difference is that if the
71 card is physically a PCI230 or PCI260, the inverting input is 2N,
72 whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a
73 PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
74 PCI260+) and differential mode is used, the differential inputs need
75 to be physically swapped on the connector.
77 The following input ranges are supported:
89 +=========+==============+===========+============+==========+
90 |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
91 +=========+==============+===========+============+==========+
92 |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
93 |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT|
95 | |--------------|-----------| | |
96 | | TRIG_TIMER(1)|TRIG_TIMER | | |
97 | | TRIG_EXT(2) | | | |
99 +---------+--------------+-----------+------------+----------+
101 Note 1: If AI command and AO command are used simultaneously, only
102 one may have scan_begin_src == TRIG_TIMER.
104 Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
105 DIO channel 16 (pin 49) which will need to be configured as
106 a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input
107 (pin 17) is used instead. For PCI230, scan_begin_src ==
108 TRIG_EXT is not supported. The trigger is a rising edge
111 Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
112 (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The
113 convert_arg value is interpreted as follows:
115 convert_arg == (CR_EDGE | 0) => rising edge
116 convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
117 convert_arg == 0 => falling edge (backwards compatibility)
118 convert_arg == 1 => rising edge (backwards compatibility)
120 All entries in the channel list must use the same analogue reference.
121 If the analogue reference is not AREF_DIFF (not differential) each
122 pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
123 input range. The input ranges used in the sequence must be all
124 bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel
125 sequence must consist of 1 or more identical subsequences. Within the
126 subsequence, channels must be in ascending order with no repeated
127 channels. For example, the following sequences are valid: 0 1 2 3
128 (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
129 subsequence), 1 1 1 1 (repeated valid subsequence). The following
130 sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
131 (incompletely repeated subsequence). Some versions of the PCI230+ and
132 PCI260+ have a bug that requires a subsequence longer than one entry
133 long to include channel 0.
137 The AO subdevice has 2 channels with 12-bit resolution.
139 The following output ranges are supported:
146 +=========+==============+===========+============+==========+
147 |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
148 +=========+==============+===========+============+==========+
149 |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE |
150 | | TRIG_EXT(2) | | |TRIG_COUNT|
152 +---------+--------------+-----------+------------+----------+
154 Note 1: If AI command and AO command are used simultaneously, only
155 one may have scan_begin_src == TRIG_TIMER.
157 Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
158 configured as a PCI230+ and is only supported on later
159 versions of the card. As a card configured as a PCI230+ is
160 not guaranteed to support external triggering, please consider
161 this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK
162 input (PCI230+ pin 25). Triggering will be on the rising edge
163 unless the CR_INVERT flag is set in scan_begin_arg.
165 The channels in the channel sequence must be in ascending order with
166 no repeats. All entries in the channel sequence must use the same
171 The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO
172 channels are configurable as inputs or outputs in four groups:
174 Port A - channels 0 to 7
175 Port B - channels 8 to 15
176 Port CL - channels 16 to 19
177 Port CH - channels 20 to 23
179 Only mode 0 of the 8255 chip is supported.
181 Bit 0 of port C (DIO channel 16) is also used as an external scan
182 trigger input for AI commands on PCI230 and PCI230+, so would need to
183 be configured as an input to use it for that purpose.
186 Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples.
187 Support for PCI230+/260+, more triggered scan functionality, and workarounds
188 for (or detection of) various hardware problems added by Ian Abbott.
191 #include "../comedidev.h"
193 #include <linux/delay.h>
194 #include <linux/interrupt.h>
196 #include "comedi_fc.h"
200 /* PCI230 PCI configuration register information */
201 #define PCI_DEVICE_ID_PCI230 0x0000
202 #define PCI_DEVICE_ID_PCI260 0x0006
203 #define PCI_DEVICE_ID_INVALID 0xffff
205 #define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */
206 #define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */
208 /* PCI230 i/o space 1 registers. */
209 #define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */
210 #define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */
211 #define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */
212 #define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */
213 #define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */
214 #define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */
215 #define PCI230_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
216 #define PCI230_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
217 #define PCI230_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
218 #define PCI230_Z2_CTC 0x17 /* 82C54 counter/timer control word */
219 #define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */
220 #define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */
221 #define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */
222 #define PCI230_INT_STAT 0x1E /* Interrupt status (r) */
224 /* PCI230 i/o space 2 registers. */
225 #define PCI230_DACCON 0x00 /* DAC control */
226 #define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */
227 #define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */
228 #define PCI230_ADCDATA 0x08 /* ADC data (r) */
229 #define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */
230 #define PCI230_ADCCON 0x0A /* ADC control */
231 #define PCI230_ADCEN 0x0C /* ADC channel enable bits */
232 #define PCI230_ADCG 0x0E /* ADC gain control bits */
233 /* PCI230+ i/o space 2 additional registers. */
234 #define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */
235 #define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */
236 #define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */
237 #define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */
238 #define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */
239 #define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */
240 #define PCI230P_EXTFUNC 0x1C /* Extended functions */
241 #define PCI230P_HWVER 0x1E /* Hardware version (r) */
242 /* PCI230+ hardware version 2 onwards. */
243 #define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */
244 #define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */
245 #define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */
247 /* Convertor related constants. */
248 #define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs */
249 /* (DAC itself is 1µs nominally). */
250 #define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs */
251 /* (ADC itself is 1.6µs nominally but we poll
253 #define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS */
254 /* - 10µs for se, 20µs de. */
256 /* DACCON read-write values. */
257 #define PCI230_DAC_OR_UNI (0<<0) /* Output range unipolar */
258 #define PCI230_DAC_OR_BIP (1<<0) /* Output range bipolar */
259 #define PCI230_DAC_OR_MASK (1<<0)
260 /* The following applies only if DAC FIFO support is enabled in the EXTFUNC
261 * register (and only for PCI230+ hardware version 2 onwards). */
262 #define PCI230P2_DAC_FIFO_EN (1<<8) /* FIFO enable */
263 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
264 * hardware version 2 onwards). */
265 #define PCI230P2_DAC_TRIG_NONE (0<<2) /* No trigger */
266 #define PCI230P2_DAC_TRIG_SW (1<<2) /* Software trigger trigger */
267 #define PCI230P2_DAC_TRIG_EXTP (2<<2) /* EXTTRIG +ve edge trigger */
268 #define PCI230P2_DAC_TRIG_EXTN (3<<2) /* EXTTRIG -ve edge trigger */
269 #define PCI230P2_DAC_TRIG_Z2CT0 (4<<2) /* CT0-OUT +ve edge trigger */
270 #define PCI230P2_DAC_TRIG_Z2CT1 (5<<2) /* CT1-OUT +ve edge trigger */
271 #define PCI230P2_DAC_TRIG_Z2CT2 (6<<2) /* CT2-OUT +ve edge trigger */
272 #define PCI230P2_DAC_TRIG_MASK (7<<2)
273 #define PCI230P2_DAC_FIFO_WRAP (1<<7) /* FIFO wraparound mode */
274 #define PCI230P2_DAC_INT_FIFO_EMPTY (0<<9) /* FIFO interrupt empty */
275 #define PCI230P2_DAC_INT_FIFO_NEMPTY (1<<9)
276 #define PCI230P2_DAC_INT_FIFO_NHALF (2<<9) /* FIFO intr not half full */
277 #define PCI230P2_DAC_INT_FIFO_HALF (3<<9)
278 #define PCI230P2_DAC_INT_FIFO_NFULL (4<<9) /* FIFO interrupt not full */
279 #define PCI230P2_DAC_INT_FIFO_FULL (5<<9)
280 #define PCI230P2_DAC_INT_FIFO_MASK (7<<9)
282 /* DACCON read-only values. */
283 #define PCI230_DAC_BUSY (1<<1) /* DAC busy. */
284 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
285 * hardware version 2 onwards). */
286 #define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1<<5) /* Underrun error */
287 #define PCI230P2_DAC_FIFO_EMPTY (1<<13) /* FIFO empty */
288 #define PCI230P2_DAC_FIFO_FULL (1<<14) /* FIFO full */
289 #define PCI230P2_DAC_FIFO_HALF (1<<15) /* FIFO half full */
291 /* DACCON write-only, transient values. */
292 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
293 * hardware version 2 onwards). */
294 #define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1<<5) /* Clear underrun */
295 #define PCI230P2_DAC_FIFO_RESET (1<<12) /* FIFO reset */
297 /* PCI230+ hardware version 2 DAC FIFO levels. */
298 #define PCI230P2_DAC_FIFOLEVEL_HALF 512
299 #define PCI230P2_DAC_FIFOLEVEL_FULL 1024
300 /* Free space in DAC FIFO. */
301 #define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL
302 #define PCI230P2_DAC_FIFOROOM_ONETOHALF \
303 (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
304 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1
305 #define PCI230P2_DAC_FIFOROOM_FULL 0
307 /* ADCCON read/write values. */
308 #define PCI230_ADC_TRIG_NONE (0<<0) /* No trigger */
309 #define PCI230_ADC_TRIG_SW (1<<0) /* Software trigger trigger */
310 #define PCI230_ADC_TRIG_EXTP (2<<0) /* EXTTRIG +ve edge trigger */
311 #define PCI230_ADC_TRIG_EXTN (3<<0) /* EXTTRIG -ve edge trigger */
312 #define PCI230_ADC_TRIG_Z2CT0 (4<<0) /* CT0-OUT +ve edge trigger */
313 #define PCI230_ADC_TRIG_Z2CT1 (5<<0) /* CT1-OUT +ve edge trigger */
314 #define PCI230_ADC_TRIG_Z2CT2 (6<<0) /* CT2-OUT +ve edge trigger */
315 #define PCI230_ADC_TRIG_MASK (7<<0)
316 #define PCI230_ADC_IR_UNI (0<<3) /* Input range unipolar */
317 #define PCI230_ADC_IR_BIP (1<<3) /* Input range bipolar */
318 #define PCI230_ADC_IR_MASK (1<<3)
319 #define PCI230_ADC_IM_SE (0<<4) /* Input mode single ended */
320 #define PCI230_ADC_IM_DIF (1<<4) /* Input mode differential */
321 #define PCI230_ADC_IM_MASK (1<<4)
322 #define PCI230_ADC_FIFO_EN (1<<8) /* FIFO enable */
323 #define PCI230_ADC_INT_FIFO_EMPTY (0<<9)
324 #define PCI230_ADC_INT_FIFO_NEMPTY (1<<9) /* FIFO interrupt not empty */
325 #define PCI230_ADC_INT_FIFO_NHALF (2<<9)
326 #define PCI230_ADC_INT_FIFO_HALF (3<<9) /* FIFO interrupt half full */
327 #define PCI230_ADC_INT_FIFO_NFULL (4<<9)
328 #define PCI230_ADC_INT_FIFO_FULL (5<<9) /* FIFO interrupt full */
329 #define PCI230P_ADC_INT_FIFO_THRESH (7<<9) /* FIFO interrupt threshold */
330 #define PCI230_ADC_INT_FIFO_MASK (7<<9)
332 /* ADCCON write-only, transient values. */
333 #define PCI230_ADC_FIFO_RESET (1<<12) /* FIFO reset */
334 #define PCI230_ADC_GLOB_RESET (1<<13) /* Global reset */
336 /* ADCCON read-only values. */
337 #define PCI230_ADC_BUSY (1<<15) /* ADC busy */
338 #define PCI230_ADC_FIFO_EMPTY (1<<12) /* FIFO empty */
339 #define PCI230_ADC_FIFO_FULL (1<<13) /* FIFO full */
340 #define PCI230_ADC_FIFO_HALF (1<<14) /* FIFO half full */
341 #define PCI230_ADC_FIFO_FULL_LATCHED (1<<5) /* Indicates overrun occurred */
343 /* PCI230 ADC FIFO levels. */
344 #define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */
345 #define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */
347 /* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
348 * mode. Can be anything. */
349 #define PCI230_ADC_CONV 0xffff
351 /* PCI230+ EXTFUNC values. */
352 #define PCI230P_EXTFUNC_GAT_EXTTRIG (1<<0)
353 /* Route EXTTRIG pin to external gate inputs. */
354 /* PCI230+ hardware version 2 values. */
355 #define PCI230P2_EXTFUNC_DACFIFO (1<<1)
356 /* Allow DAC FIFO to be enabled. */
359 * Counter/timer clock input configuration sources.
361 #define CLK_CLK 0 /* reserved (channel-specific clock) */
362 #define CLK_10MHZ 1 /* internal 10 MHz clock */
363 #define CLK_1MHZ 2 /* internal 1 MHz clock */
364 #define CLK_100KHZ 3 /* internal 100 kHz clock */
365 #define CLK_10KHZ 4 /* internal 10 kHz clock */
366 #define CLK_1KHZ 5 /* internal 1 kHz clock */
367 #define CLK_OUTNM1 6 /* output of channel-1 modulo total */
368 #define CLK_EXT 7 /* external clock */
369 /* Macro to construct clock input configuration register value. */
370 #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
371 /* Timebases in ns. */
372 #define TIMEBASE_10MHZ 100
373 #define TIMEBASE_1MHZ 1000
374 #define TIMEBASE_100KHZ 10000
375 #define TIMEBASE_10KHZ 100000
376 #define TIMEBASE_1KHZ 1000000
379 * Counter/timer gate input configuration sources.
381 #define GAT_VCC 0 /* VCC (i.e. enabled) */
382 #define GAT_GND 1 /* GND (i.e. disabled) */
383 #define GAT_EXT 2 /* external gate input (PPCn on PCI230) */
384 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
385 /* Macro to construct gate input configuration register value. */
386 #define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
389 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
391 * Channel's Channel's
392 * clock input gate input
393 * Channel CLK_OUTNM1 GAT_NOUTNM2
394 * ------- ---------- -----------
395 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
396 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
397 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
400 /* Interrupt enables/status register values. */
401 #define PCI230_INT_DISABLE 0
402 #define PCI230_INT_PPI_C0 (1<<0)
403 #define PCI230_INT_PPI_C3 (1<<1)
404 #define PCI230_INT_ADC (1<<2)
405 #define PCI230_INT_ZCLK_CT1 (1<<5)
406 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
407 #define PCI230P2_INT_DAC (1<<4)
409 #define PCI230_TEST_BIT(val, n) ((val>>n)&1)
410 /* Assumes bits numbered with zero offset, ie. 0-15 */
412 /* (Potentially) shared resources and their owners */
414 RES_Z2CT0, /* Z2-CT0 */
415 RES_Z2CT1, /* Z2-CT1 */
416 RES_Z2CT2, /* Z2-CT2 */
417 NUM_RESOURCES /* Number of (potentially) shared resources. */
421 OWNER_NONE, /* Not owned */
422 OWNER_AICMD, /* Owned by AI command */
423 OWNER_AOCMD /* Owned by AO command */
430 /* Combine old and new bits. */
431 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
433 /* Current CPU. XXX should this be hard_smp_processor_id()? */
434 #define THISCPU smp_processor_id()
436 /* State flags for atomic bit operations */
437 #define AI_CMD_STARTED 0
438 #define AO_CMD_STARTED 1
441 * Board descriptions for the two boards supported.
444 struct pci230_board {
452 unsigned int min_hwver; /* Minimum hardware version supported. */
454 static const struct pci230_board pci230_boards[] = {
457 .id = PCI_DEVICE_ID_PCI230,
467 .id = PCI_DEVICE_ID_PCI260,
477 .id = PCI_DEVICE_ID_PCI230,
486 .id = PCI_DEVICE_ID_PCI260,
494 .name = "amplc_pci230", /* Wildcard matches any above */
495 .id = PCI_DEVICE_ID_INVALID,
499 /* this structure is for data unique to this hardware driver. If
500 several hardware drivers keep similar information in this structure,
501 feel free to suggest moving the variable to the struct comedi_device struct. */
502 struct pci230_private {
503 spinlock_t isr_spinlock; /* Interrupt spin lock */
504 spinlock_t res_spinlock; /* Shared resources spin lock */
505 spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
506 spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
507 unsigned long state; /* State flags */
508 unsigned long iobase1; /* PCI230's I/O space 1 */
509 unsigned int ao_readback[2]; /* Used for AO readback */
510 unsigned int ai_scan_count; /* Number of analogue input scans
512 unsigned int ai_scan_pos; /* Current position within analogue
514 unsigned int ao_scan_count; /* Number of analogue output scans
516 int intr_cpuid; /* ID of CPU running interrupt routine. */
517 unsigned short hwver; /* Hardware version (for '+' models). */
518 unsigned short adccon; /* ADCCON register value. */
519 unsigned short daccon; /* DACCON register value. */
520 unsigned short adcfifothresh; /* ADC FIFO programmable interrupt
521 * level threshold (PCI230+/260+). */
522 unsigned short adcg; /* ADCG register value. */
523 unsigned char int_en; /* Interrupt enables bits. */
524 unsigned char ai_continuous; /* Flag set when cmd->stop_src ==
525 * TRIG_NONE - user chooses to stop
526 * continuous conversion by
528 unsigned char ao_continuous; /* Flag set when cmd->stop_src ==
529 * TRIG_NONE - user chooses to stop
530 * continuous conversion by
532 unsigned char ai_bipolar; /* Set if bipolar input range so we
533 * know to mangle it. */
534 unsigned char ao_bipolar; /* Set if bipolar output range so we
535 * know to mangle it. */
536 unsigned char ier; /* Copy of interrupt enables/status register. */
537 unsigned char intr_running; /* Flag set in interrupt routine. */
538 unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */
541 /* PCI230 clock source periods in ns */
542 static const unsigned int pci230_timebase[8] = {
543 [CLK_10MHZ] = TIMEBASE_10MHZ,
544 [CLK_1MHZ] = TIMEBASE_1MHZ,
545 [CLK_100KHZ] = TIMEBASE_100KHZ,
546 [CLK_10KHZ] = TIMEBASE_10KHZ,
547 [CLK_1KHZ] = TIMEBASE_1KHZ,
550 /* PCI230 analogue input range table */
551 static const struct comedi_lrange pci230_ai_range = { 7, {
562 /* PCI230 analogue gain bits for each input range. */
563 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
565 /* PCI230 adccon bipolar flag for each analogue input range. */
566 static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
568 /* PCI230 analogue output range table */
569 static const struct comedi_lrange pci230_ao_range = { 2, {
575 /* PCI230 daccon bipolar flag for each analogue output range. */
576 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
578 static short pci230_ai_read(struct comedi_device *dev)
580 const struct pci230_board *thisboard = comedi_board(dev);
581 struct pci230_private *devpriv = dev->private;
585 data = (short)inw(dev->iobase + PCI230_ADCDATA);
586 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
587 * four bits reserved for expansion). */
588 /* PCI230+ is 16 bit AI. */
589 data = data >> (16 - thisboard->ai_bits);
591 /* If a bipolar range was specified, mangle it (twos
592 * complement->straight binary). */
593 if (devpriv->ai_bipolar)
594 data ^= 1 << (thisboard->ai_bits - 1);
599 static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
602 const struct pci230_board *thisboard = comedi_board(dev);
603 struct pci230_private *devpriv = dev->private;
605 /* If a bipolar range was specified, mangle it (straight binary->twos
607 if (devpriv->ao_bipolar)
608 datum ^= 1 << (thisboard->ao_bits - 1);
610 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
611 * four bits reserved for expansion). */
612 /* PCI230+ is also 12 bit AO. */
613 datum <<= (16 - thisboard->ao_bits);
614 return (unsigned short)datum;
617 static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
618 short datum, unsigned int chan)
620 struct pci230_private *devpriv = dev->private;
622 /* Store unmangled datum to be read back later. */
623 devpriv->ao_readback[chan] = datum;
625 /* Write mangled datum to appropriate DACOUT register. */
626 outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
632 static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
635 struct pci230_private *devpriv = dev->private;
637 /* Store unmangled datum to be read back later. */
638 devpriv->ao_readback[chan] = datum;
640 /* Write mangled datum to appropriate DACDATA register. */
641 outw(pci230_ao_mangle_datum(dev, datum),
642 dev->iobase + PCI230P2_DACDATA);
645 static int get_resources(struct comedi_device *dev, unsigned int res_mask,
648 struct pci230_private *devpriv = dev->private;
652 unsigned int claimed;
653 unsigned long irqflags;
657 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
658 for (b = 1, i = 0; (i < NUM_RESOURCES)
659 && (res_mask != 0); b <<= 1, i++) {
660 if ((res_mask & b) != 0) {
662 if (devpriv->res_owner[i] == OWNER_NONE) {
663 devpriv->res_owner[i] = owner;
665 } else if (devpriv->res_owner[i] != owner) {
666 for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
667 if ((claimed & b) != 0) {
668 devpriv->res_owner[i]
678 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
682 static inline int get_one_resource(struct comedi_device *dev,
683 unsigned int resource, unsigned char owner)
685 return get_resources(dev, (1U << resource), owner);
688 static void put_resources(struct comedi_device *dev, unsigned int res_mask,
691 struct pci230_private *devpriv = dev->private;
694 unsigned long irqflags;
696 spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
697 for (b = 1, i = 0; (i < NUM_RESOURCES)
698 && (res_mask != 0); b <<= 1, i++) {
699 if ((res_mask & b) != 0) {
701 if (devpriv->res_owner[i] == owner)
702 devpriv->res_owner[i] = OWNER_NONE;
706 spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
709 static inline void put_one_resource(struct comedi_device *dev,
710 unsigned int resource, unsigned char owner)
712 put_resources(dev, (1U << resource), owner);
715 static inline void put_all_resources(struct comedi_device *dev,
718 put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
721 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
722 unsigned int round_mode)
728 rem = do_div(div, timebase);
729 round_mode &= TRIG_ROUND_MASK;
730 switch (round_mode) {
732 case TRIG_ROUND_NEAREST:
733 div += (rem + (timebase / 2)) / timebase;
735 case TRIG_ROUND_DOWN:
738 div += (rem + timebase - 1) / timebase;
741 return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
744 /* Given desired period in ns, returns the required internal clock source
745 * and gets the initial count. */
746 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
747 unsigned int round_mode)
749 unsigned int clk_src, cnt;
751 for (clk_src = CLK_10MHZ;; clk_src++) {
752 cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
753 if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
761 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
764 unsigned int clk_src;
766 clk_src = pci230_choose_clk_count(*ns, &count, round);
767 *ns = count * pci230_timebase[clk_src];
771 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
772 unsigned int mode, uint64_t ns,
775 struct pci230_private *devpriv = dev->private;
776 unsigned int clk_src;
780 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
781 /* Determine clock source and count. */
782 clk_src = pci230_choose_clk_count(ns, &count, round);
783 /* Program clock source. */
784 outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
785 /* Set initial count. */
789 i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
792 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
794 struct pci230_private *devpriv = dev->private;
796 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
798 /* Counter ct, 8254 mode 1, initial count not written. */
802 * COMEDI_SUBD_AI instruction;
804 static int pci230_ai_rinsn(struct comedi_device *dev,
805 struct comedi_subdevice *s, struct comedi_insn *insn,
808 struct pci230_private *devpriv = dev->private;
810 unsigned int chan, range, aref;
811 unsigned int gainshift;
813 unsigned short adccon, adcen;
815 /* Unpack channel and range. */
816 chan = CR_CHAN(insn->chanspec);
817 range = CR_RANGE(insn->chanspec);
818 aref = CR_AREF(insn->chanspec);
819 if (aref == AREF_DIFF) {
821 if (chan >= s->n_chan / 2) {
822 DPRINTK("comedi%d: amplc_pci230: ai_rinsn: "
823 "differential channel number out of range "
824 "0 to %u\n", dev->minor, (s->n_chan / 2) - 1);
829 /* Use Z2-CT2 as a conversion trigger instead of the built-in
830 * software trigger, as otherwise triggering of differential channels
831 * doesn't work properly for some versions of PCI230/260. Also set
832 * FIFO mode because the ADC busy bit only works for software triggers.
834 adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
835 /* Set Z2-CT2 output low to avoid any false triggers. */
836 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
837 devpriv->ai_bipolar = pci230_ai_bipolar[range];
838 if (aref == AREF_DIFF) {
840 gainshift = chan * 2;
841 if (devpriv->hwver == 0) {
842 /* Original PCI230/260 expects both inputs of the
843 * differential channel to be enabled. */
844 adcen = 3 << gainshift;
846 /* PCI230+/260+ expects only one input of the
847 * differential channel to be enabled. */
848 adcen = 1 << gainshift;
850 adccon |= PCI230_ADC_IM_DIF;
854 gainshift = chan & ~1;
855 adccon |= PCI230_ADC_IM_SE;
857 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
858 | (pci230_ai_gain[range] << gainshift);
859 if (devpriv->ai_bipolar)
860 adccon |= PCI230_ADC_IR_BIP;
862 adccon |= PCI230_ADC_IR_UNI;
865 /* Enable only this channel in the scan list - otherwise by default
866 * we'll get one sample from each channel. */
867 outw(adcen, dev->iobase + PCI230_ADCEN);
869 /* Set gain for channel. */
870 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
872 /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
873 devpriv->adccon = adccon;
874 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
876 /* Convert n samples */
877 for (n = 0; n < insn->n; n++) {
878 /* Trigger conversion by toggling Z2-CT2 output (finish with
880 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
882 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
886 /* wait for conversion to end */
887 for (i = 0; i < TIMEOUT; i++) {
888 status = inw(dev->iobase + PCI230_ADCCON);
889 if (!(status & PCI230_ADC_FIFO_EMPTY))
894 dev_err(dev->class_dev, "timeout\n");
899 data[n] = pci230_ai_read(dev);
902 /* return the number of samples read/written */
907 * COMEDI_SUBD_AO instructions;
909 static int pci230_ao_winsn(struct comedi_device *dev,
910 struct comedi_subdevice *s, struct comedi_insn *insn,
913 struct pci230_private *devpriv = dev->private;
917 /* Unpack channel and range. */
918 chan = CR_CHAN(insn->chanspec);
919 range = CR_RANGE(insn->chanspec);
921 /* Set range - see analogue output range table; 0 => unipolar 10V,
922 * 1 => bipolar +/-10V range scale */
923 devpriv->ao_bipolar = pci230_ao_bipolar[range];
924 outw(range, dev->iobase + PCI230_DACCON);
926 /* Writing a list of values to an AO channel is probably not
927 * very useful, but that's how the interface is defined. */
928 for (i = 0; i < insn->n; i++) {
929 /* Write value to DAC and store it. */
930 pci230_ao_write_nofifo(dev, data[i], chan);
933 /* return the number of samples read/written */
937 /* AO subdevices should have a read insn as well as a write insn.
938 * Usually this means copying a value stored in devpriv. */
939 static int pci230_ao_rinsn(struct comedi_device *dev,
940 struct comedi_subdevice *s, struct comedi_insn *insn,
943 struct pci230_private *devpriv = dev->private;
945 int chan = CR_CHAN(insn->chanspec);
947 for (i = 0; i < insn->n; i++)
948 data[i] = devpriv->ao_readback[chan];
953 static int pci230_ao_cmdtest(struct comedi_device *dev,
954 struct comedi_subdevice *s, struct comedi_cmd *cmd)
956 const struct pci230_board *thisboard = comedi_board(dev);
957 struct pci230_private *devpriv = dev->private;
961 /* Step 1 : check if triggers are trivially valid */
963 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
965 tmp = TRIG_TIMER | TRIG_INT;
966 if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
968 * For PCI230+ hardware version 2 onwards, allow external
969 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
971 * FIXME: The permitted scan_begin_src values shouldn't depend
972 * on devpriv->hwver (the detected card's actual hardware
973 * version). They should only depend on thisboard->min_hwver
974 * (the static capabilities of the configured card). To fix
975 * it, a new card model, e.g. "pci230+2" would have to be
976 * defined with min_hwver set to 2. It doesn't seem worth it
977 * for this alone. At the moment, please consider
978 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
983 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
985 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
986 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
987 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
992 /* Step 2a : make sure trigger sources are unique */
994 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
995 err |= cfc_check_trigger_is_unique(cmd->stop_src);
997 /* Step 2b : and mutually compatible */
1002 /* Step 3: check if arguments are trivially valid */
1004 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1006 #define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */
1007 #define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */
1008 /*- Comedi limit due to unsigned int cmd. Driver limit
1009 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1010 * clock) = 65.536s */
1012 switch (cmd->scan_begin_src) {
1014 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1016 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
1020 /* External trigger - for PCI230+ hardware version 2 onwards. */
1021 /* Trigger number must be 0. */
1022 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1023 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1027 /* The only flags allowed are CR_EDGE and CR_INVERT. The
1028 * CR_EDGE flag is ignored. */
1029 if ((cmd->scan_begin_arg
1030 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1031 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1033 ~(CR_EDGE | CR_INVERT));
1038 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1042 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1044 if (cmd->stop_src == TRIG_NONE)
1045 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1050 /* Step 4: fix up any arguments.
1051 * "argument conflict" returned by comedilib to user mode process
1054 if (cmd->scan_begin_src == TRIG_TIMER) {
1055 tmp = cmd->scan_begin_arg;
1056 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1057 cmd->flags & TRIG_ROUND_MASK);
1058 if (tmp != cmd->scan_begin_arg)
1065 /* Step 5: check channel list if it exists. */
1067 if (cmd->chanlist && cmd->chanlist_len > 0) {
1070 range_err = (1 << 1)
1072 unsigned int errors;
1074 unsigned int chan, prev_chan;
1075 unsigned int range, first_range;
1077 prev_chan = CR_CHAN(cmd->chanlist[0]);
1078 first_range = CR_RANGE(cmd->chanlist[0]);
1080 for (n = 1; n < cmd->chanlist_len; n++) {
1081 chan = CR_CHAN(cmd->chanlist[n]);
1082 range = CR_RANGE(cmd->chanlist[n]);
1083 /* Channel numbers must strictly increase. */
1084 if (chan < prev_chan)
1087 /* Ranges must be the same. */
1088 if (range != first_range)
1089 errors |= range_err;
1095 if ((errors & seq_err) != 0) {
1096 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1097 "channel numbers must increase\n",
1100 if ((errors & range_err) != 0) {
1101 DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1102 "channels must have the same range\n",
1114 static void pci230_ao_stop(struct comedi_device *dev,
1115 struct comedi_subdevice *s)
1117 struct pci230_private *devpriv = dev->private;
1118 unsigned long irqflags;
1119 unsigned char intsrc;
1121 struct comedi_cmd *cmd;
1123 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1124 started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
1125 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1128 cmd = &s->async->cmd;
1129 if (cmd->scan_begin_src == TRIG_TIMER) {
1130 /* Stop scan rate generator. */
1131 pci230_cancel_ct(dev, 1);
1133 /* Determine interrupt source. */
1134 if (devpriv->hwver < 2) {
1135 /* Not using DAC FIFO. Using CT1 interrupt. */
1136 intsrc = PCI230_INT_ZCLK_CT1;
1138 /* Using DAC FIFO interrupt. */
1139 intsrc = PCI230P2_INT_DAC;
1141 /* Disable interrupt and wait for interrupt routine to finish running
1142 * unless we are called from the interrupt routine. */
1143 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1144 devpriv->int_en &= ~intsrc;
1145 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
1146 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1147 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1149 if (devpriv->ier != devpriv->int_en) {
1150 devpriv->ier = devpriv->int_en;
1151 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1153 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
1154 if (devpriv->hwver >= 2) {
1155 /* Using DAC FIFO. Reset FIFO, clear underrun error,
1157 devpriv->daccon &= PCI230_DAC_OR_MASK;
1158 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
1159 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
1160 dev->iobase + PCI230_DACCON);
1162 /* Release resources. */
1163 put_all_resources(dev, OWNER_AOCMD);
1166 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
1167 struct comedi_subdevice *s)
1169 struct pci230_private *devpriv = dev->private;
1172 struct comedi_async *async = s->async;
1173 struct comedi_cmd *cmd = &async->cmd;
1175 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
1177 for (i = 0; i < cmd->chanlist_len; i++) {
1178 /* Read sample from Comedi's circular buffer. */
1179 ret = comedi_buf_get(s->async, &data);
1181 s->async->events |= COMEDI_CB_OVERFLOW;
1182 pci230_ao_stop(dev, s);
1183 comedi_error(dev, "AO buffer underrun");
1186 /* Write value to DAC. */
1187 pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
1189 async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
1190 if (!devpriv->ao_continuous) {
1191 devpriv->ao_scan_count--;
1192 if (devpriv->ao_scan_count == 0) {
1193 /* End of acquisition. */
1194 async->events |= COMEDI_CB_EOA;
1195 pci230_ao_stop(dev, s);
1200 /* Loads DAC FIFO (if using it) from buffer. */
1201 /* Returns 0 if AO finished due to completion or error, 1 if still going. */
1202 static int pci230_handle_ao_fifo(struct comedi_device *dev,
1203 struct comedi_subdevice *s)
1205 struct pci230_private *devpriv = dev->private;
1206 struct comedi_async *async = s->async;
1207 struct comedi_cmd *cmd = &async->cmd;
1208 unsigned int num_scans;
1210 unsigned short dacstat;
1212 unsigned int bytes_per_scan;
1213 unsigned int events = 0;
1216 /* Get DAC FIFO status. */
1217 dacstat = inw(dev->iobase + PCI230_DACCON);
1218 /* Determine number of scans available in buffer. */
1219 bytes_per_scan = cmd->chanlist_len * sizeof(short);
1220 num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
1221 if (!devpriv->ao_continuous) {
1222 /* Fixed number of scans. */
1223 if (num_scans > devpriv->ao_scan_count)
1224 num_scans = devpriv->ao_scan_count;
1225 if (devpriv->ao_scan_count == 0) {
1226 /* End of acquisition. */
1227 events |= COMEDI_CB_EOA;
1231 /* Check for FIFO underrun. */
1232 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
1233 comedi_error(dev, "AO FIFO underrun");
1234 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1236 /* Check for buffer underrun if FIFO less than half full
1237 * (otherwise there will be loads of "DAC FIFO not half full"
1239 if ((num_scans == 0)
1240 && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
1241 comedi_error(dev, "AO buffer underrun");
1242 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1246 /* Determine how much room is in the FIFO (in samples). */
1247 if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
1248 room = PCI230P2_DAC_FIFOROOM_FULL;
1249 else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
1250 room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
1251 else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
1252 room = PCI230P2_DAC_FIFOROOM_EMPTY;
1254 room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
1255 /* Convert room to number of scans that can be added. */
1256 room /= cmd->chanlist_len;
1257 /* Determine number of scans to process. */
1258 if (num_scans > room)
1260 /* Process scans. */
1261 for (n = 0; n < num_scans; n++) {
1262 for (i = 0; i < cmd->chanlist_len; i++) {
1265 comedi_buf_get(async, &datum);
1266 pci230_ao_write_fifo(dev, datum,
1267 CR_CHAN(cmd->chanlist[i]));
1270 events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
1271 if (!devpriv->ao_continuous) {
1272 devpriv->ao_scan_count -= num_scans;
1273 if (devpriv->ao_scan_count == 0) {
1274 /* All data for the command has been written
1275 * to FIFO. Set FIFO interrupt trigger level
1277 devpriv->daccon = (devpriv->daccon
1279 ~PCI230P2_DAC_INT_FIFO_MASK)
1280 | PCI230P2_DAC_INT_FIFO_EMPTY;
1281 outw(devpriv->daccon,
1282 dev->iobase + PCI230_DACCON);
1285 /* Check if FIFO underrun occurred while writing to FIFO. */
1286 dacstat = inw(dev->iobase + PCI230_DACCON);
1287 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
1288 comedi_error(dev, "AO FIFO underrun");
1289 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
1292 if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
1294 /* Stopping AO due to completion or error. */
1295 pci230_ao_stop(dev, s);
1300 async->events |= events;
1304 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1305 struct comedi_subdevice *s,
1306 unsigned int trig_num)
1308 struct pci230_private *devpriv = dev->private;
1309 unsigned long irqflags;
1314 spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1315 if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
1317 if (devpriv->hwver < 2) {
1318 /* Not using DAC FIFO. */
1319 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1321 pci230_handle_ao_nofifo(dev, s);
1322 comedi_event(dev, s);
1324 /* Using DAC FIFO. */
1325 /* Read DACSWTRIG register to trigger conversion. */
1326 inw(dev->iobase + PCI230P2_DACSWTRIG);
1327 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1330 /* Delay. Should driver be responsible for this? */
1331 /* XXX TODO: See if DAC busy bit can be used. */
1334 spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
1340 static void pci230_ao_start(struct comedi_device *dev,
1341 struct comedi_subdevice *s)
1343 struct pci230_private *devpriv = dev->private;
1344 struct comedi_async *async = s->async;
1345 struct comedi_cmd *cmd = &async->cmd;
1346 unsigned long irqflags;
1348 set_bit(AO_CMD_STARTED, &devpriv->state);
1349 if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1350 /* An empty acquisition! */
1351 async->events |= COMEDI_CB_EOA;
1352 pci230_ao_stop(dev, s);
1353 comedi_event(dev, s);
1355 if (devpriv->hwver >= 2) {
1356 /* Using DAC FIFO. */
1357 unsigned short scantrig;
1360 /* Preload FIFO data. */
1361 run = pci230_handle_ao_fifo(dev, s);
1362 comedi_event(dev, s);
1367 /* Set scan trigger source. */
1368 switch (cmd->scan_begin_src) {
1370 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1373 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1374 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1376 scantrig = PCI230P2_DAC_TRIG_EXTP;
1379 scantrig = PCI230P2_DAC_TRIG_EXTN;
1383 scantrig = PCI230P2_DAC_TRIG_SW;
1386 /* Shouldn't get here. */
1387 scantrig = PCI230P2_DAC_TRIG_NONE;
1390 devpriv->daccon = (devpriv->daccon
1391 & ~PCI230P2_DAC_TRIG_MASK) |
1393 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1396 switch (cmd->scan_begin_src) {
1398 if (devpriv->hwver < 2) {
1399 /* Not using DAC FIFO. */
1400 /* Enable CT1 timer interrupt. */
1401 spin_lock_irqsave(&devpriv->isr_spinlock,
1403 devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1404 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1406 devpriv->iobase1 + PCI230_INT_SCE);
1407 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1410 /* Set CT1 gate high to start counting. */
1411 outb(GAT_CONFIG(1, GAT_VCC),
1412 devpriv->iobase1 + PCI230_ZGAT_SCE);
1415 async->inttrig = pci230_ao_inttrig_scan_begin;
1418 if (devpriv->hwver >= 2) {
1419 /* Using DAC FIFO. Enable DAC FIFO interrupt. */
1420 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1421 devpriv->int_en |= PCI230P2_INT_DAC;
1422 devpriv->ier |= PCI230P2_INT_DAC;
1423 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1424 spin_unlock_irqrestore(&devpriv->isr_spinlock,
1430 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1431 struct comedi_subdevice *s,
1432 unsigned int trig_num)
1437 s->async->inttrig = NULL;
1438 pci230_ao_start(dev, s);
1443 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1445 struct pci230_private *devpriv = dev->private;
1446 unsigned short daccon;
1449 /* Get the command. */
1450 struct comedi_cmd *cmd = &s->async->cmd;
1452 if (cmd->scan_begin_src == TRIG_TIMER) {
1454 if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
1459 /* Get number of scans required. */
1460 if (cmd->stop_src == TRIG_COUNT) {
1461 devpriv->ao_scan_count = cmd->stop_arg;
1462 devpriv->ao_continuous = 0;
1464 /* TRIG_NONE, user calls cancel. */
1465 devpriv->ao_scan_count = 0;
1466 devpriv->ao_continuous = 1;
1469 /* Set range - see analogue output range table; 0 => unipolar 10V,
1470 * 1 => bipolar +/-10V range scale */
1471 range = CR_RANGE(cmd->chanlist[0]);
1472 devpriv->ao_bipolar = pci230_ao_bipolar[range];
1473 daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1474 /* Use DAC FIFO for hardware version 2 onwards. */
1475 if (devpriv->hwver >= 2) {
1476 unsigned short dacen;
1480 for (i = 0; i < cmd->chanlist_len; i++)
1481 dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1483 /* Set channel scan list. */
1484 outw(dacen, dev->iobase + PCI230P2_DACEN);
1487 * Set DAC scan source to 'none'.
1488 * Set DAC FIFO interrupt trigger level to 'not half full'.
1489 * Reset DAC FIFO and clear underrun.
1491 * N.B. DAC FIFO interrupts are currently disabled.
1493 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1494 | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1495 | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1499 outw(daccon, dev->iobase + PCI230_DACCON);
1500 /* Preserve most of DACCON apart from write-only, transient bits. */
1501 devpriv->daccon = daccon
1502 & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1504 if (cmd->scan_begin_src == TRIG_TIMER) {
1505 /* Set the counter timer 1 to the specified scan frequency. */
1506 /* cmd->scan_begin_arg is sampling period in ns */
1507 /* gate it off for now. */
1508 outb(GAT_CONFIG(1, GAT_GND),
1509 devpriv->iobase1 + PCI230_ZGAT_SCE);
1510 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1511 cmd->scan_begin_arg,
1512 cmd->flags & TRIG_ROUND_MASK);
1515 /* N.B. cmd->start_src == TRIG_INT */
1516 s->async->inttrig = pci230_ao_inttrig_start;
1521 static int pci230_ao_cancel(struct comedi_device *dev,
1522 struct comedi_subdevice *s)
1524 pci230_ao_stop(dev, s);
1528 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1530 unsigned int min_scan_period, chanlist_len;
1533 chanlist_len = cmd->chanlist_len;
1534 if (cmd->chanlist_len == 0)
1537 min_scan_period = chanlist_len * cmd->convert_arg;
1538 if ((min_scan_period < chanlist_len)
1539 || (min_scan_period < cmd->convert_arg)) {
1540 /* Arithmetic overflow. */
1541 min_scan_period = UINT_MAX;
1544 if (cmd->scan_begin_arg < min_scan_period) {
1545 cmd->scan_begin_arg = min_scan_period;
1552 static int pci230_ai_cmdtest(struct comedi_device *dev,
1553 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1555 const struct pci230_board *thisboard = comedi_board(dev);
1556 struct pci230_private *devpriv = dev->private;
1560 /* Step 1 : check if triggers are trivially valid */
1562 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1564 tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1565 if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1567 * Unfortunately, we cannot trigger a scan off an external
1568 * source on the PCI260 board, since it uses the PPIC0 (DIO)
1569 * input, which isn't present on the PCI260. For PCI260+
1570 * we can use the EXTTRIG/EXTCONVCLK input on pin 17 instead.
1574 err |= cfc_check_trigger_src(&cmd->scan_begin_src, tmp);
1575 err |= cfc_check_trigger_src(&cmd->convert_src,
1576 TRIG_TIMER | TRIG_INT | TRIG_EXT);
1577 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1578 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1583 /* Step 2a : make sure trigger sources are unique */
1585 err |= cfc_check_trigger_is_unique(cmd->start_src);
1586 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1587 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1588 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1590 /* Step 2b : and mutually compatible */
1593 * If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1594 * set up to generate a fixed number of timed conversion pulses.
1596 if ((cmd->scan_begin_src != TRIG_FOLLOW)
1597 && (cmd->convert_src != TRIG_TIMER))
1603 /* Step 3: check if arguments are trivially valid */
1605 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1607 #define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */
1608 #define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */
1609 #define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */
1610 #define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */
1611 /*- Comedi limit due to unsigned int cmd. Driver limit
1612 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1613 * clock) = 65.536s */
1615 if (cmd->convert_src == TRIG_TIMER) {
1616 unsigned int max_speed_ai;
1618 if (devpriv->hwver == 0) {
1619 /* PCI230 or PCI260. Max speed depends whether
1620 * single-ended or pseudo-differential. */
1621 if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1622 /* Peek analogue reference of first channel. */
1623 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1624 max_speed_ai = MAX_SPEED_AI_DIFF;
1626 max_speed_ai = MAX_SPEED_AI_SE;
1629 /* No channel list. Assume single-ended. */
1630 max_speed_ai = MAX_SPEED_AI_SE;
1633 /* PCI230+ or PCI260+. */
1634 max_speed_ai = MAX_SPEED_AI_PLUS;
1637 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1639 err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
1641 } else if (cmd->convert_src == TRIG_EXT) {
1645 * convert_arg == (CR_EDGE | 0)
1646 * => trigger on +ve edge.
1647 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1648 * => trigger on -ve edge.
1650 if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1651 /* Trigger number must be 0. */
1652 if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1653 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1657 /* The only flags allowed are CR_INVERT and CR_EDGE.
1658 * CR_EDGE is required. */
1659 if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1661 /* Set CR_EDGE, preserve CR_INVERT. */
1662 cmd->convert_arg = COMBINE(cmd->start_arg,
1669 /* Backwards compatibility with previous versions. */
1670 /* convert_arg == 0 => trigger on -ve edge. */
1671 /* convert_arg == 1 => trigger on +ve edge. */
1672 err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1);
1675 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1678 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1680 if (cmd->stop_src == TRIG_NONE)
1681 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1683 if (cmd->scan_begin_src == TRIG_EXT) {
1684 /* external "trigger" to begin each scan
1685 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1686 * of CT2 (sample convert trigger is CT2) */
1687 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1688 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1692 /* The only flag allowed is CR_EDGE, which is ignored. */
1693 if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1694 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1695 CR_FLAGS_MASK & ~CR_EDGE);
1698 } else if (cmd->scan_begin_src == TRIG_TIMER) {
1699 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1700 if (!pci230_ai_check_scan_period(cmd))
1704 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1710 /* Step 4: fix up any arguments.
1711 * "argument conflict" returned by comedilib to user mode process
1714 if (cmd->convert_src == TRIG_TIMER) {
1715 tmp = cmd->convert_arg;
1716 pci230_ns_to_single_timer(&cmd->convert_arg,
1717 cmd->flags & TRIG_ROUND_MASK);
1718 if (tmp != cmd->convert_arg)
1722 if (cmd->scan_begin_src == TRIG_TIMER) {
1723 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1724 tmp = cmd->scan_begin_arg;
1725 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1726 cmd->flags & TRIG_ROUND_MASK);
1727 if (!pci230_ai_check_scan_period(cmd)) {
1728 /* Was below minimum required. Round up. */
1729 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1731 pci230_ai_check_scan_period(cmd);
1733 if (tmp != cmd->scan_begin_arg)
1740 /* Step 5: check channel list if it exists. */
1742 if (cmd->chanlist && cmd->chanlist_len > 0) {
1745 rangepair_err = 1 << 1,
1746 polarity_err = 1 << 2,
1748 diffchan_err = 1 << 4,
1749 buggy_chan0_err = 1 << 5
1751 unsigned int errors;
1752 unsigned int chan, prev_chan;
1753 unsigned int range, prev_range;
1754 unsigned int polarity, prev_polarity;
1755 unsigned int aref, prev_aref;
1756 unsigned int subseq_len;
1761 prev_chan = prev_aref = prev_range = prev_polarity = 0;
1762 for (n = 0; n < cmd->chanlist_len; n++) {
1763 chan = CR_CHAN(cmd->chanlist[n]);
1764 range = CR_RANGE(cmd->chanlist[n]);
1765 aref = CR_AREF(cmd->chanlist[n]);
1766 polarity = pci230_ai_bipolar[range];
1767 /* Only the first half of the channels are available if
1768 * differential. (These are remapped in software. In
1769 * hardware, only the even channels are available.) */
1770 if ((aref == AREF_DIFF)
1771 && (chan >= (s->n_chan / 2))) {
1772 errors |= diffchan_err;
1775 /* Channel numbers must strictly increase or
1776 * subsequence must repeat exactly. */
1777 if ((chan <= prev_chan)
1778 && (subseq_len == 0)) {
1781 if ((subseq_len > 0)
1782 && (cmd->chanlist[n] !=
1783 cmd->chanlist[n % subseq_len])) {
1786 /* Channels must have same AREF. */
1787 if (aref != prev_aref)
1790 /* Channel ranges must have same polarity. */
1791 if (polarity != prev_polarity)
1792 errors |= polarity_err;
1794 /* Single-ended channel pairs must have same
1796 if ((aref != AREF_DIFF)
1797 && (((chan ^ prev_chan) & ~1) == 0)
1798 && (range != prev_range)) {
1799 errors |= rangepair_err;
1805 prev_polarity = polarity;
1807 if (subseq_len == 0) {
1808 /* Subsequence is whole sequence. */
1811 /* If channel list is a repeating subsequence, need a whole
1812 * number of repeats. */
1813 if ((n % subseq_len) != 0)
1816 if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
1818 * Buggy PCI230+ or PCI260+ requires channel 0 to be
1819 * (first) in the sequence if the sequence contains
1820 * more than one channel. Hardware versions 1 and 2
1821 * have the bug. There is no hardware version 3.
1823 * Actually, there are two firmwares that report
1824 * themselves as hardware version 1 (the boards
1825 * have different ADC chips with slightly different
1826 * timing requirements, which was supposed to be
1827 * invisible to software). The first one doesn't
1828 * seem to have the bug, but the second one
1829 * does, and we can't tell them apart!
1831 if ((subseq_len > 1)
1832 && (CR_CHAN(cmd->chanlist[0]) != 0)) {
1833 errors |= buggy_chan0_err;
1838 if ((errors & seq_err) != 0) {
1839 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1840 "channel numbers must increase or "
1841 "sequence must repeat exactly\n",
1844 if ((errors & rangepair_err) != 0) {
1845 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1846 "single-ended channel pairs must "
1847 "have the same range\n", dev->minor);
1849 if ((errors & polarity_err) != 0) {
1850 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1851 "channel sequence ranges must be all "
1852 "bipolar or all unipolar\n",
1855 if ((errors & aref_err) != 0) {
1856 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1857 "channel sequence analogue references "
1858 "must be all the same (single-ended "
1859 "or differential)\n", dev->minor);
1861 if ((errors & diffchan_err) != 0) {
1862 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1863 "differential channel number out of "
1864 "range 0 to %u\n", dev->minor,
1865 (s->n_chan / 2) - 1);
1867 if ((errors & buggy_chan0_err) != 0) {
1868 dev_info(dev->class_dev,
1869 "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",
1881 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
1882 struct comedi_subdevice *s)
1884 struct pci230_private *devpriv = dev->private;
1885 struct comedi_cmd *cmd = &s->async->cmd;
1886 unsigned int scanlen = cmd->scan_end_arg;
1888 unsigned short triglev;
1889 unsigned short adccon;
1891 if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
1892 /* Wake at end of scan. */
1893 wake = scanlen - devpriv->ai_scan_pos;
1895 if (devpriv->ai_continuous
1896 || (devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL)
1897 || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
1898 wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
1900 wake = (devpriv->ai_scan_count * scanlen)
1901 - devpriv->ai_scan_pos;
1904 if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
1905 triglev = PCI230_ADC_INT_FIFO_HALF;
1907 if ((wake > 1) && (devpriv->hwver > 0)) {
1908 /* PCI230+/260+ programmable FIFO interrupt level. */
1909 if (devpriv->adcfifothresh != wake) {
1910 devpriv->adcfifothresh = wake;
1911 outw(wake, dev->iobase + PCI230P_ADCFFTH);
1913 triglev = PCI230P_ADC_INT_FIFO_THRESH;
1915 triglev = PCI230_ADC_INT_FIFO_NEMPTY;
1918 adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
1919 if (adccon != devpriv->adccon) {
1920 devpriv->adccon = adccon;
1921 outw(adccon, dev->iobase + PCI230_ADCCON);
1925 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
1926 struct comedi_subdevice *s,
1927 unsigned int trig_num)
1929 struct pci230_private *devpriv = dev->private;
1930 unsigned long irqflags;
1935 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1936 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1937 unsigned int delayus;
1939 /* Trigger conversion by toggling Z2-CT2 output. Finish
1940 * with output high. */
1941 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1943 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1945 /* Delay. Should driver be responsible for this? An
1946 * alternative would be to wait until conversion is complete,
1947 * but we can't tell when it's complete because the ADC busy
1948 * bit has a different meaning when FIFO enabled (and when
1949 * FIFO not enabled, it only works for software triggers). */
1950 if (((devpriv->adccon & PCI230_ADC_IM_MASK)
1951 == PCI230_ADC_IM_DIF)
1952 && (devpriv->hwver == 0)) {
1953 /* PCI230/260 in differential mode */
1956 /* single-ended or PCI230+/260+ */
1959 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1962 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1968 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
1969 struct comedi_subdevice *s,
1970 unsigned int trig_num)
1972 struct pci230_private *devpriv = dev->private;
1973 unsigned long irqflags;
1979 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
1980 if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
1981 /* Trigger scan by waggling CT0 gate source. */
1982 zgat = GAT_CONFIG(0, GAT_GND);
1983 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1984 zgat = GAT_CONFIG(0, GAT_VCC);
1985 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
1987 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
1992 static void pci230_ai_stop(struct comedi_device *dev,
1993 struct comedi_subdevice *s)
1995 struct pci230_private *devpriv = dev->private;
1996 unsigned long irqflags;
1997 struct comedi_cmd *cmd;
2000 spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2001 started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
2002 spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2005 cmd = &s->async->cmd;
2006 if (cmd->convert_src == TRIG_TIMER) {
2007 /* Stop conversion rate generator. */
2008 pci230_cancel_ct(dev, 2);
2010 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2011 /* Stop scan period monostable. */
2012 pci230_cancel_ct(dev, 0);
2014 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2015 /* Disable ADC interrupt and wait for interrupt routine to finish
2016 * running unless we are called from the interrupt routine. */
2017 devpriv->int_en &= ~PCI230_INT_ADC;
2018 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2019 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2020 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2022 if (devpriv->ier != devpriv->int_en) {
2023 devpriv->ier = devpriv->int_en;
2024 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2026 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2027 /* Reset FIFO, disable FIFO and set start conversion source to none.
2028 * Keep se/diff and bip/uni settings */
2029 devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
2030 | PCI230_ADC_IM_MASK)) |
2031 PCI230_ADC_TRIG_NONE;
2032 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2033 dev->iobase + PCI230_ADCCON);
2034 /* Release resources. */
2035 put_all_resources(dev, OWNER_AICMD);
2038 static void pci230_ai_start(struct comedi_device *dev,
2039 struct comedi_subdevice *s)
2041 struct pci230_private *devpriv = dev->private;
2042 unsigned long irqflags;
2043 unsigned short conv;
2044 struct comedi_async *async = s->async;
2045 struct comedi_cmd *cmd = &async->cmd;
2047 set_bit(AI_CMD_STARTED, &devpriv->state);
2048 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2049 /* An empty acquisition! */
2050 async->events |= COMEDI_CB_EOA;
2051 pci230_ai_stop(dev, s);
2052 comedi_event(dev, s);
2054 /* Enable ADC FIFO trigger level interrupt. */
2055 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2056 devpriv->int_en |= PCI230_INT_ADC;
2057 devpriv->ier |= PCI230_INT_ADC;
2058 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2059 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2061 /* Update conversion trigger source which is currently set
2062 * to CT2 output, which is currently stuck high. */
2063 switch (cmd->convert_src) {
2065 conv = PCI230_ADC_TRIG_NONE;
2068 /* Using CT2 output. */
2069 conv = PCI230_ADC_TRIG_Z2CT2;
2072 if ((cmd->convert_arg & CR_EDGE) != 0) {
2073 if ((cmd->convert_arg & CR_INVERT) == 0) {
2074 /* Trigger on +ve edge. */
2075 conv = PCI230_ADC_TRIG_EXTP;
2077 /* Trigger on -ve edge. */
2078 conv = PCI230_ADC_TRIG_EXTN;
2081 /* Backwards compatibility. */
2082 if (cmd->convert_arg != 0) {
2083 /* Trigger on +ve edge. */
2084 conv = PCI230_ADC_TRIG_EXTP;
2086 /* Trigger on -ve edge. */
2087 conv = PCI230_ADC_TRIG_EXTN;
2092 /* Use CT2 output for software trigger due to problems
2093 * in differential mode on PCI230/260. */
2094 conv = PCI230_ADC_TRIG_Z2CT2;
2097 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
2099 outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
2100 if (cmd->convert_src == TRIG_INT)
2101 async->inttrig = pci230_ai_inttrig_convert;
2103 /* Update FIFO interrupt trigger level, which is currently
2105 pci230_ai_update_fifo_trigger_level(dev, s);
2106 if (cmd->convert_src == TRIG_TIMER) {
2107 /* Update timer gates. */
2110 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2111 /* Conversion timer CT2 needs to be gated by
2112 * inverted output of monostable CT2. */
2113 zgat = GAT_CONFIG(2, GAT_NOUTNM2);
2115 /* Conversion timer CT2 needs to be gated on
2117 zgat = GAT_CONFIG(2, GAT_VCC);
2119 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2120 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2121 /* Set monostable CT0 trigger source. */
2122 switch (cmd->scan_begin_src) {
2124 zgat = GAT_CONFIG(0, GAT_VCC);
2128 * For CT0 on PCI230, the external
2129 * trigger (gate) signal comes from
2130 * PPC0, which is channel 16 of the DIO
2131 * subdevice. The application needs to
2132 * configure this as an input in order
2133 * to use it as an external scan
2136 zgat = GAT_CONFIG(0, GAT_EXT);
2140 * Monostable CT0 triggered by rising
2141 * edge on inverted output of CT1
2142 * (falling edge on CT1).
2144 zgat = GAT_CONFIG(0, GAT_NOUTNM2);
2148 * Monostable CT0 is triggered by
2149 * inttrig function waggling the CT0
2152 zgat = GAT_CONFIG(0, GAT_VCC);
2155 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2156 switch (cmd->scan_begin_src) {
2158 /* Scan period timer CT1 needs to be
2159 * gated on to start counting. */
2160 zgat = GAT_CONFIG(1, GAT_VCC);
2161 outb(zgat, devpriv->iobase1
2166 pci230_ai_inttrig_scan_begin;
2170 } else if (cmd->convert_src != TRIG_INT) {
2171 /* No longer need Z2-CT2. */
2172 put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
2177 static int pci230_ai_inttrig_start(struct comedi_device *dev,
2178 struct comedi_subdevice *s,
2179 unsigned int trig_num)
2184 s->async->inttrig = NULL;
2185 pci230_ai_start(dev, s);
2190 static void pci230_handle_ai(struct comedi_device *dev,
2191 struct comedi_subdevice *s)
2193 struct pci230_private *devpriv = dev->private;
2194 unsigned int events = 0;
2195 unsigned int status_fifo;
2198 unsigned int fifoamount;
2199 struct comedi_async *async = s->async;
2200 unsigned int scanlen = async->cmd.scan_end_arg;
2202 /* Determine number of samples to read. */
2203 if (devpriv->ai_continuous) {
2204 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2205 } else if (devpriv->ai_scan_count == 0) {
2207 } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2208 || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2209 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2211 todo = (devpriv->ai_scan_count * scanlen)
2212 - devpriv->ai_scan_pos;
2213 if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
2214 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2219 for (i = 0; i < todo; i++) {
2220 if (fifoamount == 0) {
2221 /* Read FIFO state. */
2222 status_fifo = inw(dev->iobase + PCI230_ADCCON);
2223 if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2224 /* Report error otherwise FIFO overruns will go
2225 * unnoticed by the caller. */
2226 comedi_error(dev, "AI FIFO overrun");
2227 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2229 } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2232 } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2233 /* FIFO half full. */
2234 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2236 /* FIFO not empty. */
2237 if (devpriv->hwver > 0) {
2238 /* Read PCI230+/260+ ADC FIFO level. */
2239 fifoamount = inw(dev->iobase
2240 + PCI230P_ADCFFLEV);
2241 if (fifoamount == 0) {
2242 /* Shouldn't happen. */
2250 /* Read sample and store in Comedi's circular buffer. */
2251 if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2252 events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2253 comedi_error(dev, "AI buffer overflow");
2257 devpriv->ai_scan_pos++;
2258 if (devpriv->ai_scan_pos == scanlen) {
2260 devpriv->ai_scan_pos = 0;
2261 devpriv->ai_scan_count--;
2262 async->events |= COMEDI_CB_EOS;
2265 if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2266 /* End of acquisition. */
2267 events |= COMEDI_CB_EOA;
2269 /* More samples required, tell Comedi to block. */
2270 events |= COMEDI_CB_BLOCK;
2272 async->events |= events;
2273 if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2274 COMEDI_CB_OVERFLOW)) != 0) {
2275 /* disable hardware conversions */
2276 pci230_ai_stop(dev, s);
2278 /* update FIFO interrupt trigger level */
2279 pci230_ai_update_fifo_trigger_level(dev, s);
2283 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2285 struct pci230_private *devpriv = dev->private;
2286 unsigned int i, chan, range, diff;
2287 unsigned int res_mask;
2288 unsigned short adccon, adcen;
2291 /* Get the command. */
2292 struct comedi_async *async = s->async;
2293 struct comedi_cmd *cmd = &async->cmd;
2296 * Determine which shared resources are needed.
2299 /* Need Z2-CT2 to supply a conversion trigger source at a high
2300 * logic level, even if not doing timed conversions. */
2301 res_mask |= (1U << RES_Z2CT2);
2302 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2303 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2304 res_mask |= (1U << RES_Z2CT0);
2305 if (cmd->scan_begin_src == TRIG_TIMER) {
2306 /* Using Z2-CT1 for scan frequency */
2307 res_mask |= (1U << RES_Z2CT1);
2310 /* Claim resources. */
2311 if (!get_resources(dev, res_mask, OWNER_AICMD))
2315 /* Get number of scans required. */
2316 if (cmd->stop_src == TRIG_COUNT) {
2317 devpriv->ai_scan_count = cmd->stop_arg;
2318 devpriv->ai_continuous = 0;
2320 /* TRIG_NONE, user calls cancel. */
2321 devpriv->ai_scan_count = 0;
2322 devpriv->ai_continuous = 1;
2324 devpriv->ai_scan_pos = 0; /* Position within scan. */
2327 * - Set channel scan list.
2328 * - Set channel gains.
2329 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2330 * start conversion source to point to something at a high logic
2331 * level (we use the output of counter/timer 2 for this purpose.
2332 * - PAUSE to allow things to settle down.
2333 * - Reset the FIFO again because it needs resetting twice and there
2334 * may have been a false conversion trigger on some versions of
2335 * PCI230/260 due to the start conversion source being set to a
2337 * - Enable ADC FIFO level interrupt.
2338 * - Set actual conversion trigger source and FIFO interrupt trigger
2340 * - If convert_src is TRIG_TIMER, set up the timers.
2343 adccon = PCI230_ADC_FIFO_EN;
2346 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2347 /* Differential - all channels must be differential. */
2349 adccon |= PCI230_ADC_IM_DIF;
2351 /* Single ended - all channels must be single-ended. */
2353 adccon |= PCI230_ADC_IM_SE;
2356 range = CR_RANGE(cmd->chanlist[0]);
2357 devpriv->ai_bipolar = pci230_ai_bipolar[range];
2358 if (devpriv->ai_bipolar)
2359 adccon |= PCI230_ADC_IR_BIP;
2361 adccon |= PCI230_ADC_IR_UNI;
2363 for (i = 0; i < cmd->chanlist_len; i++) {
2364 unsigned int gainshift;
2366 chan = CR_CHAN(cmd->chanlist[i]);
2367 range = CR_RANGE(cmd->chanlist[i]);
2369 gainshift = 2 * chan;
2370 if (devpriv->hwver == 0) {
2371 /* Original PCI230/260 expects both inputs of
2372 * the differential channel to be enabled. */
2373 adcen |= 3 << gainshift;
2375 /* PCI230+/260+ expects only one input of the
2376 * differential channel to be enabled. */
2377 adcen |= 1 << gainshift;
2380 gainshift = (chan & ~1);
2383 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2384 | (pci230_ai_gain[range] << gainshift);
2387 /* Set channel scan list. */
2388 outw(adcen, dev->iobase + PCI230_ADCEN);
2390 /* Set channel gains. */
2391 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2393 /* Set counter/timer 2 output high for use as the initial start
2394 * conversion source. */
2395 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2397 /* Temporarily use CT2 output as conversion trigger source and
2398 * temporarily set FIFO interrupt trigger level to 'full'. */
2399 adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2401 /* Enable and reset FIFO, specify FIFO trigger level full, specify
2402 * uni/bip, se/diff, and temporarily set the start conversion source
2403 * to CT2 output. Note that CT2 output is currently high, and this
2404 * will produce a false conversion trigger on some versions of the
2405 * PCI230/260, but that will be dealt with later. */
2406 devpriv->adccon = adccon;
2407 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2410 /* Failure to include this will result in the first few channels'-worth
2411 * of data being corrupt, normally manifesting itself by large negative
2412 * voltages. It seems the board needs time to settle between the first
2413 * FIFO reset (above) and the second FIFO reset (below). Setting the
2414 * channel gains and scan list _before_ the first FIFO reset also
2415 * helps, though only slightly. */
2418 /* Reset FIFO again. */
2419 outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2421 if (cmd->convert_src == TRIG_TIMER) {
2422 /* Set up CT2 as conversion timer, but gate it off for now.
2423 * Note, counter/timer output 2 can be monitored on the
2424 * connector: PCI230 pin 21, PCI260 pin 18. */
2425 zgat = GAT_CONFIG(2, GAT_GND);
2426 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2427 /* Set counter/timer 2 to the specified conversion period. */
2428 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2429 cmd->flags & TRIG_ROUND_MASK);
2430 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2432 * Set up monostable on CT0 output for scan timing. A
2433 * rising edge on the trigger (gate) input of CT0 will
2434 * trigger the monostable, causing its output to go low
2435 * for the configured period. The period depends on
2436 * the conversion period and the number of conversions
2439 * Set the trigger high before setting up the
2440 * monostable to stop it triggering. The trigger
2441 * source will be changed later.
2443 zgat = GAT_CONFIG(0, GAT_VCC);
2444 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2445 pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2446 ((uint64_t) cmd->convert_arg
2447 * cmd->scan_end_arg),
2449 if (cmd->scan_begin_src == TRIG_TIMER) {
2451 * Monostable on CT0 will be triggered by
2452 * output of CT1 at configured scan frequency.
2454 * Set up CT1 but gate it off for now.
2456 zgat = GAT_CONFIG(1, GAT_GND);
2457 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2458 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2459 cmd->scan_begin_arg,
2467 if (cmd->start_src == TRIG_INT) {
2468 s->async->inttrig = pci230_ai_inttrig_start;
2471 pci230_ai_start(dev, s);
2477 static int pci230_ai_cancel(struct comedi_device *dev,
2478 struct comedi_subdevice *s)
2480 pci230_ai_stop(dev, s);
2484 /* Interrupt handler */
2485 static irqreturn_t pci230_interrupt(int irq, void *d)
2487 unsigned char status_int, valid_status_int;
2488 struct comedi_device *dev = (struct comedi_device *)d;
2489 struct pci230_private *devpriv = dev->private;
2490 struct comedi_subdevice *s;
2491 unsigned long irqflags;
2493 /* Read interrupt status/enable register. */
2494 status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2496 if (status_int == PCI230_INT_DISABLE)
2500 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2501 valid_status_int = devpriv->int_en & status_int;
2502 /* Disable triggered interrupts.
2503 * (Only those interrupts that need re-enabling, are, later in the
2505 devpriv->ier = devpriv->int_en & ~status_int;
2506 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2507 devpriv->intr_running = 1;
2508 devpriv->intr_cpuid = THISCPU;
2509 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2512 * Check the source of interrupt and handle it.
2513 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2514 * interrupts. However, at present (Comedi-0.7.60) does not allow
2515 * concurrent execution of commands, instructions or a mixture of the
2519 if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2520 s = dev->write_subdev;
2521 pci230_handle_ao_nofifo(dev, s);
2522 comedi_event(dev, s);
2525 if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2526 s = dev->write_subdev;
2527 pci230_handle_ao_fifo(dev, s);
2528 comedi_event(dev, s);
2531 if ((valid_status_int & PCI230_INT_ADC) != 0) {
2532 s = dev->read_subdev;
2533 pci230_handle_ai(dev, s);
2534 comedi_event(dev, s);
2537 /* Reenable interrupts. */
2538 spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2539 if (devpriv->ier != devpriv->int_en) {
2540 devpriv->ier = devpriv->int_en;
2541 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2543 devpriv->intr_running = 0;
2544 spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2549 /* Check if PCI device matches a specific board. */
2550 static bool pci230_match_pci_board(const struct pci230_board *board,
2551 struct pci_dev *pci_dev)
2553 /* assume pci_dev->device != PCI_DEVICE_ID_INVALID */
2554 if (board->id != pci_dev->device)
2556 if (board->min_hwver == 0)
2558 /* Looking for a '+' model. First check length of registers. */
2559 if (pci_resource_len(pci_dev, 3) < 32)
2560 return false; /* Not a '+' model. */
2561 /* TODO: temporarily enable PCI device and read the hardware version
2562 * register. For now, assume it's okay. */
2566 /* Look for board matching PCI device. */
2567 static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev)
2571 for (i = 0; i < ARRAY_SIZE(pci230_boards); i++)
2572 if (pci230_match_pci_board(&pci230_boards[i], pci_dev))
2573 return &pci230_boards[i];
2577 /* Look for PCI device matching requested board name, bus and slot. */
2578 static struct pci_dev *pci230_find_pci_dev(struct comedi_device *dev,
2579 struct comedi_devconfig *it)
2581 const struct pci230_board *thisboard = comedi_board(dev);
2582 struct pci_dev *pci_dev = NULL;
2583 int bus = it->options[0];
2584 int slot = it->options[1];
2586 for_each_pci_dev(pci_dev) {
2587 /* Check vendor ID (same for all supported PCI boards). */
2588 if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
2590 /* If bus/slot specified, check them. */
2591 if ((bus || slot) &&
2592 (bus != pci_dev->bus->number ||
2593 slot != PCI_SLOT(pci_dev->devfn)))
2595 if (thisboard->id == PCI_DEVICE_ID_INVALID) {
2596 /* Wildcard board matches any supported PCI board. */
2597 const struct pci230_board *foundboard;
2599 foundboard = pci230_find_pci_board(pci_dev);
2600 if (foundboard == NULL)
2602 /* Replace wildcard board_ptr. */
2603 dev->board_ptr = foundboard;
2605 /* Need to match a specific board. */
2606 if (!pci230_match_pci_board(thisboard, pci_dev))
2611 dev_err(dev->class_dev,
2612 "No supported board found! (req. bus %d, slot %d)\n",
2617 static int pci230_alloc_private(struct comedi_device *dev)
2619 struct pci230_private *devpriv;
2621 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
2624 dev->private = devpriv;
2626 spin_lock_init(&devpriv->isr_spinlock);
2627 spin_lock_init(&devpriv->res_spinlock);
2628 spin_lock_init(&devpriv->ai_stop_spinlock);
2629 spin_lock_init(&devpriv->ao_stop_spinlock);
2633 /* Common part of attach and auto_attach. */
2634 static int pci230_attach_common(struct comedi_device *dev,
2635 struct pci_dev *pci_dev)
2637 const struct pci230_board *thisboard = comedi_board(dev);
2638 struct pci230_private *devpriv = dev->private;
2639 struct comedi_subdevice *s;
2640 unsigned long iobase1, iobase2;
2641 /* PCI230's I/O spaces 1 and 2 respectively. */
2644 comedi_set_hw_dev(dev, &pci_dev->dev);
2646 dev->board_name = thisboard->name;
2647 /* Enable PCI device and reserve I/O spaces. */
2648 if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) {
2649 dev_err(dev->class_dev,
2650 "failed to enable PCI device and request regions\n");
2653 /* Read base addresses of the PCI230's two I/O regions from PCI
2654 * configuration register. */
2655 iobase1 = pci_resource_start(pci_dev, 2);
2656 iobase2 = pci_resource_start(pci_dev, 3);
2657 dev_dbg(dev->class_dev,
2658 "%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
2659 dev->board_name, iobase1, iobase2);
2660 devpriv->iobase1 = iobase1;
2661 dev->iobase = iobase2;
2662 /* Read bits of DACCON register - only the output range. */
2663 devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
2664 /* Read hardware version register and set extended function register
2666 if (pci_resource_len(pci_dev, 3) >= 32) {
2667 unsigned short extfunc = 0;
2669 devpriv->hwver = inw(dev->iobase + PCI230P_HWVER);
2670 if (devpriv->hwver < thisboard->min_hwver) {
2671 dev_err(dev->class_dev,
2672 "%s - bad hardware version - got %u, need %u\n",
2673 dev->board_name, devpriv->hwver,
2674 thisboard->min_hwver);
2677 if (devpriv->hwver > 0) {
2678 if (!thisboard->have_dio) {
2679 /* No DIO ports. Route counters' external gates
2680 * to the EXTTRIG signal (PCI260+ pin 17).
2681 * (Otherwise, they would be routed to DIO
2682 * inputs PC0, PC1 and PC2 which don't exist
2684 extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
2686 if ((thisboard->ao_chans > 0)
2687 && (devpriv->hwver >= 2)) {
2688 /* Enable DAC FIFO functionality. */
2689 extfunc |= PCI230P2_EXTFUNC_DACFIFO;
2692 outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
2693 if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) {
2694 /* Temporarily enable DAC FIFO, reset it and disable
2695 * FIFO wraparound. */
2696 outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN
2697 | PCI230P2_DAC_FIFO_RESET,
2698 dev->iobase + PCI230_DACCON);
2699 /* Clear DAC FIFO channel enable register. */
2700 outw(0, dev->iobase + PCI230P2_DACEN);
2701 /* Disable DAC FIFO. */
2702 outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
2705 /* Disable board's interrupts. */
2706 outb(0, devpriv->iobase1 + PCI230_INT_SCE);
2707 /* Set ADC to a reasonable state. */
2709 devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE
2710 | PCI230_ADC_IR_BIP;
2711 outw(1 << 0, dev->iobase + PCI230_ADCEN);
2712 outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2713 outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2714 dev->iobase + PCI230_ADCCON);
2715 /* Register the interrupt handler. */
2716 irq_hdl = request_irq(pci_dev->irq, pci230_interrupt,
2717 IRQF_SHARED, "amplc_pci230", dev);
2719 dev_warn(dev->class_dev,
2720 "unable to register irq %u, commands will not be available\n",
2723 dev->irq = pci_dev->irq;
2724 dev_dbg(dev->class_dev, "registered irq %u\n", pci_dev->irq);
2727 rc = comedi_alloc_subdevices(dev, 3);
2731 s = &dev->subdevices[0];
2732 /* analog input subdevice */
2733 s->type = COMEDI_SUBD_AI;
2734 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
2735 s->n_chan = thisboard->ai_chans;
2736 s->maxdata = (1 << thisboard->ai_bits) - 1;
2737 s->range_table = &pci230_ai_range;
2738 s->insn_read = &pci230_ai_rinsn;
2739 s->len_chanlist = 256; /* but there are restrictions. */
2740 /* Only register commands if the interrupt handler is installed. */
2742 dev->read_subdev = s;
2743 s->subdev_flags |= SDF_CMD_READ;
2744 s->do_cmd = &pci230_ai_cmd;
2745 s->do_cmdtest = &pci230_ai_cmdtest;
2746 s->cancel = pci230_ai_cancel;
2748 s = &dev->subdevices[1];
2749 /* analog output subdevice */
2750 if (thisboard->ao_chans > 0) {
2751 s->type = COMEDI_SUBD_AO;
2752 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
2753 s->n_chan = thisboard->ao_chans;
2754 s->maxdata = (1 << thisboard->ao_bits) - 1;
2755 s->range_table = &pci230_ao_range;
2756 s->insn_write = &pci230_ao_winsn;
2757 s->insn_read = &pci230_ao_rinsn;
2758 s->len_chanlist = thisboard->ao_chans;
2759 /* Only register commands if the interrupt handler is
2762 dev->write_subdev = s;
2763 s->subdev_flags |= SDF_CMD_WRITE;
2764 s->do_cmd = &pci230_ao_cmd;
2765 s->do_cmdtest = &pci230_ao_cmdtest;
2766 s->cancel = pci230_ao_cancel;
2769 s->type = COMEDI_SUBD_UNUSED;
2771 s = &dev->subdevices[2];
2772 /* digital i/o subdevice */
2773 if (thisboard->have_dio) {
2774 rc = subdev_8255_init(dev, s, NULL,
2775 (devpriv->iobase1 + PCI230_PPI_X_BASE));
2779 s->type = COMEDI_SUBD_UNUSED;
2781 dev_info(dev->class_dev, "attached\n");
2785 static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2787 const struct pci230_board *thisboard = comedi_board(dev);
2788 struct pci_dev *pci_dev;
2791 dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n",
2792 thisboard->name, it->options[0], it->options[1]);
2794 rc = pci230_alloc_private(dev);
2798 pci_dev = pci230_find_pci_dev(dev, it);
2801 return pci230_attach_common(dev, pci_dev);
2804 static int pci230_auto_attach(struct comedi_device *dev,
2805 unsigned long context_unused)
2807 struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
2810 dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
2813 rc = pci230_alloc_private(dev);
2817 dev->board_ptr = pci230_find_pci_board(pci_dev);
2818 if (dev->board_ptr == NULL) {
2819 dev_err(dev->class_dev,
2820 "amplc_pci230: BUG! cannot determine board type!\n");
2824 * Need to 'get' the PCI device to match the 'put' in pci230_detach().
2825 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
2826 * support for manual attachment of PCI devices via pci230_attach()
2829 pci_dev_get(pci_dev);
2830 return pci230_attach_common(dev, pci_dev);
2833 static void pci230_detach(struct comedi_device *dev)
2835 const struct pci230_board *thisboard = comedi_board(dev);
2836 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2838 if (dev->subdevices && thisboard->have_dio)
2839 subdev_8255_cleanup(dev, &dev->subdevices[2]);
2841 free_irq(dev->irq, dev);
2844 comedi_pci_disable(pcidev);
2845 pci_dev_put(pcidev);
2849 static struct comedi_driver amplc_pci230_driver = {
2850 .driver_name = "amplc_pci230",
2851 .module = THIS_MODULE,
2852 .attach = pci230_attach,
2853 .auto_attach = pci230_auto_attach,
2854 .detach = pci230_detach,
2855 .board_name = &pci230_boards[0].name,
2856 .offset = sizeof(pci230_boards[0]),
2857 .num_names = ARRAY_SIZE(pci230_boards),
2860 static int amplc_pci230_pci_probe(struct pci_dev *dev,
2861 const struct pci_device_id *ent)
2863 return comedi_pci_auto_config(dev, &lc_pci230_driver);
2866 static void amplc_pci230_pci_remove(struct pci_dev *dev)
2868 comedi_pci_auto_unconfig(dev);
2871 static DEFINE_PCI_DEVICE_TABLE(amplc_pci230_pci_table) = {
2872 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
2873 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
2876 MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table);
2878 static struct pci_driver amplc_pci230_pci_driver = {
2879 .name = "amplc_pci230",
2880 .id_table = amplc_pci230_pci_table,
2881 .probe = amplc_pci230_pci_probe,
2882 .remove = amplc_pci230_pci_remove
2884 module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
2886 MODULE_AUTHOR("Comedi http://www.comedi.org");
2887 MODULE_DESCRIPTION("Comedi low-level driver");
2888 MODULE_LICENSE("GPL");