1  /*
2     comedi/drivers/amplc_pci230.c
3     Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
4 
5     Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
6 
7     COMEDI - Linux Control and Measurement Device Interface
8     Copyright (C) 2000 David A. Schleef <ds@schleef.org>
9 
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.
14 
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.
19 
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.
23   */
24 /*
25 Driver: amplc_pci230
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)
34 Status: works
35 
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
40           will be used.
41 
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.
48 
49 Subdevices:
50 
51                 PCI230(+)    PCI260(+)
52                 ---------    ---------
53   Subdevices       3            1
54         0          AI           AI
55 	1          AO
56 	2          DIO
57 
58 AI Subdevice:
59 
60   The AI subdevice has 16 single-ended channels or 8 differential
61   channels.
62 
63   The PCI230 and PCI260 cards have 12-bit resolution.  The PCI230+ and
64   PCI260+ cards have 16-bit resolution.
65 
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.
76 
77   The following input ranges are supported:
78 
79     0 => [-10, +10] V
80     1 => [-5, +5] V
81     2 => [-2.5, +2.5] V
82     3 => [-1.25, +1.25] V
83     4 => [0, 10] V
84     5 => [0, 5] V
85     6 => [0, 2.5] V
86 
87 AI Commands:
88 
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|
94   |         |              |TRIG_INT   |            |          |
95   |         |--------------|-----------|            |          |
96   |         | TRIG_TIMER(1)|TRIG_TIMER |            |          |
97   |         | TRIG_EXT(2)  |           |            |          |
98   |         | TRIG_INT     |           |            |          |
99   +---------+--------------+-----------+------------+----------+
100 
101   Note 1: If AI command and AO command are used simultaneously, only
102           one may have scan_begin_src == TRIG_TIMER.
103 
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
109           on the input.
110 
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:
114 
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)
119 
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.
134 
135 AO Subdevice:
136 
137   The AO subdevice has 2 channels with 12-bit resolution.
138 
139   The following output ranges are supported:
140 
141     0 => [0, 10] V
142     1 => [-10, +10] V
143 
144 AO Commands:
145 
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|
151   |         | TRIG_INT     |           |            |          |
152   +---------+--------------+-----------+------------+----------+
153 
154   Note 1: If AI command and AO command are used simultaneously, only
155           one may have scan_begin_src == TRIG_TIMER.
156 
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.
164 
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
167   output range.
168 
169 DIO Subdevice:
170 
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:
173 
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
178 
179   Only mode 0 of the 8255 chip is supported.
180 
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.
184 */
185 /*
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.
189 */
190 
191 #include "../comedidev.h"
192 
193 #include <linux/delay.h>
194 #include <linux/interrupt.h>
195 
196 #include "comedi_pci.h"
197 #include "8253.h"
198 #include "8255.h"
199 
200 /* PCI230 PCI configuration register information */
201 #define PCI_VENDOR_ID_AMPLICON 0x14dc
202 #define PCI_DEVICE_ID_PCI230 0x0000
203 #define PCI_DEVICE_ID_PCI260 0x0006
204 #define PCI_DEVICE_ID_INVALID 0xffff
205 
206 #define PCI230_IO1_SIZE 32	/* Size of I/O space 1 */
207 #define PCI230_IO2_SIZE 16	/* Size of I/O space 2 */
208 
209 /* PCI230 i/o space 1 registers. */
210 #define PCI230_PPI_X_BASE	0x00	/* User PPI (82C55) base */
211 #define PCI230_PPI_X_A		0x00	/* User PPI (82C55) port A */
212 #define PCI230_PPI_X_B		0x01	/* User PPI (82C55) port B */
213 #define PCI230_PPI_X_C		0x02	/* User PPI (82C55) port C */
214 #define PCI230_PPI_X_CMD	0x03	/* User PPI (82C55) control word */
215 #define PCI230_Z2_CT_BASE	0x14	/* 82C54 counter/timer base */
216 #define PCI230_Z2_CT0		0x14	/* 82C54 counter/timer 0 */
217 #define PCI230_Z2_CT1		0x15	/* 82C54 counter/timer 1 */
218 #define PCI230_Z2_CT2		0x16	/* 82C54 counter/timer 2 */
219 #define PCI230_Z2_CTC		0x17	/* 82C54 counter/timer control word */
220 #define PCI230_ZCLK_SCE		0x1A	/* Group Z Clock Configuration */
221 #define PCI230_ZGAT_SCE		0x1D	/* Group Z Gate Configuration */
222 #define PCI230_INT_SCE		0x1E	/* Interrupt source mask (w) */
223 #define PCI230_INT_STAT		0x1E	/* Interrupt status (r) */
224 
225 /* PCI230 i/o space 2 registers. */
226 #define PCI230_DACCON		0x00	/* DAC control */
227 #define PCI230_DACOUT1		0x02	/* DAC channel 0 (w) */
228 #define PCI230_DACOUT2		0x04	/* DAC channel 1 (w) (not FIFO mode) */
229 #define PCI230_ADCDATA		0x08	/* ADC data (r) */
230 #define PCI230_ADCSWTRIG	0x08	/* ADC software trigger (w) */
231 #define PCI230_ADCCON		0x0A	/* ADC control */
232 #define PCI230_ADCEN		0x0C	/* ADC channel enable bits */
233 #define PCI230_ADCG		0x0E	/* ADC gain control bits */
234 /* PCI230+ i/o space 2 additional registers. */
235 #define PCI230P_ADCTRIG		0x10	/* ADC start acquisition trigger */
236 #define PCI230P_ADCTH		0x12	/* ADC analog trigger threshold */
237 #define PCI230P_ADCFFTH		0x14	/* ADC FIFO interrupt threshold */
238 #define PCI230P_ADCFFLEV	0x16	/* ADC FIFO level (r) */
239 #define PCI230P_ADCPTSC		0x18	/* ADC pre-trigger sample count (r) */
240 #define PCI230P_ADCHYST		0x1A	/* ADC analog trigger hysteresys */
241 #define PCI230P_EXTFUNC		0x1C	/* Extended functions */
242 #define PCI230P_HWVER		0x1E	/* Hardware version (r) */
243 /* PCI230+ hardware version 2 onwards. */
244 #define PCI230P2_DACDATA	0x02	/* DAC data (FIFO mode) (w) */
245 #define PCI230P2_DACSWTRIG	0x02	/* DAC soft trigger (FIFO mode) (r) */
246 #define PCI230P2_DACEN		0x06	/* DAC channel enable (FIFO mode) */
247 
248 /* Convertor related constants. */
249 #define PCI230_DAC_SETTLE 5	/* Analogue output settling time in µs */
250 				/* (DAC itself is 1µs nominally). */
251 #define PCI230_ADC_SETTLE 1	/* Analogue input settling time in µs */
252 				/* (ADC itself is 1.6µs nominally but we poll
253 				 * anyway). */
254 #define PCI230_MUX_SETTLE 10	/* ADC MUX settling time in µS */
255 				/* - 10µs for se, 20µs de. */
256 
257 /* DACCON read-write values. */
258 #define PCI230_DAC_OR_UNI		(0<<0)	/* Output range unipolar */
259 #define PCI230_DAC_OR_BIP		(1<<0)	/* Output range bipolar */
260 #define PCI230_DAC_OR_MASK		(1<<0)
261 /* The following applies only if DAC FIFO support is enabled in the EXTFUNC
262  * register (and only for PCI230+ hardware version 2 onwards). */
263 #define PCI230P2_DAC_FIFO_EN		(1<<8)	/* FIFO enable */
264 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
265  * hardware version 2 onwards). */
266 #define PCI230P2_DAC_TRIG_NONE		(0<<2)	/* No trigger */
267 #define PCI230P2_DAC_TRIG_SW		(1<<2)	/* Software trigger trigger */
268 #define PCI230P2_DAC_TRIG_EXTP		(2<<2)	/* EXTTRIG +ve edge trigger */
269 #define PCI230P2_DAC_TRIG_EXTN		(3<<2)	/* EXTTRIG -ve edge trigger */
270 #define PCI230P2_DAC_TRIG_Z2CT0		(4<<2)	/* CT0-OUT +ve edge trigger */
271 #define PCI230P2_DAC_TRIG_Z2CT1		(5<<2)	/* CT1-OUT +ve edge trigger */
272 #define PCI230P2_DAC_TRIG_Z2CT2		(6<<2)	/* CT2-OUT +ve edge trigger */
273 #define PCI230P2_DAC_TRIG_MASK		(7<<2)
274 #define PCI230P2_DAC_FIFO_WRAP		(1<<7)	/* FIFO wraparound mode */
275 #define PCI230P2_DAC_INT_FIFO_EMPTY	(0<<9)	/* FIFO interrupt empty */
276 #define PCI230P2_DAC_INT_FIFO_NEMPTY	(1<<9)
277 #define PCI230P2_DAC_INT_FIFO_NHALF	(2<<9)	/* FIFO intr not half full */
278 #define PCI230P2_DAC_INT_FIFO_HALF	(3<<9)
279 #define PCI230P2_DAC_INT_FIFO_NFULL	(4<<9)	/* FIFO interrupt not full */
280 #define PCI230P2_DAC_INT_FIFO_FULL	(5<<9)
281 #define PCI230P2_DAC_INT_FIFO_MASK	(7<<9)
282 
283 /* DACCON read-only values. */
284 #define PCI230_DAC_BUSY			(1<<1)	/* DAC busy. */
285 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
286  * hardware version 2 onwards). */
287 #define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED	(1<<5)	/* Underrun error */
288 #define PCI230P2_DAC_FIFO_EMPTY		(1<<13)	/* FIFO empty */
289 #define PCI230P2_DAC_FIFO_FULL		(1<<14)	/* FIFO full */
290 #define PCI230P2_DAC_FIFO_HALF		(1<<15)	/* FIFO half full */
291 
292 /* DACCON write-only, transient values. */
293 /* The following apply only if the DAC FIFO is enabled (and only for PCI230+
294  * hardware version 2 onwards). */
295 #define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR	(1<<5)	/* Clear underrun */
296 #define PCI230P2_DAC_FIFO_RESET		(1<<12)	/* FIFO reset */
297 
298 /* PCI230+ hardware version 2 DAC FIFO levels. */
299 #define PCI230P2_DAC_FIFOLEVEL_HALF	512
300 #define PCI230P2_DAC_FIFOLEVEL_FULL	1024
301 /* Free space in DAC FIFO. */
302 #define PCI230P2_DAC_FIFOROOM_EMPTY		PCI230P2_DAC_FIFOLEVEL_FULL
303 #define PCI230P2_DAC_FIFOROOM_ONETOHALF		\
304 	(PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
305 #define PCI230P2_DAC_FIFOROOM_HALFTOFULL	1
306 #define PCI230P2_DAC_FIFOROOM_FULL		0
307 
308 /* ADCCON read/write values. */
309 #define PCI230_ADC_TRIG_NONE		(0<<0)	/* No trigger */
310 #define PCI230_ADC_TRIG_SW		(1<<0)	/* Software trigger trigger */
311 #define PCI230_ADC_TRIG_EXTP		(2<<0)	/* EXTTRIG +ve edge trigger */
312 #define PCI230_ADC_TRIG_EXTN		(3<<0)	/* EXTTRIG -ve edge trigger */
313 #define PCI230_ADC_TRIG_Z2CT0		(4<<0)	/* CT0-OUT +ve edge trigger */
314 #define PCI230_ADC_TRIG_Z2CT1		(5<<0)	/* CT1-OUT +ve edge trigger */
315 #define PCI230_ADC_TRIG_Z2CT2		(6<<0)	/* CT2-OUT +ve edge trigger */
316 #define PCI230_ADC_TRIG_MASK		(7<<0)
317 #define PCI230_ADC_IR_UNI		(0<<3)	/* Input range unipolar */
318 #define PCI230_ADC_IR_BIP		(1<<3)	/* Input range bipolar */
319 #define PCI230_ADC_IR_MASK		(1<<3)
320 #define PCI230_ADC_IM_SE		(0<<4)	/* Input mode single ended */
321 #define PCI230_ADC_IM_DIF		(1<<4)	/* Input mode differential */
322 #define PCI230_ADC_IM_MASK		(1<<4)
323 #define PCI230_ADC_FIFO_EN		(1<<8)	/* FIFO enable */
324 #define PCI230_ADC_INT_FIFO_EMPTY	(0<<9)
325 #define PCI230_ADC_INT_FIFO_NEMPTY	(1<<9)	/* FIFO interrupt not empty */
326 #define PCI230_ADC_INT_FIFO_NHALF	(2<<9)
327 #define PCI230_ADC_INT_FIFO_HALF	(3<<9)	/* FIFO interrupt half full */
328 #define PCI230_ADC_INT_FIFO_NFULL	(4<<9)
329 #define PCI230_ADC_INT_FIFO_FULL	(5<<9)	/* FIFO interrupt full */
330 #define PCI230P_ADC_INT_FIFO_THRESH	(7<<9)	/* FIFO interrupt threshold */
331 #define PCI230_ADC_INT_FIFO_MASK	(7<<9)
332 
333 /* ADCCON write-only, transient values. */
334 #define PCI230_ADC_FIFO_RESET		(1<<12)	/* FIFO reset */
335 #define PCI230_ADC_GLOB_RESET		(1<<13)	/* Global reset */
336 
337 /* ADCCON read-only values. */
338 #define PCI230_ADC_BUSY			(1<<15)	/* ADC busy */
339 #define PCI230_ADC_FIFO_EMPTY		(1<<12)	/* FIFO empty */
340 #define PCI230_ADC_FIFO_FULL		(1<<13)	/* FIFO full */
341 #define PCI230_ADC_FIFO_HALF		(1<<14)	/* FIFO half full */
342 #define PCI230_ADC_FIFO_FULL_LATCHED	(1<<5)	/* Indicates overrun occurred */
343 
344 /* PCI230 ADC FIFO levels. */
345 #define PCI230_ADC_FIFOLEVEL_HALFFULL	2049	/* Value for FIFO half full */
346 #define PCI230_ADC_FIFOLEVEL_FULL	4096	/* FIFO size */
347 
348 /* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
349  * mode.  Can be anything.  */
350 #define PCI230_ADC_CONV			0xffff
351 
352 /* PCI230+ EXTFUNC values. */
353 #define PCI230P_EXTFUNC_GAT_EXTTRIG	(1<<0)
354 			/* Route EXTTRIG pin to external gate inputs. */
355 /* PCI230+ hardware version 2 values. */
356 #define PCI230P2_EXTFUNC_DACFIFO	(1<<1)
357 			/* Allow DAC FIFO to be enabled. */
358 
359 /*
360  * Counter/timer clock input configuration sources.
361  */
362 #define CLK_CLK		0	/* reserved (channel-specific clock) */
363 #define CLK_10MHZ	1	/* internal 10 MHz clock */
364 #define CLK_1MHZ	2	/* internal 1 MHz clock */
365 #define CLK_100KHZ	3	/* internal 100 kHz clock */
366 #define CLK_10KHZ	4	/* internal 10 kHz clock */
367 #define CLK_1KHZ	5	/* internal 1 kHz clock */
368 #define CLK_OUTNM1	6	/* output of channel-1 modulo total */
369 #define CLK_EXT		7	/* external clock */
370 /* Macro to construct clock input configuration register value. */
371 #define CLK_CONFIG(chan, src)	((((chan) & 3) << 3) | ((src) & 7))
372 /* Timebases in ns. */
373 #define TIMEBASE_10MHZ		100
374 #define TIMEBASE_1MHZ		1000
375 #define TIMEBASE_100KHZ		10000
376 #define TIMEBASE_10KHZ		100000
377 #define TIMEBASE_1KHZ		1000000
378 
379 /*
380  * Counter/timer gate input configuration sources.
381  */
382 #define GAT_VCC		0	/* VCC (i.e. enabled) */
383 #define GAT_GND		1	/* GND (i.e. disabled) */
384 #define GAT_EXT		2	/* external gate input (PPCn on PCI230) */
385 #define GAT_NOUTNM2	3	/* inverted output of channel-2 modulo total */
386 /* Macro to construct gate input configuration register value. */
387 #define GAT_CONFIG(chan, src)	((((chan) & 3) << 3) | ((src) & 7))
388 
389 /*
390  * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
391  *
392  *              Channel's       Channel's
393  *              clock input     gate input
394  * Channel      CLK_OUTNM1      GAT_NOUTNM2
395  * -------      ----------      -----------
396  * Z2-CT0       Z2-CT2-OUT      /Z2-CT1-OUT
397  * Z2-CT1       Z2-CT0-OUT      /Z2-CT2-OUT
398  * Z2-CT2       Z2-CT1-OUT      /Z2-CT0-OUT
399  */
400 
401 /* Interrupt enables/status register values. */
402 #define PCI230_INT_DISABLE		0
403 #define PCI230_INT_PPI_C0		(1<<0)
404 #define PCI230_INT_PPI_C3		(1<<1)
405 #define PCI230_INT_ADC			(1<<2)
406 #define PCI230_INT_ZCLK_CT1		(1<<5)
407 /* For PCI230+ hardware version 2 when DAC FIFO enabled. */
408 #define PCI230P2_INT_DAC		(1<<4)
409 
410 #define PCI230_TEST_BIT(val, n)	((val>>n)&1)
411 			/* Assumes bits numbered with zero offset, ie. 0-15 */
412 
413 /* (Potentially) shared resources and their owners */
414 enum {
415 	RES_Z2CT0,		/* Z2-CT0 */
416 	RES_Z2CT1,		/* Z2-CT1 */
417 	RES_Z2CT2,		/* Z2-CT2 */
418 	NUM_RESOURCES		/* Number of (potentially) shared resources. */
419 };
420 
421 enum {
422 	OWNER_NONE,		/* Not owned */
423 	OWNER_AICMD,		/* Owned by AI command */
424 	OWNER_AOCMD		/* Owned by AO command */
425 };
426 
427 /*
428  * Handy macros.
429  */
430 
431 /* Combine old and new bits. */
432 #define COMBINE(old, new, mask)	(((old) & ~(mask)) | ((new) & (mask)))
433 
434 /* A generic null function pointer value.  */
435 #define NULLFUNC	0
436 
437 /* Current CPU.  XXX should this be hard_smp_processor_id()? */
438 #define THISCPU		smp_processor_id()
439 
440 /* State flags for atomic bit operations */
441 #define AI_CMD_STARTED	0
442 #define AO_CMD_STARTED	1
443 
444 /*
445  * Board descriptions for the two boards supported.
446  */
447 
448 struct pci230_board {
449 	const char *name;
450 	unsigned short id;
451 	int ai_chans;
452 	int ai_bits;
453 	int ao_chans;
454 	int ao_bits;
455 	int have_dio;
456 	unsigned int min_hwver;	/* Minimum hardware version supported. */
457 };
458 static const struct pci230_board pci230_boards[] = {
459 	{
460 	 .name = "pci230+",
461 	 .id = PCI_DEVICE_ID_PCI230,
462 	 .ai_chans = 16,
463 	 .ai_bits = 16,
464 	 .ao_chans = 2,
465 	 .ao_bits = 12,
466 	 .have_dio = 1,
467 	 .min_hwver = 1,
468 	 },
469 	{
470 	 .name = "pci260+",
471 	 .id = PCI_DEVICE_ID_PCI260,
472 	 .ai_chans = 16,
473 	 .ai_bits = 16,
474 	 .ao_chans = 0,
475 	 .ao_bits = 0,
476 	 .have_dio = 0,
477 	 .min_hwver = 1,
478 	 },
479 	{
480 	 .name = "pci230",
481 	 .id = PCI_DEVICE_ID_PCI230,
482 	 .ai_chans = 16,
483 	 .ai_bits = 12,
484 	 .ao_chans = 2,
485 	 .ao_bits = 12,
486 	 .have_dio = 1,
487 	 },
488 	{
489 	 .name = "pci260",
490 	 .id = PCI_DEVICE_ID_PCI260,
491 	 .ai_chans = 16,
492 	 .ai_bits = 12,
493 	 .ao_chans = 0,
494 	 .ao_bits = 0,
495 	 .have_dio = 0,
496 	 },
497 	{
498 	 .name = "amplc_pci230",	/* Wildcard matches any above */
499 	 .id = PCI_DEVICE_ID_INVALID,
500 	 },
501 };
502 
503 static DEFINE_PCI_DEVICE_TABLE(pci230_pci_table) = {
504 	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230) },
505 	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260) },
506 	{0}
507 };
508 
509 MODULE_DEVICE_TABLE(pci, pci230_pci_table);
510 /*
511  * Useful for shorthand access to the particular board structure
512  */
513 #define n_pci230_boards ARRAY_SIZE(pci230_boards)
514 #define thisboard ((const struct pci230_board *)dev->board_ptr)
515 
516 /* this structure is for data unique to this hardware driver.  If
517    several hardware drivers keep similar information in this structure,
518    feel free to suggest moving the variable to the struct comedi_device struct.  */
519 struct pci230_private {
520 	struct pci_dev *pci_dev;
521 	spinlock_t isr_spinlock;	/* Interrupt spin lock */
522 	spinlock_t res_spinlock;	/* Shared resources spin lock */
523 	spinlock_t ai_stop_spinlock;	/* Spin lock for stopping AI command */
524 	spinlock_t ao_stop_spinlock;	/* Spin lock for stopping AO command */
525 	unsigned long state;	/* State flags */
526 	unsigned long iobase1;	/* PCI230's I/O space 1 */
527 	unsigned int ao_readback[2];	/* Used for AO readback */
528 	unsigned int ai_scan_count;	/* Number of analogue input scans
529 					 * remaining.  */
530 	unsigned int ai_scan_pos;	/* Current position within analogue
531 					 * input scan */
532 	unsigned int ao_scan_count;	/* Number of analogue output scans
533 					 * remaining.  */
534 	int intr_cpuid;		/* ID of CPU running interrupt routine. */
535 	unsigned short hwver;	/* Hardware version (for '+' models). */
536 	unsigned short adccon;	/* ADCCON register value. */
537 	unsigned short daccon;	/* DACCON register value. */
538 	unsigned short adcfifothresh;	/* ADC FIFO programmable interrupt
539 					 * level threshold (PCI230+/260+). */
540 	unsigned short adcg;	/* ADCG register value. */
541 	unsigned char int_en;	/* Interrupt enables bits. */
542 	unsigned char ai_continuous;	/* Flag set when cmd->stop_src ==
543 					 * TRIG_NONE - user chooses to stop
544 					 * continuous conversion by
545 					 * cancelation. */
546 	unsigned char ao_continuous;	/* Flag set when cmd->stop_src ==
547 					 * TRIG_NONE - user chooses to stop
548 					 * continuous conversion by
549 					 * cancelation. */
550 	unsigned char ai_bipolar;	/* Set if bipolar input range so we
551 					 * know to mangle it. */
552 	unsigned char ao_bipolar;	/* Set if bipolar output range so we
553 					 * know to mangle it. */
554 	unsigned char ier;	/* Copy of interrupt enables/status register. */
555 	unsigned char intr_running;	/* Flag set in interrupt routine. */
556 	unsigned char res_owner[NUM_RESOURCES];	/* Shared resource owners. */
557 };
558 
559 #define devpriv ((struct pci230_private *)dev->private)
560 
561 /* PCI230 clock source periods in ns */
562 static const unsigned int pci230_timebase[8] = {
563 	[CLK_10MHZ] = TIMEBASE_10MHZ,
564 	[CLK_1MHZ] = TIMEBASE_1MHZ,
565 	[CLK_100KHZ] = TIMEBASE_100KHZ,
566 	[CLK_10KHZ] = TIMEBASE_10KHZ,
567 	[CLK_1KHZ] = TIMEBASE_1KHZ,
568 };
569 
570 /* PCI230 analogue input range table */
571 static const struct comedi_lrange pci230_ai_range = { 7, {
572 							  BIP_RANGE(10),
573 							  BIP_RANGE(5),
574 							  BIP_RANGE(2.5),
575 							  BIP_RANGE(1.25),
576 							  UNI_RANGE(10),
577 							  UNI_RANGE(5),
578 							  UNI_RANGE(2.5)
579 							  }
580 };
581 
582 /* PCI230 analogue gain bits for each input range. */
583 static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
584 
585 /* PCI230 adccon bipolar flag for each analogue input range. */
586 static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
587 
588 /* PCI230 analogue output range table */
589 static const struct comedi_lrange pci230_ao_range = { 2, {
590 							  UNI_RANGE(10),
591 							  BIP_RANGE(10)
592 							  }
593 };
594 
595 /* PCI230 daccon bipolar flag for each analogue output range. */
596 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
597 
598 /*
599  * The struct comedi_driver structure tells the Comedi core module
600  * which functions to call to configure/deconfigure (attach/detach)
601  * the board, and also about the kernel module that contains
602  * the device code.
603  */
604 static int pci230_attach(struct comedi_device *dev,
605 			 struct comedi_devconfig *it);
606 static int pci230_detach(struct comedi_device *dev);
607 static struct comedi_driver driver_amplc_pci230 = {
608 	.driver_name = "amplc_pci230",
609 	.module = THIS_MODULE,
610 	.attach = pci230_attach,
611 	.detach = pci230_detach,
612 	.board_name = &pci230_boards[0].name,
613 	.offset = sizeof(pci230_boards[0]),
614 	.num_names = ARRAY_SIZE(pci230_boards),
615 };
616 
driver_amplc_pci230_pci_probe(struct pci_dev * dev,const struct pci_device_id * ent)617 static int __devinit driver_amplc_pci230_pci_probe(struct pci_dev *dev,
618 						   const struct pci_device_id
619 						   *ent)
620 {
621 	return comedi_pci_auto_config(dev, driver_amplc_pci230.driver_name);
622 }
623 
driver_amplc_pci230_pci_remove(struct pci_dev * dev)624 static void __devexit driver_amplc_pci230_pci_remove(struct pci_dev *dev)
625 {
626 	comedi_pci_auto_unconfig(dev);
627 }
628 
629 static struct pci_driver driver_amplc_pci230_pci_driver = {
630 	.id_table = pci230_pci_table,
631 	.probe = &driver_amplc_pci230_pci_probe,
632 	.remove = __devexit_p(&driver_amplc_pci230_pci_remove)
633 };
634 
driver_amplc_pci230_init_module(void)635 static int __init driver_amplc_pci230_init_module(void)
636 {
637 	int retval;
638 
639 	retval = comedi_driver_register(&driver_amplc_pci230);
640 	if (retval < 0)
641 		return retval;
642 
643 	driver_amplc_pci230_pci_driver.name =
644 	    (char *)driver_amplc_pci230.driver_name;
645 	return pci_register_driver(&driver_amplc_pci230_pci_driver);
646 }
647 
driver_amplc_pci230_cleanup_module(void)648 static void __exit driver_amplc_pci230_cleanup_module(void)
649 {
650 	pci_unregister_driver(&driver_amplc_pci230_pci_driver);
651 	comedi_driver_unregister(&driver_amplc_pci230);
652 }
653 
654 module_init(driver_amplc_pci230_init_module);
655 module_exit(driver_amplc_pci230_cleanup_module);
656 
657 static int pci230_ai_rinsn(struct comedi_device *dev,
658 			   struct comedi_subdevice *s, struct comedi_insn *insn,
659 			   unsigned int *data);
660 static int pci230_ao_winsn(struct comedi_device *dev,
661 			   struct comedi_subdevice *s, struct comedi_insn *insn,
662 			   unsigned int *data);
663 static int pci230_ao_rinsn(struct comedi_device *dev,
664 			   struct comedi_subdevice *s, struct comedi_insn *insn,
665 			   unsigned int *data);
666 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
667 				    unsigned int mode, uint64_t ns,
668 				    unsigned int round);
669 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
670 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct);
671 static irqreturn_t pci230_interrupt(int irq, void *d);
672 static int pci230_ao_cmdtest(struct comedi_device *dev,
673 			     struct comedi_subdevice *s,
674 			     struct comedi_cmd *cmd);
675 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
676 static int pci230_ao_cancel(struct comedi_device *dev,
677 			    struct comedi_subdevice *s);
678 static void pci230_ao_stop(struct comedi_device *dev,
679 			   struct comedi_subdevice *s);
680 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
681 				    struct comedi_subdevice *s);
682 static int pci230_handle_ao_fifo(struct comedi_device *dev,
683 				 struct comedi_subdevice *s);
684 static int pci230_ai_cmdtest(struct comedi_device *dev,
685 			     struct comedi_subdevice *s,
686 			     struct comedi_cmd *cmd);
687 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
688 static int pci230_ai_cancel(struct comedi_device *dev,
689 			    struct comedi_subdevice *s);
690 static void pci230_ai_stop(struct comedi_device *dev,
691 			   struct comedi_subdevice *s);
692 static void pci230_handle_ai(struct comedi_device *dev,
693 			     struct comedi_subdevice *s);
694 
pci230_ai_read(struct comedi_device * dev)695 static short pci230_ai_read(struct comedi_device *dev)
696 {
697 	/* Read sample. */
698 	short data = (short)inw(dev->iobase + PCI230_ADCDATA);
699 
700 	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
701 	 * four bits reserved for expansion). */
702 	/* PCI230+ is 16 bit AI. */
703 	data = data >> (16 - thisboard->ai_bits);
704 
705 	/* If a bipolar range was specified, mangle it (twos
706 	 * complement->straight binary). */
707 	if (devpriv->ai_bipolar)
708 		data ^= 1 << (thisboard->ai_bits - 1);
709 
710 	return data;
711 }
712 
pci230_ao_mangle_datum(struct comedi_device * dev,short datum)713 static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
714 						    short datum)
715 {
716 	/* If a bipolar range was specified, mangle it (straight binary->twos
717 	 * complement). */
718 	if (devpriv->ao_bipolar)
719 		datum ^= 1 << (thisboard->ao_bits - 1);
720 
721 
722 	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
723 	 * four bits reserved for expansion). */
724 	/* PCI230+ is also 12 bit AO. */
725 	datum <<= (16 - thisboard->ao_bits);
726 	return (unsigned short)datum;
727 }
728 
pci230_ao_write_nofifo(struct comedi_device * dev,short datum,unsigned int chan)729 static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
730 					  short datum, unsigned int chan)
731 {
732 	/* Store unmangled datum to be read back later. */
733 	devpriv->ao_readback[chan] = datum;
734 
735 	/* Write mangled datum to appropriate DACOUT register. */
736 	outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
737 								? PCI230_DACOUT1
738 								:
739 								PCI230_DACOUT2));
740 }
741 
pci230_ao_write_fifo(struct comedi_device * dev,short datum,unsigned int chan)742 static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
743 					unsigned int chan)
744 {
745 	/* Store unmangled datum to be read back later. */
746 	devpriv->ao_readback[chan] = datum;
747 
748 	/* Write mangled datum to appropriate DACDATA register. */
749 	outw(pci230_ao_mangle_datum(dev, datum),
750 	     dev->iobase + PCI230P2_DACDATA);
751 }
752 
753 /*
754  * Attach is called by the Comedi core to configure the driver
755  * for a particular board.  If you specified a board_name array
756  * in the driver structure, dev->board_ptr contains that
757  * address.
758  */
pci230_attach(struct comedi_device * dev,struct comedi_devconfig * it)759 static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
760 {
761 	struct comedi_subdevice *s;
762 	unsigned long iobase1, iobase2;
763 	/* PCI230's I/O spaces 1 and 2 respectively. */
764 	struct pci_dev *pci_dev = NULL;
765 	int i = 0, irq_hdl, rc;
766 
767 	printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
768 	       thisboard->name, it->options[0], it->options[1]);
769 
770 	/* Allocate the private structure area using alloc_private().
771 	 * Macro defined in comedidev.h - memsets struct fields to 0. */
772 	if ((alloc_private(dev, sizeof(struct pci230_private))) < 0)
773 		return -ENOMEM;
774 
775 	spin_lock_init(&devpriv->isr_spinlock);
776 	spin_lock_init(&devpriv->res_spinlock);
777 	spin_lock_init(&devpriv->ai_stop_spinlock);
778 	spin_lock_init(&devpriv->ao_stop_spinlock);
779 	/* Find card */
780 	for_each_pci_dev(pci_dev) {
781 		if (it->options[0] || it->options[1]) {
782 			/* Match against bus/slot options. */
783 			if (it->options[0] != pci_dev->bus->number ||
784 			    it->options[1] != PCI_SLOT(pci_dev->devfn))
785 				continue;
786 		}
787 		if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
788 			continue;
789 		if (thisboard->id == PCI_DEVICE_ID_INVALID) {
790 			/* The name was specified as "amplc_pci230" which is
791 			 * used to match any supported device.  Replace the
792 			 * current dev->board_ptr with one that matches the
793 			 * PCI device ID. */
794 			for (i = 0; i < n_pci230_boards; i++) {
795 				if (pci_dev->device == pci230_boards[i].id) {
796 					if (pci230_boards[i].min_hwver > 0) {
797 						/* Check for a '+' model.
798 						 * First check length of
799 						 * registers. */
800 						if (pci_resource_len(pci_dev, 3)
801 						    < 32) {
802 							/* Not a '+' model. */
803 							continue;
804 						}
805 						/* TODO: temporarily enable the
806 						 * PCI device and read the
807 						 * hardware version register.
808 						 * For now assume it's okay. */
809 					}
810 					/* Change board_ptr to matched board */
811 					dev->board_ptr = &pci230_boards[i];
812 					break;
813 				}
814 			}
815 			if (i < n_pci230_boards)
816 				break;
817 		} else {
818 			/* The name was specified as a specific device name.
819 			 * The current dev->board_ptr is correct.  Check
820 			 * whether it matches the PCI device ID. */
821 			if (thisboard->id == pci_dev->device) {
822 				/* Check minimum hardware version. */
823 				if (thisboard->min_hwver > 0) {
824 					/* Looking for a '+' model.  First
825 					 * check length of registers. */
826 					if (pci_resource_len(pci_dev, 3) < 32) {
827 						/* Not a '+' model. */
828 						continue;
829 					}
830 					/* TODO: temporarily enable the PCI
831 					 * device and read the hardware version
832 					 * register.  For now, assume it's
833 					 * okay. */
834 					break;
835 				} else {
836 					break;
837 				}
838 			}
839 		}
840 	}
841 	if (!pci_dev) {
842 		printk("comedi%d: No %s card found\n", dev->minor,
843 		       thisboard->name);
844 		return -EIO;
845 	}
846 	devpriv->pci_dev = pci_dev;
847 
848 	/*
849 	 * Initialize dev->board_name.
850 	 */
851 	dev->board_name = thisboard->name;
852 
853 	/* Enable PCI device and reserve I/O spaces. */
854 	if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) {
855 		printk("comedi%d: failed to enable PCI device "
856 		       "and request regions\n", dev->minor);
857 		return -EIO;
858 	}
859 
860 	/* Read base addresses of the PCI230's two I/O regions from PCI
861 	 * configuration register. */
862 	iobase1 = pci_resource_start(pci_dev, 2);
863 	iobase2 = pci_resource_start(pci_dev, 3);
864 
865 	printk("comedi%d: %s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
866 	       dev->minor, dev->board_name, iobase1, iobase2);
867 
868 	devpriv->iobase1 = iobase1;
869 	dev->iobase = iobase2;
870 
871 	/* Read bits of DACCON register - only the output range. */
872 	devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
873 
874 	/* Read hardware version register and set extended function register
875 	 * if they exist. */
876 	if (pci_resource_len(pci_dev, 3) >= 32) {
877 		unsigned short extfunc = 0;
878 
879 		devpriv->hwver = inw(dev->iobase + PCI230P_HWVER);
880 		if (devpriv->hwver < thisboard->min_hwver) {
881 			printk("comedi%d: %s - bad hardware version "
882 			       "- got %u, need %u\n", dev->minor,
883 			       dev->board_name, devpriv->hwver,
884 			       thisboard->min_hwver);
885 			return -EIO;
886 		}
887 		if (devpriv->hwver > 0) {
888 			if (!thisboard->have_dio) {
889 				/* No DIO ports.  Route counters' external gates
890 				 * to the EXTTRIG signal (PCI260+ pin 17).
891 				 * (Otherwise, they would be routed to DIO
892 				 * inputs PC0, PC1 and PC2 which don't exist
893 				 * on PCI260[+].) */
894 				extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
895 			}
896 			if ((thisboard->ao_chans > 0)
897 			    && (devpriv->hwver >= 2)) {
898 				/* Enable DAC FIFO functionality. */
899 				extfunc |= PCI230P2_EXTFUNC_DACFIFO;
900 			}
901 		}
902 		outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
903 		if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) {
904 			/* Temporarily enable DAC FIFO, reset it and disable
905 			 * FIFO wraparound. */
906 			outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN
907 			     | PCI230P2_DAC_FIFO_RESET,
908 			     dev->iobase + PCI230_DACCON);
909 			/* Clear DAC FIFO channel enable register. */
910 			outw(0, dev->iobase + PCI230P2_DACEN);
911 			/* Disable DAC FIFO. */
912 			outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
913 		}
914 	}
915 
916 	/* Disable board's interrupts. */
917 	outb(0, devpriv->iobase1 + PCI230_INT_SCE);
918 
919 	/* Set ADC to a reasonable state. */
920 	devpriv->adcg = 0;
921 	devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE
922 	    | PCI230_ADC_IR_BIP;
923 	outw(1 << 0, dev->iobase + PCI230_ADCEN);
924 	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
925 	outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
926 	     dev->iobase + PCI230_ADCCON);
927 
928 	/* Register the interrupt handler. */
929 	irq_hdl = request_irq(devpriv->pci_dev->irq, pci230_interrupt,
930 			      IRQF_SHARED, "amplc_pci230", dev);
931 	if (irq_hdl < 0) {
932 		printk("comedi%d: unable to register irq, "
933 		       "commands will not be available %d\n", dev->minor,
934 		       devpriv->pci_dev->irq);
935 	} else {
936 		dev->irq = devpriv->pci_dev->irq;
937 		printk("comedi%d: registered irq %u\n", dev->minor,
938 		       devpriv->pci_dev->irq);
939 	}
940 
941 	/*
942 	 * Allocate the subdevice structures.  alloc_subdevice() is a
943 	 * convenient macro defined in comedidev.h.
944 	 */
945 	if (alloc_subdevices(dev, 3) < 0)
946 		return -ENOMEM;
947 
948 	s = dev->subdevices + 0;
949 	/* analog input subdevice */
950 	s->type = COMEDI_SUBD_AI;
951 	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
952 	s->n_chan = thisboard->ai_chans;
953 	s->maxdata = (1 << thisboard->ai_bits) - 1;
954 	s->range_table = &pci230_ai_range;
955 	s->insn_read = &pci230_ai_rinsn;
956 	s->len_chanlist = 256;	/* but there are restrictions. */
957 	/* Only register commands if the interrupt handler is installed. */
958 	if (irq_hdl == 0) {
959 		dev->read_subdev = s;
960 		s->subdev_flags |= SDF_CMD_READ;
961 		s->do_cmd = &pci230_ai_cmd;
962 		s->do_cmdtest = &pci230_ai_cmdtest;
963 		s->cancel = pci230_ai_cancel;
964 	}
965 
966 	s = dev->subdevices + 1;
967 	/* analog output subdevice */
968 	if (thisboard->ao_chans > 0) {
969 		s->type = COMEDI_SUBD_AO;
970 		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
971 		s->n_chan = thisboard->ao_chans;
972 		s->maxdata = (1 << thisboard->ao_bits) - 1;
973 		s->range_table = &pci230_ao_range;
974 		s->insn_write = &pci230_ao_winsn;
975 		s->insn_read = &pci230_ao_rinsn;
976 		s->len_chanlist = thisboard->ao_chans;
977 		/* Only register commands if the interrupt handler is
978 		 * installed. */
979 		if (irq_hdl == 0) {
980 			dev->write_subdev = s;
981 			s->subdev_flags |= SDF_CMD_WRITE;
982 			s->do_cmd = &pci230_ao_cmd;
983 			s->do_cmdtest = &pci230_ao_cmdtest;
984 			s->cancel = pci230_ao_cancel;
985 		}
986 	} else {
987 		s->type = COMEDI_SUBD_UNUSED;
988 	}
989 
990 	s = dev->subdevices + 2;
991 	/* digital i/o subdevice */
992 	if (thisboard->have_dio) {
993 		rc = subdev_8255_init(dev, s, NULL,
994 				      (devpriv->iobase1 + PCI230_PPI_X_BASE));
995 		if (rc < 0)
996 			return rc;
997 	} else {
998 		s->type = COMEDI_SUBD_UNUSED;
999 	}
1000 
1001 	printk("comedi%d: attached\n", dev->minor);
1002 
1003 	return 1;
1004 }
1005 
1006 /*
1007  * _detach is called to deconfigure a device.  It should deallocate
1008  * resources.
1009  * This function is also called when _attach() fails, so it should be
1010  * careful not to release resources that were not necessarily
1011  * allocated by _attach().  dev->private and dev->subdevices are
1012  * deallocated automatically by the core.
1013  */
pci230_detach(struct comedi_device * dev)1014 static int pci230_detach(struct comedi_device *dev)
1015 {
1016 	printk("comedi%d: amplc_pci230: remove\n", dev->minor);
1017 
1018 	if (dev->subdevices && thisboard->have_dio)
1019 		/* Clean up dio subdevice. */
1020 		subdev_8255_cleanup(dev, dev->subdevices + 2);
1021 
1022 	if (dev->irq)
1023 		free_irq(dev->irq, dev);
1024 
1025 	if (devpriv) {
1026 		if (devpriv->pci_dev) {
1027 			if (dev->iobase)
1028 				comedi_pci_disable(devpriv->pci_dev);
1029 
1030 			pci_dev_put(devpriv->pci_dev);
1031 		}
1032 	}
1033 
1034 	return 0;
1035 }
1036 
get_resources(struct comedi_device * dev,unsigned int res_mask,unsigned char owner)1037 static int get_resources(struct comedi_device *dev, unsigned int res_mask,
1038 			 unsigned char owner)
1039 {
1040 	int ok;
1041 	unsigned int i;
1042 	unsigned int b;
1043 	unsigned int claimed;
1044 	unsigned long irqflags;
1045 
1046 	ok = 1;
1047 	claimed = 0;
1048 	spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
1049 	for (b = 1, i = 0; (i < NUM_RESOURCES)
1050 	     && (res_mask != 0); b <<= 1, i++) {
1051 		if ((res_mask & b) != 0) {
1052 			res_mask &= ~b;
1053 			if (devpriv->res_owner[i] == OWNER_NONE) {
1054 				devpriv->res_owner[i] = owner;
1055 				claimed |= b;
1056 			} else if (devpriv->res_owner[i] != owner) {
1057 				for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
1058 					if ((claimed & b) != 0) {
1059 						devpriv->res_owner[i]
1060 						    = OWNER_NONE;
1061 						claimed &= ~b;
1062 					}
1063 				}
1064 				ok = 0;
1065 				break;
1066 			}
1067 		}
1068 	}
1069 	spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
1070 	return ok;
1071 }
1072 
get_one_resource(struct comedi_device * dev,unsigned int resource,unsigned char owner)1073 static inline int get_one_resource(struct comedi_device *dev,
1074 				   unsigned int resource, unsigned char owner)
1075 {
1076 	return get_resources(dev, (1U << resource), owner);
1077 }
1078 
put_resources(struct comedi_device * dev,unsigned int res_mask,unsigned char owner)1079 static void put_resources(struct comedi_device *dev, unsigned int res_mask,
1080 			  unsigned char owner)
1081 {
1082 	unsigned int i;
1083 	unsigned int b;
1084 	unsigned long irqflags;
1085 
1086 	spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
1087 	for (b = 1, i = 0; (i < NUM_RESOURCES)
1088 	     && (res_mask != 0); b <<= 1, i++) {
1089 		if ((res_mask & b) != 0) {
1090 			res_mask &= ~b;
1091 			if (devpriv->res_owner[i] == owner)
1092 				devpriv->res_owner[i] = OWNER_NONE;
1093 
1094 		}
1095 	}
1096 	spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
1097 }
1098 
put_one_resource(struct comedi_device * dev,unsigned int resource,unsigned char owner)1099 static inline void put_one_resource(struct comedi_device *dev,
1100 				    unsigned int resource, unsigned char owner)
1101 {
1102 	put_resources(dev, (1U << resource), owner);
1103 }
1104 
put_all_resources(struct comedi_device * dev,unsigned char owner)1105 static inline void put_all_resources(struct comedi_device *dev,
1106 				     unsigned char owner)
1107 {
1108 	put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
1109 }
1110 
1111 /*
1112  *  COMEDI_SUBD_AI instruction;
1113  */
pci230_ai_rinsn(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1114 static int pci230_ai_rinsn(struct comedi_device *dev,
1115 			   struct comedi_subdevice *s, struct comedi_insn *insn,
1116 			   unsigned int *data)
1117 {
1118 	unsigned int n, i;
1119 	unsigned int chan, range, aref;
1120 	unsigned int gainshift;
1121 	unsigned int status;
1122 	unsigned short adccon, adcen;
1123 
1124 	/* Unpack channel and range. */
1125 	chan = CR_CHAN(insn->chanspec);
1126 	range = CR_RANGE(insn->chanspec);
1127 	aref = CR_AREF(insn->chanspec);
1128 	if (aref == AREF_DIFF) {
1129 		/* Differential. */
1130 		if (chan >= s->n_chan / 2) {
1131 			DPRINTK("comedi%d: amplc_pci230: ai_rinsn: "
1132 				"differential channel number out of range "
1133 				"0 to %u\n", dev->minor, (s->n_chan / 2) - 1);
1134 			return -EINVAL;
1135 		}
1136 	}
1137 
1138 	/* Use Z2-CT2 as a conversion trigger instead of the built-in
1139 	 * software trigger, as otherwise triggering of differential channels
1140 	 * doesn't work properly for some versions of PCI230/260.  Also set
1141 	 * FIFO mode because the ADC busy bit only works for software triggers.
1142 	 */
1143 	adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
1144 	/* Set Z2-CT2 output low to avoid any false triggers. */
1145 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
1146 	devpriv->ai_bipolar = pci230_ai_bipolar[range];
1147 	if (aref == AREF_DIFF) {
1148 		/* Differential. */
1149 		gainshift = chan * 2;
1150 		if (devpriv->hwver == 0) {
1151 			/* Original PCI230/260 expects both inputs of the
1152 			 * differential channel to be enabled. */
1153 			adcen = 3 << gainshift;
1154 		} else {
1155 			/* PCI230+/260+ expects only one input of the
1156 			 * differential channel to be enabled. */
1157 			adcen = 1 << gainshift;
1158 		}
1159 		adccon |= PCI230_ADC_IM_DIF;
1160 	} else {
1161 		/* Single ended. */
1162 		adcen = 1 << chan;
1163 		gainshift = chan & ~1;
1164 		adccon |= PCI230_ADC_IM_SE;
1165 	}
1166 	devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
1167 	    | (pci230_ai_gain[range] << gainshift);
1168 	if (devpriv->ai_bipolar)
1169 		adccon |= PCI230_ADC_IR_BIP;
1170 	else
1171 		adccon |= PCI230_ADC_IR_UNI;
1172 
1173 
1174 	/* Enable only this channel in the scan list - otherwise by default
1175 	 * we'll get one sample from each channel. */
1176 	outw(adcen, dev->iobase + PCI230_ADCEN);
1177 
1178 	/* Set gain for channel. */
1179 	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
1180 
1181 	/* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
1182 	devpriv->adccon = adccon;
1183 	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
1184 
1185 	/* Convert n samples */
1186 	for (n = 0; n < insn->n; n++) {
1187 		/* Trigger conversion by toggling Z2-CT2 output (finish with
1188 		 * output high). */
1189 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1190 			       I8254_MODE0);
1191 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1192 			       I8254_MODE1);
1193 
1194 #define TIMEOUT 100
1195 		/* wait for conversion to end */
1196 		for (i = 0; i < TIMEOUT; i++) {
1197 			status = inw(dev->iobase + PCI230_ADCCON);
1198 			if (!(status & PCI230_ADC_FIFO_EMPTY))
1199 				break;
1200 			udelay(1);
1201 		}
1202 		if (i == TIMEOUT) {
1203 			/* printk() should be used instead of printk()
1204 			 * whenever the code can be called from real-time. */
1205 			printk("timeout\n");
1206 			return -ETIMEDOUT;
1207 		}
1208 
1209 		/* read data */
1210 		data[n] = pci230_ai_read(dev);
1211 	}
1212 
1213 	/* return the number of samples read/written */
1214 	return n;
1215 }
1216 
1217 /*
1218  *  COMEDI_SUBD_AO instructions;
1219  */
pci230_ao_winsn(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1220 static int pci230_ao_winsn(struct comedi_device *dev,
1221 			   struct comedi_subdevice *s, struct comedi_insn *insn,
1222 			   unsigned int *data)
1223 {
1224 	int i;
1225 	int chan, range;
1226 
1227 	/* Unpack channel and range. */
1228 	chan = CR_CHAN(insn->chanspec);
1229 	range = CR_RANGE(insn->chanspec);
1230 
1231 	/* Set range - see analogue output range table; 0 => unipolar 10V,
1232 	 * 1 => bipolar +/-10V range scale */
1233 	devpriv->ao_bipolar = pci230_ao_bipolar[range];
1234 	outw(range, dev->iobase + PCI230_DACCON);
1235 
1236 	/* Writing a list of values to an AO channel is probably not
1237 	 * very useful, but that's how the interface is defined. */
1238 	for (i = 0; i < insn->n; i++) {
1239 		/* Write value to DAC and store it. */
1240 		pci230_ao_write_nofifo(dev, data[i], chan);
1241 	}
1242 
1243 	/* return the number of samples read/written */
1244 	return i;
1245 }
1246 
1247 /* AO subdevices should have a read insn as well as a write insn.
1248  * Usually this means copying a value stored in devpriv. */
pci230_ao_rinsn(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1249 static int pci230_ao_rinsn(struct comedi_device *dev,
1250 			   struct comedi_subdevice *s, struct comedi_insn *insn,
1251 			   unsigned int *data)
1252 {
1253 	int i;
1254 	int chan = CR_CHAN(insn->chanspec);
1255 
1256 	for (i = 0; i < insn->n; i++)
1257 		data[i] = devpriv->ao_readback[chan];
1258 
1259 	return i;
1260 }
1261 
pci230_ao_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)1262 static int pci230_ao_cmdtest(struct comedi_device *dev,
1263 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
1264 {
1265 	int err = 0;
1266 	unsigned int tmp;
1267 
1268 	/* cmdtest tests a particular command to see if it is valid.
1269 	 * Using the cmdtest ioctl, a user can create a valid cmd
1270 	 * and then have it executes by the cmd ioctl.
1271 	 *
1272 	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
1273 	 * the command passes. */
1274 
1275 	/* Step 1: make sure trigger sources are trivially valid.
1276 	 * "invalid source" returned by comedilib to user mode process
1277 	 * if this fails. */
1278 
1279 	tmp = cmd->start_src;
1280 	cmd->start_src &= TRIG_INT;
1281 	if (!cmd->start_src || tmp != cmd->start_src)
1282 		err++;
1283 
1284 	tmp = cmd->scan_begin_src;
1285 	if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
1286 		/*
1287 		 * For PCI230+ hardware version 2 onwards, allow external
1288 		 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
1289 		 *
1290 		 * FIXME: The permitted scan_begin_src values shouldn't depend
1291 		 * on devpriv->hwver (the detected card's actual hardware
1292 		 * version).  They should only depend on thisboard->min_hwver
1293 		 * (the static capabilities of the configured card).  To fix
1294 		 * it, a new card model, e.g. "pci230+2" would have to be
1295 		 * defined with min_hwver set to 2.  It doesn't seem worth it
1296 		 * for this alone.  At the moment, please consider
1297 		 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
1298 		 * guarantee!
1299 		 */
1300 		cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1301 	} else {
1302 		cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT;
1303 	}
1304 	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1305 		err++;
1306 
1307 	tmp = cmd->convert_src;
1308 	cmd->convert_src &= TRIG_NOW;
1309 	if (!cmd->convert_src || tmp != cmd->convert_src)
1310 		err++;
1311 
1312 	tmp = cmd->scan_end_src;
1313 	cmd->scan_end_src &= TRIG_COUNT;
1314 	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1315 		err++;
1316 
1317 	tmp = cmd->stop_src;
1318 	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1319 	if (!cmd->stop_src || tmp != cmd->stop_src)
1320 		err++;
1321 
1322 	if (err)
1323 		return 1;
1324 
1325 	/* Step 2: make sure trigger sources are unique and mutually compatible
1326 	 * "source conflict" returned by comedilib to user mode process
1327 	 * if this fails. */
1328 
1329 	/* these tests are true if more than one _src bit is set */
1330 	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1331 		err++;
1332 	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1333 		err++;
1334 	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1335 		err++;
1336 	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1337 		err++;
1338 	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1339 		err++;
1340 
1341 	if (err)
1342 		return 2;
1343 
1344 	/* Step 3: make sure arguments are trivially compatible.
1345 	 * "invalid argument" returned by comedilib to user mode process
1346 	 * if this fails. */
1347 
1348 	if (cmd->start_arg != 0) {
1349 		cmd->start_arg = 0;
1350 		err++;
1351 	}
1352 #define MAX_SPEED_AO	8000	/* 8000 ns => 125 kHz */
1353 #define MIN_SPEED_AO	4294967295u	/* 4294967295ns = 4.29s */
1354 			/*- Comedi limit due to unsigned int cmd.  Driver limit
1355 			 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1356 			 * clock) = 65.536s */
1357 
1358 	switch (cmd->scan_begin_src) {
1359 	case TRIG_TIMER:
1360 		if (cmd->scan_begin_arg < MAX_SPEED_AO) {
1361 			cmd->scan_begin_arg = MAX_SPEED_AO;
1362 			err++;
1363 		}
1364 		if (cmd->scan_begin_arg > MIN_SPEED_AO) {
1365 			cmd->scan_begin_arg = MIN_SPEED_AO;
1366 			err++;
1367 		}
1368 		break;
1369 	case TRIG_EXT:
1370 		/* External trigger - for PCI230+ hardware version 2 onwards. */
1371 		/* Trigger number must be 0. */
1372 		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1373 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1374 						      ~CR_FLAGS_MASK);
1375 			err++;
1376 		}
1377 		/* The only flags allowed are CR_EDGE and CR_INVERT.  The
1378 		 * CR_EDGE flag is ignored. */
1379 		if ((cmd->scan_begin_arg
1380 		     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1381 			cmd->scan_begin_arg =
1382 			    COMBINE(cmd->scan_begin_arg, 0,
1383 				    CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
1384 			err++;
1385 		}
1386 		break;
1387 	default:
1388 		if (cmd->scan_begin_arg != 0) {
1389 			cmd->scan_begin_arg = 0;
1390 			err++;
1391 		}
1392 		break;
1393 	}
1394 
1395 	if (cmd->scan_end_arg != cmd->chanlist_len) {
1396 		cmd->scan_end_arg = cmd->chanlist_len;
1397 		err++;
1398 	}
1399 	if (cmd->stop_src == TRIG_NONE) {
1400 		/* TRIG_NONE */
1401 		if (cmd->stop_arg != 0) {
1402 			cmd->stop_arg = 0;
1403 			err++;
1404 		}
1405 	}
1406 
1407 	if (err)
1408 		return 3;
1409 
1410 	/* Step 4: fix up any arguments.
1411 	 * "argument conflict" returned by comedilib to user mode process
1412 	 * if this fails. */
1413 
1414 	if (cmd->scan_begin_src == TRIG_TIMER) {
1415 		tmp = cmd->scan_begin_arg;
1416 		pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1417 					  cmd->flags & TRIG_ROUND_MASK);
1418 		if (tmp != cmd->scan_begin_arg)
1419 			err++;
1420 	}
1421 
1422 	if (err)
1423 		return 4;
1424 
1425 	/* Step 5: check channel list if it exists. */
1426 
1427 	if (cmd->chanlist && cmd->chanlist_len > 0) {
1428 		enum {
1429 			seq_err = (1 << 0),
1430 			range_err = (1 << 1)
1431 		};
1432 		unsigned int errors;
1433 		unsigned int n;
1434 		unsigned int chan, prev_chan;
1435 		unsigned int range, first_range;
1436 
1437 		prev_chan = CR_CHAN(cmd->chanlist[0]);
1438 		first_range = CR_RANGE(cmd->chanlist[0]);
1439 		errors = 0;
1440 		for (n = 1; n < cmd->chanlist_len; n++) {
1441 			chan = CR_CHAN(cmd->chanlist[n]);
1442 			range = CR_RANGE(cmd->chanlist[n]);
1443 			/* Channel numbers must strictly increase. */
1444 			if (chan < prev_chan)
1445 				errors |= seq_err;
1446 
1447 			/* Ranges must be the same. */
1448 			if (range != first_range)
1449 				errors |= range_err;
1450 
1451 			prev_chan = chan;
1452 		}
1453 		if (errors != 0) {
1454 			err++;
1455 			if ((errors & seq_err) != 0) {
1456 				DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1457 					"channel numbers must increase\n",
1458 					dev->minor);
1459 			}
1460 			if ((errors & range_err) != 0) {
1461 				DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1462 					"channels must have the same range\n",
1463 					dev->minor);
1464 			}
1465 		}
1466 	}
1467 
1468 	if (err)
1469 		return 5;
1470 
1471 	return 0;
1472 }
1473 
pci230_ao_inttrig_scan_begin(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1474 static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1475 					struct comedi_subdevice *s,
1476 					unsigned int trig_num)
1477 {
1478 	unsigned long irqflags;
1479 
1480 	if (trig_num != 0)
1481 		return -EINVAL;
1482 
1483 	spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1484 	if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
1485 		/* Perform scan. */
1486 		if (devpriv->hwver < 2) {
1487 			/* Not using DAC FIFO. */
1488 			spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1489 					       irqflags);
1490 			pci230_handle_ao_nofifo(dev, s);
1491 			comedi_event(dev, s);
1492 		} else {
1493 			/* Using DAC FIFO. */
1494 			/* Read DACSWTRIG register to trigger conversion. */
1495 			inw(dev->iobase + PCI230P2_DACSWTRIG);
1496 			spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
1497 					       irqflags);
1498 		}
1499 		/* Delay.  Should driver be responsible for this? */
1500 		/* XXX TODO: See if DAC busy bit can be used. */
1501 		udelay(8);
1502 	}
1503 
1504 	return 1;
1505 }
1506 
pci230_ao_start(struct comedi_device * dev,struct comedi_subdevice * s)1507 static void pci230_ao_start(struct comedi_device *dev,
1508 			    struct comedi_subdevice *s)
1509 {
1510 	struct comedi_async *async = s->async;
1511 	struct comedi_cmd *cmd = &async->cmd;
1512 	unsigned long irqflags;
1513 
1514 	set_bit(AO_CMD_STARTED, &devpriv->state);
1515 	if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1516 		/* An empty acquisition! */
1517 		async->events |= COMEDI_CB_EOA;
1518 		pci230_ao_stop(dev, s);
1519 		comedi_event(dev, s);
1520 	} else {
1521 		if (devpriv->hwver >= 2) {
1522 			/* Using DAC FIFO. */
1523 			unsigned short scantrig;
1524 			int run;
1525 
1526 			/* Preload FIFO data. */
1527 			run = pci230_handle_ao_fifo(dev, s);
1528 			comedi_event(dev, s);
1529 			if (!run) {
1530 				/* Stopped. */
1531 				return;
1532 			}
1533 			/* Set scan trigger source. */
1534 			switch (cmd->scan_begin_src) {
1535 			case TRIG_TIMER:
1536 				scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1537 				break;
1538 			case TRIG_EXT:
1539 				/* Trigger on EXTTRIG/EXTCONVCLK pin. */
1540 				if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1541 					/* +ve edge */
1542 					scantrig = PCI230P2_DAC_TRIG_EXTP;
1543 				} else {
1544 					/* -ve edge */
1545 					scantrig = PCI230P2_DAC_TRIG_EXTN;
1546 				}
1547 				break;
1548 			case TRIG_INT:
1549 				scantrig = PCI230P2_DAC_TRIG_SW;
1550 				break;
1551 			default:
1552 				/* Shouldn't get here. */
1553 				scantrig = PCI230P2_DAC_TRIG_NONE;
1554 				break;
1555 			}
1556 			devpriv->daccon = (devpriv->daccon
1557 					   & ~PCI230P2_DAC_TRIG_MASK) |
1558 			    scantrig;
1559 			outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1560 
1561 		}
1562 		switch (cmd->scan_begin_src) {
1563 		case TRIG_TIMER:
1564 			if (devpriv->hwver < 2) {
1565 				/* Not using DAC FIFO. */
1566 				/* Enable CT1 timer interrupt. */
1567 				spin_lock_irqsave(&devpriv->isr_spinlock,
1568 						  irqflags);
1569 				devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1570 				devpriv->ier |= PCI230_INT_ZCLK_CT1;
1571 				outb(devpriv->ier,
1572 				     devpriv->iobase1 + PCI230_INT_SCE);
1573 				spin_unlock_irqrestore(&devpriv->isr_spinlock,
1574 						       irqflags);
1575 			}
1576 			/* Set CT1 gate high to start counting. */
1577 			outb(GAT_CONFIG(1, GAT_VCC),
1578 			     devpriv->iobase1 + PCI230_ZGAT_SCE);
1579 			break;
1580 		case TRIG_INT:
1581 			async->inttrig = pci230_ao_inttrig_scan_begin;
1582 			break;
1583 		}
1584 		if (devpriv->hwver >= 2) {
1585 			/* Using DAC FIFO.  Enable DAC FIFO interrupt. */
1586 			spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
1587 			devpriv->int_en |= PCI230P2_INT_DAC;
1588 			devpriv->ier |= PCI230P2_INT_DAC;
1589 			outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1590 			spin_unlock_irqrestore(&devpriv->isr_spinlock,
1591 					       irqflags);
1592 		}
1593 	}
1594 }
1595 
pci230_ao_inttrig_start(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)1596 static int pci230_ao_inttrig_start(struct comedi_device *dev,
1597 				   struct comedi_subdevice *s,
1598 				   unsigned int trig_num)
1599 {
1600 	if (trig_num != 0)
1601 		return -EINVAL;
1602 
1603 	s->async->inttrig = NULLFUNC;
1604 	pci230_ao_start(dev, s);
1605 
1606 	return 1;
1607 }
1608 
pci230_ao_cmd(struct comedi_device * dev,struct comedi_subdevice * s)1609 static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1610 {
1611 	unsigned short daccon;
1612 	unsigned int range;
1613 
1614 	/* Get the command. */
1615 	struct comedi_cmd *cmd = &s->async->cmd;
1616 
1617 	if (cmd->scan_begin_src == TRIG_TIMER) {
1618 		/* Claim Z2-CT1. */
1619 		if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
1620 			return -EBUSY;
1621 
1622 	}
1623 
1624 	/* Get number of scans required. */
1625 	if (cmd->stop_src == TRIG_COUNT) {
1626 		devpriv->ao_scan_count = cmd->stop_arg;
1627 		devpriv->ao_continuous = 0;
1628 	} else {
1629 		/* TRIG_NONE, user calls cancel. */
1630 		devpriv->ao_scan_count = 0;
1631 		devpriv->ao_continuous = 1;
1632 	}
1633 
1634 	/* Set range - see analogue output range table; 0 => unipolar 10V,
1635 	 * 1 => bipolar +/-10V range scale */
1636 	range = CR_RANGE(cmd->chanlist[0]);
1637 	devpriv->ao_bipolar = pci230_ao_bipolar[range];
1638 	daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1639 	/* Use DAC FIFO for hardware version 2 onwards. */
1640 	if (devpriv->hwver >= 2) {
1641 		unsigned short dacen;
1642 		unsigned int i;
1643 
1644 		dacen = 0;
1645 		for (i = 0; i < cmd->chanlist_len; i++)
1646 			dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1647 
1648 		/* Set channel scan list. */
1649 		outw(dacen, dev->iobase + PCI230P2_DACEN);
1650 		/*
1651 		 * Enable DAC FIFO.
1652 		 * Set DAC scan source to 'none'.
1653 		 * Set DAC FIFO interrupt trigger level to 'not half full'.
1654 		 * Reset DAC FIFO and clear underrun.
1655 		 *
1656 		 * N.B. DAC FIFO interrupts are currently disabled.
1657 		 */
1658 		daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1659 		    | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1660 		    | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1661 	}
1662 
1663 	/* Set DACCON. */
1664 	outw(daccon, dev->iobase + PCI230_DACCON);
1665 	/* Preserve most of DACCON apart from write-only, transient bits. */
1666 	devpriv->daccon = daccon
1667 	    & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1668 
1669 	if (cmd->scan_begin_src == TRIG_TIMER) {
1670 		/* Set the counter timer 1 to the specified scan frequency. */
1671 		/* cmd->scan_begin_arg is sampling period in ns */
1672 		/* gate it off for now. */
1673 		outb(GAT_CONFIG(1, GAT_GND),
1674 		     devpriv->iobase1 + PCI230_ZGAT_SCE);
1675 		pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1676 					cmd->scan_begin_arg,
1677 					cmd->flags & TRIG_ROUND_MASK);
1678 	}
1679 
1680 	/* N.B. cmd->start_src == TRIG_INT */
1681 	s->async->inttrig = pci230_ao_inttrig_start;
1682 
1683 	return 0;
1684 }
1685 
pci230_ai_check_scan_period(struct comedi_cmd * cmd)1686 static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1687 {
1688 	unsigned int min_scan_period, chanlist_len;
1689 	int err = 0;
1690 
1691 	chanlist_len = cmd->chanlist_len;
1692 	if (cmd->chanlist_len == 0)
1693 		chanlist_len = 1;
1694 
1695 	min_scan_period = chanlist_len * cmd->convert_arg;
1696 	if ((min_scan_period < chanlist_len)
1697 	    || (min_scan_period < cmd->convert_arg)) {
1698 		/* Arithmetic overflow. */
1699 		min_scan_period = UINT_MAX;
1700 		err++;
1701 	}
1702 	if (cmd->scan_begin_arg < min_scan_period) {
1703 		cmd->scan_begin_arg = min_scan_period;
1704 		err++;
1705 	}
1706 
1707 	return !err;
1708 }
1709 
pci230_ai_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)1710 static int pci230_ai_cmdtest(struct comedi_device *dev,
1711 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
1712 {
1713 	int err = 0;
1714 	unsigned int tmp;
1715 
1716 	/* cmdtest tests a particular command to see if it is valid.
1717 	 * Using the cmdtest ioctl, a user can create a valid cmd
1718 	 * and then have it executes by the cmd ioctl.
1719 	 *
1720 	 * cmdtest returns 1,2,3,4,5 or 0, depending on which tests
1721 	 * the command passes. */
1722 
1723 	/* Step 1: make sure trigger sources are trivially valid.
1724 	 * "invalid source" returned by comedilib to user mode process
1725 	 * if this fails. */
1726 
1727 	tmp = cmd->start_src;
1728 	cmd->start_src &= TRIG_NOW | TRIG_INT;
1729 	if (!cmd->start_src || tmp != cmd->start_src)
1730 		err++;
1731 
1732 	tmp = cmd->scan_begin_src;
1733 	/* Unfortunately, we cannot trigger a scan off an external source
1734 	 * on the PCI260 board, since it uses the PPIC0 (DIO) input, which
1735 	 * isn't present on the PCI260.  For PCI260+ we can use the
1736 	 * EXTTRIG/EXTCONVCLK input on pin 17 instead. */
1737 	if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1738 		cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT
1739 		    | TRIG_EXT;
1740 	} else {
1741 		cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1742 	}
1743 	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1744 		err++;
1745 
1746 	tmp = cmd->convert_src;
1747 	cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1748 	if (!cmd->convert_src || tmp != cmd->convert_src)
1749 		err++;
1750 
1751 	tmp = cmd->scan_end_src;
1752 	cmd->scan_end_src &= TRIG_COUNT;
1753 	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1754 		err++;
1755 
1756 	tmp = cmd->stop_src;
1757 	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1758 	if (!cmd->stop_src || tmp != cmd->stop_src)
1759 		err++;
1760 
1761 	if (err)
1762 		return 1;
1763 
1764 	/* Step 2: make sure trigger sources are unique and mutually compatible
1765 	 * "source conflict" returned by comedilib to user mode process
1766 	 * if this fails. */
1767 
1768 	/* these tests are true if more than one _src bit is set */
1769 	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1770 		err++;
1771 	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1772 		err++;
1773 	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1774 		err++;
1775 	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1776 		err++;
1777 	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1778 		err++;
1779 
1780 	/* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1781 	 * set up to generate a fixed number of timed conversion pulses. */
1782 	if ((cmd->scan_begin_src != TRIG_FOLLOW)
1783 	    && (cmd->convert_src != TRIG_TIMER))
1784 		err++;
1785 
1786 	if (err)
1787 		return 2;
1788 
1789 	/* Step 3: make sure arguments are trivially compatible.
1790 	 * "invalid argument" returned by comedilib to user mode process
1791 	 * if this fails. */
1792 
1793 	if (cmd->start_arg != 0) {
1794 		cmd->start_arg = 0;
1795 		err++;
1796 	}
1797 #define MAX_SPEED_AI_SE		3200	/* PCI230 SE:   3200 ns => 312.5 kHz */
1798 #define MAX_SPEED_AI_DIFF	8000	/* PCI230 DIFF: 8000 ns => 125 kHz */
1799 #define MAX_SPEED_AI_PLUS	4000	/* PCI230+:     4000 ns => 250 kHz */
1800 #define MIN_SPEED_AI	4294967295u	/* 4294967295ns = 4.29s */
1801 			/*- Comedi limit due to unsigned int cmd.  Driver limit
1802 			 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1803 			 * clock) = 65.536s */
1804 
1805 	if (cmd->convert_src == TRIG_TIMER) {
1806 		unsigned int max_speed_ai;
1807 
1808 		if (devpriv->hwver == 0) {
1809 			/* PCI230 or PCI260.  Max speed depends whether
1810 			 * single-ended or pseudo-differential. */
1811 			if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1812 				/* Peek analogue reference of first channel. */
1813 				if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
1814 					max_speed_ai = MAX_SPEED_AI_DIFF;
1815 				else
1816 					max_speed_ai = MAX_SPEED_AI_SE;
1817 
1818 			} else {
1819 				/* No channel list.  Assume single-ended. */
1820 				max_speed_ai = MAX_SPEED_AI_SE;
1821 			}
1822 		} else {
1823 			/* PCI230+ or PCI260+. */
1824 			max_speed_ai = MAX_SPEED_AI_PLUS;
1825 		}
1826 
1827 		if (cmd->convert_arg < max_speed_ai) {
1828 			cmd->convert_arg = max_speed_ai;
1829 			err++;
1830 		}
1831 		if (cmd->convert_arg > MIN_SPEED_AI) {
1832 			cmd->convert_arg = MIN_SPEED_AI;
1833 			err++;
1834 		}
1835 	} else if (cmd->convert_src == TRIG_EXT) {
1836 		/*
1837 		 * external trigger
1838 		 *
1839 		 * convert_arg == (CR_EDGE | 0)
1840 		 *                => trigger on +ve edge.
1841 		 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1842 		 *                => trigger on -ve edge.
1843 		 */
1844 		if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1845 			/* Trigger number must be 0. */
1846 			if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1847 				cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1848 							   ~CR_FLAGS_MASK);
1849 				err++;
1850 			}
1851 			/* The only flags allowed are CR_INVERT and CR_EDGE.
1852 			 * CR_EDGE is required. */
1853 			if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1854 			    != CR_EDGE) {
1855 				/* Set CR_EDGE, preserve CR_INVERT. */
1856 				cmd->convert_arg =
1857 				    COMBINE(cmd->start_arg, (CR_EDGE | 0),
1858 					    CR_FLAGS_MASK & ~CR_INVERT);
1859 				err++;
1860 			}
1861 		} else {
1862 			/* Backwards compatibility with previous versions. */
1863 			/* convert_arg == 0 => trigger on -ve edge. */
1864 			/* convert_arg == 1 => trigger on +ve edge. */
1865 			if (cmd->convert_arg > 1) {
1866 				/* Default to trigger on +ve edge. */
1867 				cmd->convert_arg = 1;
1868 				err++;
1869 			}
1870 		}
1871 	} else {
1872 		if (cmd->convert_arg != 0) {
1873 			cmd->convert_arg = 0;
1874 			err++;
1875 		}
1876 	}
1877 
1878 	if (cmd->scan_end_arg != cmd->chanlist_len) {
1879 		cmd->scan_end_arg = cmd->chanlist_len;
1880 		err++;
1881 	}
1882 
1883 	if (cmd->stop_src == TRIG_NONE) {
1884 		if (cmd->stop_arg != 0) {
1885 			cmd->stop_arg = 0;
1886 			err++;
1887 		}
1888 	}
1889 
1890 	if (cmd->scan_begin_src == TRIG_EXT) {
1891 		/* external "trigger" to begin each scan
1892 		 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1893 		 * of CT2 (sample convert trigger is CT2) */
1894 		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1895 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1896 						      ~CR_FLAGS_MASK);
1897 			err++;
1898 		}
1899 		/* The only flag allowed is CR_EDGE, which is ignored. */
1900 		if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1901 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1902 						      CR_FLAGS_MASK & ~CR_EDGE);
1903 			err++;
1904 		}
1905 	} else if (cmd->scan_begin_src == TRIG_TIMER) {
1906 		/* N.B. cmd->convert_arg is also TRIG_TIMER */
1907 		if (!pci230_ai_check_scan_period(cmd))
1908 			err++;
1909 
1910 	} else {
1911 		if (cmd->scan_begin_arg != 0) {
1912 			cmd->scan_begin_arg = 0;
1913 			err++;
1914 		}
1915 	}
1916 
1917 	if (err)
1918 		return 3;
1919 
1920 	/* Step 4: fix up any arguments.
1921 	 * "argument conflict" returned by comedilib to user mode process
1922 	 * if this fails. */
1923 
1924 	if (cmd->convert_src == TRIG_TIMER) {
1925 		tmp = cmd->convert_arg;
1926 		pci230_ns_to_single_timer(&cmd->convert_arg,
1927 					  cmd->flags & TRIG_ROUND_MASK);
1928 		if (tmp != cmd->convert_arg)
1929 			err++;
1930 	}
1931 
1932 	if (cmd->scan_begin_src == TRIG_TIMER) {
1933 		/* N.B. cmd->convert_arg is also TRIG_TIMER */
1934 		tmp = cmd->scan_begin_arg;
1935 		pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1936 					  cmd->flags & TRIG_ROUND_MASK);
1937 		if (!pci230_ai_check_scan_period(cmd)) {
1938 			/* Was below minimum required.  Round up. */
1939 			pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1940 						  TRIG_ROUND_UP);
1941 			pci230_ai_check_scan_period(cmd);
1942 		}
1943 		if (tmp != cmd->scan_begin_arg)
1944 			err++;
1945 	}
1946 
1947 	if (err)
1948 		return 4;
1949 
1950 	/* Step 5: check channel list if it exists. */
1951 
1952 	if (cmd->chanlist && cmd->chanlist_len > 0) {
1953 		enum {
1954 			seq_err = 1 << 0,
1955 			rangepair_err = 1 << 1,
1956 			polarity_err = 1 << 2,
1957 			aref_err = 1 << 3,
1958 			diffchan_err = 1 << 4,
1959 			buggy_chan0_err = 1 << 5
1960 		};
1961 		unsigned int errors;
1962 		unsigned int chan, prev_chan;
1963 		unsigned int range, prev_range;
1964 		unsigned int polarity, prev_polarity;
1965 		unsigned int aref, prev_aref;
1966 		unsigned int subseq_len;
1967 		unsigned int n;
1968 
1969 		subseq_len = 0;
1970 		errors = 0;
1971 		prev_chan = prev_aref = prev_range = prev_polarity = 0;
1972 		for (n = 0; n < cmd->chanlist_len; n++) {
1973 			chan = CR_CHAN(cmd->chanlist[n]);
1974 			range = CR_RANGE(cmd->chanlist[n]);
1975 			aref = CR_AREF(cmd->chanlist[n]);
1976 			polarity = pci230_ai_bipolar[range];
1977 			/* Only the first half of the channels are available if
1978 			 * differential.  (These are remapped in software.  In
1979 			 * hardware, only the even channels are available.) */
1980 			if ((aref == AREF_DIFF)
1981 			    && (chan >= (s->n_chan / 2))) {
1982 				errors |= diffchan_err;
1983 			}
1984 			if (n > 0) {
1985 				/* Channel numbers must strictly increase or
1986 				 * subsequence must repeat exactly. */
1987 				if ((chan <= prev_chan)
1988 				    && (subseq_len == 0)) {
1989 					subseq_len = n;
1990 				}
1991 				if ((subseq_len > 0)
1992 				    && (cmd->chanlist[n] !=
1993 					cmd->chanlist[n % subseq_len])) {
1994 					errors |= seq_err;
1995 				}
1996 				/* Channels must have same AREF. */
1997 				if (aref != prev_aref)
1998 					errors |= aref_err;
1999 
2000 				/* Channel ranges must have same polarity. */
2001 				if (polarity != prev_polarity)
2002 					errors |= polarity_err;
2003 
2004 				/* Single-ended channel pairs must have same
2005 				 * range.  */
2006 				if ((aref != AREF_DIFF)
2007 				    && (((chan ^ prev_chan) & ~1) == 0)
2008 				    && (range != prev_range)) {
2009 					errors |= rangepair_err;
2010 				}
2011 			}
2012 			prev_chan = chan;
2013 			prev_range = range;
2014 			prev_aref = aref;
2015 			prev_polarity = polarity;
2016 		}
2017 		if (subseq_len == 0) {
2018 			/* Subsequence is whole sequence. */
2019 			subseq_len = n;
2020 		}
2021 		/* If channel list is a repeating subsequence, need a whole
2022 		 * number of repeats. */
2023 		if ((n % subseq_len) != 0)
2024 			errors |= seq_err;
2025 
2026 		if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
2027 			/*
2028 			 * Buggy PCI230+ or PCI260+ requires channel 0 to be
2029 			 * (first) in the sequence if the sequence contains
2030 			 * more than one channel.  Hardware versions 1 and 2
2031 			 * have the bug.  There is no hardware version 3.
2032 			 *
2033 			 * Actually, there are two firmwares that report
2034 			 * themselves as hardware version 1 (the boards
2035 			 * have different ADC chips with slightly different
2036 			 * timing requirements, which was supposed to be
2037 			 * invisible to software).  The first one doesn't
2038 			 * seem to have the bug, but the second one
2039 			 * does, and we can't tell them apart!
2040 			 */
2041 			if ((subseq_len > 1)
2042 			    && (CR_CHAN(cmd->chanlist[0]) != 0)) {
2043 				errors |= buggy_chan0_err;
2044 			}
2045 		}
2046 		if (errors != 0) {
2047 			err++;
2048 			if ((errors & seq_err) != 0) {
2049 				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2050 					"channel numbers must increase or "
2051 					"sequence must repeat exactly\n",
2052 					dev->minor);
2053 			}
2054 			if ((errors & rangepair_err) != 0) {
2055 				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2056 					"single-ended channel pairs must "
2057 					"have the same range\n", dev->minor);
2058 			}
2059 			if ((errors & polarity_err) != 0) {
2060 				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2061 					"channel sequence ranges must be all "
2062 					"bipolar or all unipolar\n",
2063 					dev->minor);
2064 			}
2065 			if ((errors & aref_err) != 0) {
2066 				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2067 					"channel sequence analogue references "
2068 					"must be all the same (single-ended "
2069 					"or differential)\n", dev->minor);
2070 			}
2071 			if ((errors & diffchan_err) != 0) {
2072 				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2073 					"differential channel number out of "
2074 					"range 0 to %u\n", dev->minor,
2075 					(s->n_chan / 2) - 1);
2076 			}
2077 			if ((errors & buggy_chan0_err) != 0) {
2078 				/* Use printk instead of DPRINTK here. */
2079 				printk("comedi: comedi%d: amplc_pci230: "
2080 				       "ai_cmdtest: Buggy PCI230+/260+ "
2081 				       "h/w version %u requires first channel "
2082 				       "of multi-channel sequence to be 0 "
2083 				       "(corrected in h/w version 4)\n",
2084 				       dev->minor, devpriv->hwver);
2085 			}
2086 		}
2087 	}
2088 
2089 	if (err)
2090 		return 5;
2091 
2092 	return 0;
2093 }
2094 
pci230_ai_update_fifo_trigger_level(struct comedi_device * dev,struct comedi_subdevice * s)2095 static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
2096 						struct comedi_subdevice *s)
2097 {
2098 	struct comedi_cmd *cmd = &s->async->cmd;
2099 	unsigned int scanlen = cmd->scan_end_arg;
2100 	unsigned int wake;
2101 	unsigned short triglev;
2102 	unsigned short adccon;
2103 
2104 	if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
2105 		/* Wake at end of scan. */
2106 		wake = scanlen - devpriv->ai_scan_pos;
2107 	} else {
2108 		if (devpriv->ai_continuous
2109 		    || (devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL)
2110 		    || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2111 			wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
2112 		} else {
2113 			wake = (devpriv->ai_scan_count * scanlen)
2114 			    - devpriv->ai_scan_pos;
2115 		}
2116 	}
2117 	if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
2118 		triglev = PCI230_ADC_INT_FIFO_HALF;
2119 	} else {
2120 		if ((wake > 1) && (devpriv->hwver > 0)) {
2121 			/* PCI230+/260+ programmable FIFO interrupt level. */
2122 			if (devpriv->adcfifothresh != wake) {
2123 				devpriv->adcfifothresh = wake;
2124 				outw(wake, dev->iobase + PCI230P_ADCFFTH);
2125 			}
2126 			triglev = PCI230P_ADC_INT_FIFO_THRESH;
2127 		} else {
2128 			triglev = PCI230_ADC_INT_FIFO_NEMPTY;
2129 		}
2130 	}
2131 	adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
2132 	if (adccon != devpriv->adccon) {
2133 		devpriv->adccon = adccon;
2134 		outw(adccon, dev->iobase + PCI230_ADCCON);
2135 	}
2136 }
2137 
pci230_ai_inttrig_convert(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)2138 static int pci230_ai_inttrig_convert(struct comedi_device *dev,
2139 				     struct comedi_subdevice *s,
2140 				     unsigned int trig_num)
2141 {
2142 	unsigned long irqflags;
2143 
2144 	if (trig_num != 0)
2145 		return -EINVAL;
2146 
2147 	spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2148 	if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2149 		unsigned int delayus;
2150 
2151 		/* Trigger conversion by toggling Z2-CT2 output.  Finish
2152 		 * with output high. */
2153 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2154 			       I8254_MODE0);
2155 		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2156 			       I8254_MODE1);
2157 		/* Delay.  Should driver be responsible for this?  An
2158 		 * alternative would be to wait until conversion is complete,
2159 		 * but we can't tell when it's complete because the ADC busy
2160 		 * bit has a different meaning when FIFO enabled (and when
2161 		 * FIFO not enabled, it only works for software triggers). */
2162 		if (((devpriv->adccon & PCI230_ADC_IM_MASK)
2163 		     == PCI230_ADC_IM_DIF)
2164 		    && (devpriv->hwver == 0)) {
2165 			/* PCI230/260 in differential mode */
2166 			delayus = 8;
2167 		} else {
2168 			/* single-ended or PCI230+/260+ */
2169 			delayus = 4;
2170 		}
2171 		spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2172 		udelay(delayus);
2173 	} else {
2174 		spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2175 	}
2176 
2177 	return 1;
2178 }
2179 
pci230_ai_inttrig_scan_begin(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)2180 static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
2181 					struct comedi_subdevice *s,
2182 					unsigned int trig_num)
2183 {
2184 	unsigned long irqflags;
2185 	unsigned char zgat;
2186 
2187 	if (trig_num != 0)
2188 		return -EINVAL;
2189 
2190 	spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2191 	if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2192 		/* Trigger scan by waggling CT0 gate source. */
2193 		zgat = GAT_CONFIG(0, GAT_GND);
2194 		outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2195 		zgat = GAT_CONFIG(0, GAT_VCC);
2196 		outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2197 	}
2198 	spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2199 
2200 	return 1;
2201 }
2202 
pci230_ai_start(struct comedi_device * dev,struct comedi_subdevice * s)2203 static void pci230_ai_start(struct comedi_device *dev,
2204 			    struct comedi_subdevice *s)
2205 {
2206 	unsigned long irqflags;
2207 	unsigned short conv;
2208 	struct comedi_async *async = s->async;
2209 	struct comedi_cmd *cmd = &async->cmd;
2210 
2211 	set_bit(AI_CMD_STARTED, &devpriv->state);
2212 	if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2213 		/* An empty acquisition! */
2214 		async->events |= COMEDI_CB_EOA;
2215 		pci230_ai_stop(dev, s);
2216 		comedi_event(dev, s);
2217 	} else {
2218 		/* Enable ADC FIFO trigger level interrupt. */
2219 		spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2220 		devpriv->int_en |= PCI230_INT_ADC;
2221 		devpriv->ier |= PCI230_INT_ADC;
2222 		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2223 		spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2224 
2225 		/* Update conversion trigger source which is currently set
2226 		 * to CT2 output, which is currently stuck high. */
2227 		switch (cmd->convert_src) {
2228 		default:
2229 			conv = PCI230_ADC_TRIG_NONE;
2230 			break;
2231 		case TRIG_TIMER:
2232 			/* Using CT2 output. */
2233 			conv = PCI230_ADC_TRIG_Z2CT2;
2234 			break;
2235 		case TRIG_EXT:
2236 			if ((cmd->convert_arg & CR_EDGE) != 0) {
2237 				if ((cmd->convert_arg & CR_INVERT) == 0) {
2238 					/* Trigger on +ve edge. */
2239 					conv = PCI230_ADC_TRIG_EXTP;
2240 				} else {
2241 					/* Trigger on -ve edge. */
2242 					conv = PCI230_ADC_TRIG_EXTN;
2243 				}
2244 			} else {
2245 				/* Backwards compatibility. */
2246 				if (cmd->convert_arg != 0) {
2247 					/* Trigger on +ve edge. */
2248 					conv = PCI230_ADC_TRIG_EXTP;
2249 				} else {
2250 					/* Trigger on -ve edge. */
2251 					conv = PCI230_ADC_TRIG_EXTN;
2252 				}
2253 			}
2254 			break;
2255 		case TRIG_INT:
2256 			/* Use CT2 output for software trigger due to problems
2257 			 * in differential mode on PCI230/260. */
2258 			conv = PCI230_ADC_TRIG_Z2CT2;
2259 			break;
2260 		}
2261 		devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
2262 		    | conv;
2263 		outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
2264 		if (cmd->convert_src == TRIG_INT)
2265 			async->inttrig = pci230_ai_inttrig_convert;
2266 
2267 		/* Update FIFO interrupt trigger level, which is currently
2268 		 * set to "full".  */
2269 		pci230_ai_update_fifo_trigger_level(dev, s);
2270 		if (cmd->convert_src == TRIG_TIMER) {
2271 			/* Update timer gates. */
2272 			unsigned char zgat;
2273 
2274 			if (cmd->scan_begin_src != TRIG_FOLLOW) {
2275 				/* Conversion timer CT2 needs to be gated by
2276 				 * inverted output of monostable CT2. */
2277 				zgat = GAT_CONFIG(2, GAT_NOUTNM2);
2278 			} else {
2279 				/* Conversion timer CT2 needs to be gated on
2280 				 * continuously. */
2281 				zgat = GAT_CONFIG(2, GAT_VCC);
2282 			}
2283 			outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2284 			if (cmd->scan_begin_src != TRIG_FOLLOW) {
2285 				/* Set monostable CT0 trigger source. */
2286 				switch (cmd->scan_begin_src) {
2287 				default:
2288 					zgat = GAT_CONFIG(0, GAT_VCC);
2289 					break;
2290 				case TRIG_EXT:
2291 					/*
2292 					 * For CT0 on PCI230, the external
2293 					 * trigger (gate) signal comes from
2294 					 * PPC0, which is channel 16 of the DIO
2295 					 * subdevice.  The application needs to
2296 					 * configure this as an input in order
2297 					 * to use it as an external scan
2298 					 * trigger.
2299 					 */
2300 					zgat = GAT_CONFIG(0, GAT_EXT);
2301 					break;
2302 				case TRIG_TIMER:
2303 					/*
2304 					 * Monostable CT0 triggered by rising
2305 					 * edge on inverted output of CT1
2306 					 * (falling edge on CT1).
2307 					 */
2308 					zgat = GAT_CONFIG(0, GAT_NOUTNM2);
2309 					break;
2310 				case TRIG_INT:
2311 					/*
2312 					 * Monostable CT0 is triggered by
2313 					 * inttrig function waggling the CT0
2314 					 * gate source.
2315 					 */
2316 					zgat = GAT_CONFIG(0, GAT_VCC);
2317 					break;
2318 				}
2319 				outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2320 				switch (cmd->scan_begin_src) {
2321 				case TRIG_TIMER:
2322 					/* Scan period timer CT1 needs to be
2323 					 * gated on to start counting. */
2324 					zgat = GAT_CONFIG(1, GAT_VCC);
2325 					outb(zgat, devpriv->iobase1
2326 					     + PCI230_ZGAT_SCE);
2327 					break;
2328 				case TRIG_INT:
2329 					async->inttrig =
2330 					    pci230_ai_inttrig_scan_begin;
2331 					break;
2332 				}
2333 			}
2334 		} else if (cmd->convert_src != TRIG_INT) {
2335 			/* No longer need Z2-CT2. */
2336 			put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
2337 		}
2338 	}
2339 }
2340 
pci230_ai_inttrig_start(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)2341 static int pci230_ai_inttrig_start(struct comedi_device *dev,
2342 				   struct comedi_subdevice *s,
2343 				   unsigned int trig_num)
2344 {
2345 	if (trig_num != 0)
2346 		return -EINVAL;
2347 
2348 	s->async->inttrig = NULLFUNC;
2349 	pci230_ai_start(dev, s);
2350 
2351 	return 1;
2352 }
2353 
pci230_ai_cmd(struct comedi_device * dev,struct comedi_subdevice * s)2354 static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2355 {
2356 	unsigned int i, chan, range, diff;
2357 	unsigned int res_mask;
2358 	unsigned short adccon, adcen;
2359 	unsigned char zgat;
2360 
2361 	/* Get the command. */
2362 	struct comedi_async *async = s->async;
2363 	struct comedi_cmd *cmd = &async->cmd;
2364 
2365 	/*
2366 	 * Determine which shared resources are needed.
2367 	 */
2368 	res_mask = 0;
2369 	/* Need Z2-CT2 to supply a conversion trigger source at a high
2370 	 * logic level, even if not doing timed conversions. */
2371 	res_mask |= (1U << RES_Z2CT2);
2372 	if (cmd->scan_begin_src != TRIG_FOLLOW) {
2373 		/* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2374 		res_mask |= (1U << RES_Z2CT0);
2375 		if (cmd->scan_begin_src == TRIG_TIMER) {
2376 			/* Using Z2-CT1 for scan frequency */
2377 			res_mask |= (1U << RES_Z2CT1);
2378 		}
2379 	}
2380 	/* Claim resources. */
2381 	if (!get_resources(dev, res_mask, OWNER_AICMD))
2382 		return -EBUSY;
2383 
2384 
2385 	/* Get number of scans required. */
2386 	if (cmd->stop_src == TRIG_COUNT) {
2387 		devpriv->ai_scan_count = cmd->stop_arg;
2388 		devpriv->ai_continuous = 0;
2389 	} else {
2390 		/* TRIG_NONE, user calls cancel. */
2391 		devpriv->ai_scan_count = 0;
2392 		devpriv->ai_continuous = 1;
2393 	}
2394 	devpriv->ai_scan_pos = 0;	/* Position within scan. */
2395 
2396 	/* Steps;
2397 	 * - Set channel scan list.
2398 	 * - Set channel gains.
2399 	 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2400 	 *   start conversion source to point to something at a high logic
2401 	 *   level (we use the output of counter/timer 2 for this purpose.
2402 	 * - PAUSE to allow things to settle down.
2403 	 * - Reset the FIFO again because it needs resetting twice and there
2404 	 *   may have been a false conversion trigger on some versions of
2405 	 *   PCI230/260 due to the start conversion source being set to a
2406 	 *   high logic level.
2407 	 * - Enable ADC FIFO level interrupt.
2408 	 * - Set actual conversion trigger source and FIFO interrupt trigger
2409 	 *   level.
2410 	 * - If convert_src is TRIG_TIMER, set up the timers.
2411 	 */
2412 
2413 	adccon = PCI230_ADC_FIFO_EN;
2414 	adcen = 0;
2415 
2416 	if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2417 		/* Differential - all channels must be differential. */
2418 		diff = 1;
2419 		adccon |= PCI230_ADC_IM_DIF;
2420 	} else {
2421 		/* Single ended - all channels must be single-ended. */
2422 		diff = 0;
2423 		adccon |= PCI230_ADC_IM_SE;
2424 	}
2425 
2426 	range = CR_RANGE(cmd->chanlist[0]);
2427 	devpriv->ai_bipolar = pci230_ai_bipolar[range];
2428 	if (devpriv->ai_bipolar)
2429 		adccon |= PCI230_ADC_IR_BIP;
2430 	else
2431 		adccon |= PCI230_ADC_IR_UNI;
2432 
2433 	for (i = 0; i < cmd->chanlist_len; i++) {
2434 		unsigned int gainshift;
2435 
2436 		chan = CR_CHAN(cmd->chanlist[i]);
2437 		range = CR_RANGE(cmd->chanlist[i]);
2438 		if (diff) {
2439 			gainshift = 2 * chan;
2440 			if (devpriv->hwver == 0) {
2441 				/* Original PCI230/260 expects both inputs of
2442 				 * the differential channel to be enabled. */
2443 				adcen |= 3 << gainshift;
2444 			} else {
2445 				/* PCI230+/260+ expects only one input of the
2446 				 * differential channel to be enabled. */
2447 				adcen |= 1 << gainshift;
2448 			}
2449 		} else {
2450 			gainshift = (chan & ~1);
2451 			adcen |= 1 << chan;
2452 		}
2453 		devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2454 		    | (pci230_ai_gain[range] << gainshift);
2455 	}
2456 
2457 	/* Set channel scan list. */
2458 	outw(adcen, dev->iobase + PCI230_ADCEN);
2459 
2460 	/* Set channel gains. */
2461 	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2462 
2463 	/* Set counter/timer 2 output high for use as the initial start
2464 	 * conversion source. */
2465 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2466 
2467 	/* Temporarily use CT2 output as conversion trigger source and
2468 	 * temporarily set FIFO interrupt trigger level to 'full'. */
2469 	adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2470 
2471 	/* Enable and reset FIFO, specify FIFO trigger level full, specify
2472 	 * uni/bip, se/diff, and temporarily set the start conversion source
2473 	 * to CT2 output.  Note that CT2 output is currently high, and this
2474 	 * will produce a false conversion trigger on some versions of the
2475 	 * PCI230/260, but that will be dealt with later. */
2476 	devpriv->adccon = adccon;
2477 	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2478 
2479 	/* Delay */
2480 	/* Failure to include this will result in the first few channels'-worth
2481 	 * of data being corrupt, normally manifesting itself by large negative
2482 	 * voltages. It seems the board needs time to settle between the first
2483 	 * FIFO reset (above) and the second FIFO reset (below). Setting the
2484 	 * channel gains and scan list _before_ the first FIFO reset also
2485 	 * helps, though only slightly. */
2486 	udelay(25);
2487 
2488 	/* Reset FIFO again. */
2489 	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2490 
2491 	if (cmd->convert_src == TRIG_TIMER) {
2492 		/* Set up CT2 as conversion timer, but gate it off for now.
2493 		 * Note, counter/timer output 2 can be monitored on the
2494 		 * connector: PCI230 pin 21, PCI260 pin 18. */
2495 		zgat = GAT_CONFIG(2, GAT_GND);
2496 		outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2497 		/* Set counter/timer 2 to the specified conversion period. */
2498 		pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2499 					cmd->flags & TRIG_ROUND_MASK);
2500 		if (cmd->scan_begin_src != TRIG_FOLLOW) {
2501 			/*
2502 			 * Set up monostable on CT0 output for scan timing.  A
2503 			 * rising edge on the trigger (gate) input of CT0 will
2504 			 * trigger the monostable, causing its output to go low
2505 			 * for the configured period.  The period depends on
2506 			 * the conversion period and the number of conversions
2507 			 * in the scan.
2508 			 *
2509 			 * Set the trigger high before setting up the
2510 			 * monostable to stop it triggering.  The trigger
2511 			 * source will be changed later.
2512 			 */
2513 			zgat = GAT_CONFIG(0, GAT_VCC);
2514 			outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2515 			pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2516 						((uint64_t) cmd->convert_arg
2517 						 * cmd->scan_end_arg),
2518 						TRIG_ROUND_UP);
2519 			if (cmd->scan_begin_src == TRIG_TIMER) {
2520 				/*
2521 				 * Monostable on CT0 will be triggered by
2522 				 * output of CT1 at configured scan frequency.
2523 				 *
2524 				 * Set up CT1 but gate it off for now.
2525 				 */
2526 				zgat = GAT_CONFIG(1, GAT_GND);
2527 				outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2528 				pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2529 							cmd->scan_begin_arg,
2530 							cmd->
2531 							flags &
2532 							TRIG_ROUND_MASK);
2533 			}
2534 		}
2535 	}
2536 
2537 	if (cmd->start_src == TRIG_INT) {
2538 		s->async->inttrig = pci230_ai_inttrig_start;
2539 	} else {
2540 		/* TRIG_NOW */
2541 		pci230_ai_start(dev, s);
2542 	}
2543 
2544 	return 0;
2545 }
2546 
divide_ns(uint64_t ns,unsigned int timebase,unsigned int round_mode)2547 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
2548 			      unsigned int round_mode)
2549 {
2550 	uint64_t div;
2551 	unsigned int rem;
2552 
2553 	div = ns;
2554 	rem = do_div(div, timebase);
2555 	round_mode &= TRIG_ROUND_MASK;
2556 	switch (round_mode) {
2557 	default:
2558 	case TRIG_ROUND_NEAREST:
2559 		div += (rem + (timebase / 2)) / timebase;
2560 		break;
2561 	case TRIG_ROUND_DOWN:
2562 		break;
2563 	case TRIG_ROUND_UP:
2564 		div += (rem + timebase - 1) / timebase;
2565 		break;
2566 	}
2567 	return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
2568 }
2569 
2570 /* Given desired period in ns, returns the required internal clock source
2571  * and gets the initial count. */
pci230_choose_clk_count(uint64_t ns,unsigned int * count,unsigned int round_mode)2572 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
2573 					    unsigned int round_mode)
2574 {
2575 	unsigned int clk_src, cnt;
2576 
2577 	for (clk_src = CLK_10MHZ;; clk_src++) {
2578 		cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
2579 		if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
2580 			break;
2581 
2582 	}
2583 	*count = cnt;
2584 	return clk_src;
2585 }
2586 
pci230_ns_to_single_timer(unsigned int * ns,unsigned int round)2587 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
2588 {
2589 	unsigned int count;
2590 	unsigned int clk_src;
2591 
2592 	clk_src = pci230_choose_clk_count(*ns, &count, round);
2593 	*ns = count * pci230_timebase[clk_src];
2594 	return;
2595 }
2596 
pci230_ct_setup_ns_mode(struct comedi_device * dev,unsigned int ct,unsigned int mode,uint64_t ns,unsigned int round)2597 static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
2598 				    unsigned int mode, uint64_t ns,
2599 				    unsigned int round)
2600 {
2601 	unsigned int clk_src;
2602 	unsigned int count;
2603 
2604 	/* Set mode. */
2605 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
2606 	/* Determine clock source and count. */
2607 	clk_src = pci230_choose_clk_count(ns, &count, round);
2608 	/* Program clock source. */
2609 	outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
2610 	/* Set initial count. */
2611 	if (count >= 65536)
2612 		count = 0;
2613 
2614 	i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
2615 }
2616 
pci230_cancel_ct(struct comedi_device * dev,unsigned int ct)2617 static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
2618 {
2619 	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
2620 		       I8254_MODE1);
2621 	/* Counter ct, 8254 mode 1, initial count not written. */
2622 }
2623 
2624 /* Interrupt handler */
pci230_interrupt(int irq,void * d)2625 static irqreturn_t pci230_interrupt(int irq, void *d)
2626 {
2627 	unsigned char status_int, valid_status_int;
2628 	struct comedi_device *dev = (struct comedi_device *)d;
2629 	struct comedi_subdevice *s;
2630 	unsigned long irqflags;
2631 
2632 	/* Read interrupt status/enable register. */
2633 	status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2634 
2635 	if (status_int == PCI230_INT_DISABLE)
2636 		return IRQ_NONE;
2637 
2638 
2639 	spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2640 	valid_status_int = devpriv->int_en & status_int;
2641 	/* Disable triggered interrupts.
2642 	 * (Only those interrupts that need re-enabling, are, later in the
2643 	 * handler).  */
2644 	devpriv->ier = devpriv->int_en & ~status_int;
2645 	outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2646 	devpriv->intr_running = 1;
2647 	devpriv->intr_cpuid = THISCPU;
2648 	spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2649 
2650 	/*
2651 	 * Check the source of interrupt and handle it.
2652 	 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2653 	 * interrupts.  However, at present (Comedi-0.7.60) does not allow
2654 	 * concurrent execution of commands, instructions or a mixture of the
2655 	 * two.
2656 	 */
2657 
2658 	if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2659 		s = dev->write_subdev;
2660 		pci230_handle_ao_nofifo(dev, s);
2661 		comedi_event(dev, s);
2662 	}
2663 
2664 	if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2665 		s = dev->write_subdev;
2666 		pci230_handle_ao_fifo(dev, s);
2667 		comedi_event(dev, s);
2668 	}
2669 
2670 	if ((valid_status_int & PCI230_INT_ADC) != 0) {
2671 		s = dev->read_subdev;
2672 		pci230_handle_ai(dev, s);
2673 		comedi_event(dev, s);
2674 	}
2675 
2676 	/* Reenable interrupts. */
2677 	spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2678 	if (devpriv->ier != devpriv->int_en) {
2679 		devpriv->ier = devpriv->int_en;
2680 		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2681 	}
2682 	devpriv->intr_running = 0;
2683 	spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2684 
2685 	return IRQ_HANDLED;
2686 }
2687 
pci230_handle_ao_nofifo(struct comedi_device * dev,struct comedi_subdevice * s)2688 static void pci230_handle_ao_nofifo(struct comedi_device *dev,
2689 				    struct comedi_subdevice *s)
2690 {
2691 	short data;
2692 	int i, ret;
2693 	struct comedi_async *async = s->async;
2694 	struct comedi_cmd *cmd = &async->cmd;
2695 
2696 	if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
2697 		return;
2698 
2699 
2700 	for (i = 0; i < cmd->chanlist_len; i++) {
2701 		/* Read sample from Comedi's circular buffer. */
2702 		ret = comedi_buf_get(s->async, &data);
2703 		if (ret == 0) {
2704 			s->async->events |= COMEDI_CB_OVERFLOW;
2705 			pci230_ao_stop(dev, s);
2706 			comedi_error(dev, "AO buffer underrun");
2707 			return;
2708 		}
2709 		/* Write value to DAC. */
2710 		pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
2711 	}
2712 
2713 	async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
2714 	if (!devpriv->ao_continuous) {
2715 		devpriv->ao_scan_count--;
2716 		if (devpriv->ao_scan_count == 0) {
2717 			/* End of acquisition. */
2718 			async->events |= COMEDI_CB_EOA;
2719 			pci230_ao_stop(dev, s);
2720 		}
2721 	}
2722 }
2723 
2724 /* Loads DAC FIFO (if using it) from buffer. */
2725 /* Returns 0 if AO finished due to completion or error, 1 if still going. */
pci230_handle_ao_fifo(struct comedi_device * dev,struct comedi_subdevice * s)2726 static int pci230_handle_ao_fifo(struct comedi_device *dev,
2727 				 struct comedi_subdevice *s)
2728 {
2729 	struct comedi_async *async = s->async;
2730 	struct comedi_cmd *cmd = &async->cmd;
2731 	unsigned int num_scans;
2732 	unsigned int room;
2733 	unsigned short dacstat;
2734 	unsigned int i, n;
2735 	unsigned int bytes_per_scan;
2736 	unsigned int events = 0;
2737 	int running;
2738 
2739 	/* Get DAC FIFO status. */
2740 	dacstat = inw(dev->iobase + PCI230_DACCON);
2741 
2742 	/* Determine number of scans available in buffer. */
2743 	bytes_per_scan = cmd->chanlist_len * sizeof(short);
2744 	num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
2745 	if (!devpriv->ao_continuous) {
2746 		/* Fixed number of scans. */
2747 		if (num_scans > devpriv->ao_scan_count)
2748 			num_scans = devpriv->ao_scan_count;
2749 
2750 		if (devpriv->ao_scan_count == 0) {
2751 			/* End of acquisition. */
2752 			events |= COMEDI_CB_EOA;
2753 		}
2754 	}
2755 	if (events == 0) {
2756 		/* Check for FIFO underrun. */
2757 		if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2758 			comedi_error(dev, "AO FIFO underrun");
2759 			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2760 		}
2761 		/* Check for buffer underrun if FIFO less than half full
2762 		 * (otherwise there will be loads of "DAC FIFO not half full"
2763 		 * interrupts). */
2764 		if ((num_scans == 0)
2765 		    && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
2766 			comedi_error(dev, "AO buffer underrun");
2767 			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2768 		}
2769 	}
2770 	if (events == 0) {
2771 		/* Determine how much room is in the FIFO (in samples). */
2772 		if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
2773 			room = PCI230P2_DAC_FIFOROOM_FULL;
2774 		else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
2775 			room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
2776 		else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
2777 			room = PCI230P2_DAC_FIFOROOM_EMPTY;
2778 		else
2779 			room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
2780 
2781 		/* Convert room to number of scans that can be added. */
2782 		room /= cmd->chanlist_len;
2783 		/* Determine number of scans to process. */
2784 		if (num_scans > room)
2785 			num_scans = room;
2786 
2787 		/* Process scans. */
2788 		for (n = 0; n < num_scans; n++) {
2789 			for (i = 0; i < cmd->chanlist_len; i++) {
2790 				short datum;
2791 
2792 				comedi_buf_get(async, &datum);
2793 				pci230_ao_write_fifo(dev, datum,
2794 						     CR_CHAN(cmd->chanlist[i]));
2795 			}
2796 		}
2797 		events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
2798 		if (!devpriv->ao_continuous) {
2799 			devpriv->ao_scan_count -= num_scans;
2800 			if (devpriv->ao_scan_count == 0) {
2801 				/* All data for the command has been written
2802 				 * to FIFO.  Set FIFO interrupt trigger level
2803 				 * to 'empty'. */
2804 				devpriv->daccon = (devpriv->daccon
2805 						   &
2806 						   ~PCI230P2_DAC_INT_FIFO_MASK)
2807 				    | PCI230P2_DAC_INT_FIFO_EMPTY;
2808 				outw(devpriv->daccon,
2809 				     dev->iobase + PCI230_DACCON);
2810 			}
2811 		}
2812 		/* Check if FIFO underrun occurred while writing to FIFO. */
2813 		dacstat = inw(dev->iobase + PCI230_DACCON);
2814 		if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2815 			comedi_error(dev, "AO FIFO underrun");
2816 			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2817 		}
2818 	}
2819 	if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
2820 	    != 0) {
2821 		/* Stopping AO due to completion or error. */
2822 		pci230_ao_stop(dev, s);
2823 		running = 0;
2824 	} else {
2825 		running = 1;
2826 	}
2827 	async->events |= events;
2828 	return running;
2829 }
2830 
pci230_handle_ai(struct comedi_device * dev,struct comedi_subdevice * s)2831 static void pci230_handle_ai(struct comedi_device *dev,
2832 			     struct comedi_subdevice *s)
2833 {
2834 	unsigned int events = 0;
2835 	unsigned int status_fifo;
2836 	unsigned int i;
2837 	unsigned int todo;
2838 	unsigned int fifoamount;
2839 	struct comedi_async *async = s->async;
2840 	unsigned int scanlen = async->cmd.scan_end_arg;
2841 
2842 	/* Determine number of samples to read. */
2843 	if (devpriv->ai_continuous) {
2844 		todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2845 	} else if (devpriv->ai_scan_count == 0) {
2846 		todo = 0;
2847 	} else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2848 		   || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2849 		todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2850 	} else {
2851 		todo = (devpriv->ai_scan_count * scanlen)
2852 		    - devpriv->ai_scan_pos;
2853 		if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
2854 			todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2855 
2856 	}
2857 
2858 	if (todo == 0)
2859 		return;
2860 
2861 
2862 	fifoamount = 0;
2863 	for (i = 0; i < todo; i++) {
2864 		if (fifoamount == 0) {
2865 			/* Read FIFO state. */
2866 			status_fifo = inw(dev->iobase + PCI230_ADCCON);
2867 
2868 			if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2869 				/* Report error otherwise FIFO overruns will go
2870 				 * unnoticed by the caller. */
2871 				comedi_error(dev, "AI FIFO overrun");
2872 				events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2873 				break;
2874 			} else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2875 				/* FIFO empty. */
2876 				break;
2877 			} else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2878 				/* FIFO half full. */
2879 				fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2880 			} else {
2881 				/* FIFO not empty. */
2882 				if (devpriv->hwver > 0) {
2883 					/* Read PCI230+/260+ ADC FIFO level. */
2884 					fifoamount = inw(dev->iobase
2885 							 + PCI230P_ADCFFLEV);
2886 					if (fifoamount == 0) {
2887 						/* Shouldn't happen. */
2888 						break;
2889 					}
2890 				} else {
2891 					fifoamount = 1;
2892 				}
2893 			}
2894 		}
2895 
2896 		/* Read sample and store in Comedi's circular buffer. */
2897 		if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2898 			events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2899 			comedi_error(dev, "AI buffer overflow");
2900 			break;
2901 		}
2902 		fifoamount--;
2903 		devpriv->ai_scan_pos++;
2904 		if (devpriv->ai_scan_pos == scanlen) {
2905 			/* End of scan. */
2906 			devpriv->ai_scan_pos = 0;
2907 			devpriv->ai_scan_count--;
2908 			async->events |= COMEDI_CB_EOS;
2909 		}
2910 	}
2911 
2912 	if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2913 		/* End of acquisition. */
2914 		events |= COMEDI_CB_EOA;
2915 	} else {
2916 		/* More samples required, tell Comedi to block. */
2917 		events |= COMEDI_CB_BLOCK;
2918 	}
2919 	async->events |= events;
2920 
2921 	if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2922 			      COMEDI_CB_OVERFLOW)) != 0) {
2923 		/* disable hardware conversions */
2924 		pci230_ai_stop(dev, s);
2925 	} else {
2926 		/* update FIFO interrupt trigger level */
2927 		pci230_ai_update_fifo_trigger_level(dev, s);
2928 	}
2929 }
2930 
pci230_ao_stop(struct comedi_device * dev,struct comedi_subdevice * s)2931 static void pci230_ao_stop(struct comedi_device *dev,
2932 			   struct comedi_subdevice *s)
2933 {
2934 	unsigned long irqflags;
2935 	unsigned char intsrc;
2936 	int started;
2937 	struct comedi_cmd *cmd;
2938 
2939 	spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
2940 	started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
2941 	spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
2942 	if (!started)
2943 		return;
2944 
2945 
2946 	cmd = &s->async->cmd;
2947 	if (cmd->scan_begin_src == TRIG_TIMER) {
2948 		/* Stop scan rate generator. */
2949 		pci230_cancel_ct(dev, 1);
2950 	}
2951 
2952 	/* Determine interrupt source. */
2953 	if (devpriv->hwver < 2) {
2954 		/* Not using DAC FIFO.  Using CT1 interrupt. */
2955 		intsrc = PCI230_INT_ZCLK_CT1;
2956 	} else {
2957 		/* Using DAC FIFO interrupt. */
2958 		intsrc = PCI230P2_INT_DAC;
2959 	}
2960 	/* Disable interrupt and wait for interrupt routine to finish running
2961 	 * unless we are called from the interrupt routine. */
2962 	spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2963 	devpriv->int_en &= ~intsrc;
2964 	while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2965 		spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2966 		spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2967 	}
2968 	if (devpriv->ier != devpriv->int_en) {
2969 		devpriv->ier = devpriv->int_en;
2970 		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2971 	}
2972 	spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2973 
2974 	if (devpriv->hwver >= 2) {
2975 		/* Using DAC FIFO.  Reset FIFO, clear underrun error,
2976 		 * disable FIFO. */
2977 		devpriv->daccon &= PCI230_DAC_OR_MASK;
2978 		outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
2979 		     | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
2980 		     dev->iobase + PCI230_DACCON);
2981 	}
2982 
2983 	/* Release resources. */
2984 	put_all_resources(dev, OWNER_AOCMD);
2985 }
2986 
pci230_ao_cancel(struct comedi_device * dev,struct comedi_subdevice * s)2987 static int pci230_ao_cancel(struct comedi_device *dev,
2988 			    struct comedi_subdevice *s)
2989 {
2990 	pci230_ao_stop(dev, s);
2991 	return 0;
2992 }
2993 
pci230_ai_stop(struct comedi_device * dev,struct comedi_subdevice * s)2994 static void pci230_ai_stop(struct comedi_device *dev,
2995 			   struct comedi_subdevice *s)
2996 {
2997 	unsigned long irqflags;
2998 	struct comedi_cmd *cmd;
2999 	int started;
3000 
3001 	spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
3002 	started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
3003 	spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
3004 	if (!started)
3005 		return;
3006 
3007 
3008 	cmd = &s->async->cmd;
3009 	if (cmd->convert_src == TRIG_TIMER) {
3010 		/* Stop conversion rate generator. */
3011 		pci230_cancel_ct(dev, 2);
3012 	}
3013 	if (cmd->scan_begin_src != TRIG_FOLLOW) {
3014 		/* Stop scan period monostable. */
3015 		pci230_cancel_ct(dev, 0);
3016 	}
3017 
3018 	spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
3019 	/* Disable ADC interrupt and wait for interrupt routine to finish
3020 	 * running unless we are called from the interrupt routine. */
3021 	devpriv->int_en &= ~PCI230_INT_ADC;
3022 	while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
3023 		spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
3024 		spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
3025 	}
3026 	if (devpriv->ier != devpriv->int_en) {
3027 		devpriv->ier = devpriv->int_en;
3028 		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
3029 	}
3030 	spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
3031 
3032 	/* Reset FIFO, disable FIFO and set start conversion source to none.
3033 	 * Keep se/diff and bip/uni settings */
3034 	devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
3035 					      | PCI230_ADC_IM_MASK)) |
3036 	    PCI230_ADC_TRIG_NONE;
3037 	outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
3038 	     dev->iobase + PCI230_ADCCON);
3039 
3040 	/* Release resources. */
3041 	put_all_resources(dev, OWNER_AICMD);
3042 }
3043 
pci230_ai_cancel(struct comedi_device * dev,struct comedi_subdevice * s)3044 static int pci230_ai_cancel(struct comedi_device *dev,
3045 			    struct comedi_subdevice *s)
3046 {
3047 	pci230_ai_stop(dev, s);
3048 	return 0;
3049 }
3050 
3051 MODULE_AUTHOR("Comedi http://www.comedi.org");
3052 MODULE_DESCRIPTION("Comedi low-level driver");
3053 MODULE_LICENSE("GPL");
3054