serial2002: Set range for digital inputs and outputs...
[comedi.git] / comedi / drivers / rtd520.c
1 /*
2     comedi/drivers/rtd520.c
3     Comedi driver for Real Time Devices (RTD) PCI4520/DM7520
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2001 David A. Schleef <ds@schleef.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 /*
23 Driver: rtd520
24 Description: Real Time Devices PCI4520/DM7520
25 Author: Dan Christian
26 Devices: [Real Time Devices] DM7520HR-1 (rtd520), DM7520HR-8,
27   PCI4520, PCI4520-8
28 Status: Works.  Only tested on DM7520-8.  Not SMP safe.
29
30 Configuration options:
31   [0] - PCI bus of device (optional)
32           If bus/slot is not specified, the first available PCI
33           device will be used.
34   [1] - PCI slot of device (optional)
35 */
36 /*
37     Created by Dan Christian, NASA Ames Research Center.
38
39     The PCI4520 is a PCI card.  The DM7520 is a PC/104-plus card.
40     Both have:
41     8/16 12 bit ADC with FIFO and channel gain table
42     8 bits high speed digital out (for external MUX) (or 8 in or 8 out)
43     8 bits high speed digital in with FIFO and interrupt on change (or 8 IO)
44     2 12 bit DACs with FIFOs
45     2 bits output
46     2 bits input
47     bus mastering DMA
48     timers: ADC sample, pacer, burst, about, delay, DA1, DA2
49     sample counter
50     3 user timer/counters (8254)
51     external interrupt
52
53     The DM7520 has slightly fewer features (fewer gain steps).
54
55     These boards can support external multiplexors and multi-board
56     synchronization, but this driver doesn't support that.
57
58     Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm
59     Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf
60     Example source: http://www.rtdusa.com/examples/dm/dm7520.zip
61     Call them and ask for the register level manual.
62     PCI chip: http://www.plxtech.com/products/toolbox/9080.htm
63
64     Notes:
65     This board is memory mapped.  There is some IO stuff, but it isn't needed.
66
67     I use a pretty loose naming style within the driver (rtd_blah).
68     All externally visible names should be rtd520_blah.
69     I use camelCase for structures (and inside them).
70     I may also use upper CamelCase for function names (old habit).
71
72     This board is somewhat related to the RTD PCI4400 board.
73
74     I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and
75     das1800, since they have the best documented code.  Driver
76     cb_pcidas64.c uses the same DMA controller.
77
78     As far as I can tell, the About interrupt doesnt work if Sample is
79     also enabled.  It turns out that About really isn't needed, since
80     we always count down samples read.
81
82     There was some timer/counter code, but it didn't follow the right API.
83
84 */
85
86 /*
87   driver status:
88
89   Analog-In supports instruction and command mode.
90
91   With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2
92   (single channel, 64K read buffer).  I get random system lockups when
93   using DMA with ALI-15xx based systems.  I haven't been able to test
94   any other chipsets.  The lockups happen soon after the start of an
95   acquistion, not in the middle of a long run.
96
97   Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2
98   (with a 256K read buffer).
99
100   Digital-IO and Analog-Out only support instruction mode.
101
102 */
103
104 #include <linux/comedidev.h>
105 #include <linux/delay.h>
106
107 #include "comedi_pci.h"
108
109 #define DRV_NAME "rtd520"
110
111 /*======================================================================
112   Driver specific stuff (tunable)
113 ======================================================================*/
114 /* Enable this to test the new DMA support. You may get hard lock ups */
115 /*#define USE_DMA*/
116
117 /* We really only need 2 buffers.  More than that means being much
118    smarter about knowing which ones are full. */
119 #define DMA_CHAIN_COUNT 2       /* max DMA segments/buffers in a ring (min 2) */
120
121 /* Target period for periodic transfers.  This sets the user read latency. */
122 /* Note: There are certain rates where we give this up and transfer 1/2 FIFO */
123 /* If this is too low, efficiency is poor */
124 #define TRANS_TARGET_PERIOD 10000000    /* 10 ms (in nanoseconds) */
125
126 /* Set a practical limit on how long a list to support (affects memory use) */
127 /* The board support a channel list up to the FIFO length (1K or 8K) */
128 #define RTD_MAX_CHANLIST        128     /* max channel list that we allow */
129
130 /* tuning for ai/ao instruction done polling */
131 #ifdef FAST_SPIN
132 #define WAIT_QUIETLY            /* as nothing, spin on done bit */
133 #define RTD_ADC_TIMEOUT 66000   /* 2 msec at 33mhz bus rate */
134 #define RTD_DAC_TIMEOUT 66000
135 #define RTD_DMA_TIMEOUT 33000   /* 1 msec */
136 #else
137 /* by delaying, power and electrical noise are reduced somewhat */
138 #define WAIT_QUIETLY    comedi_udelay (1)
139 #define RTD_ADC_TIMEOUT 2000    /* in usec */
140 #define RTD_DAC_TIMEOUT 2000    /* in usec */
141 #define RTD_DMA_TIMEOUT 1000    /* in usec */
142 #endif
143
144 /*======================================================================
145   Board specific stuff
146 ======================================================================*/
147
148 /* registers  */
149 #define PCI_VENDOR_ID_RTD       0x1435
150 /*
151   The board has three memory windows: las0, las1, and lcfg (the PCI chip)
152   Las1 has the data and can be burst DMAed 32bits at a time.
153 */
154 #define LCFG_PCIINDEX   0
155 /* PCI region 1 is a 256 byte IO space mapping.  Use??? */
156 #define LAS0_PCIINDEX   2       /* PCI memory resources */
157 #define LAS1_PCIINDEX   3
158 #define LCFG_PCISIZE    0x100
159 #define LAS0_PCISIZE    0x200
160 #define LAS1_PCISIZE    0x10
161
162 #define RTD_CLOCK_RATE  8000000 /* 8Mhz onboard clock */
163 #define RTD_CLOCK_BASE  125     /* clock period in ns */
164
165 /* Note: these speed are slower than the spec, but fit the counter resolution*/
166 #define RTD_MAX_SPEED   1625    /* when sampling, in nanoseconds */
167 /* max speed if we don't have to wait for settling */
168 #define RTD_MAX_SPEED_1 875     /* if single channel, in nanoseconds */
169
170 #define RTD_MIN_SPEED   2097151875      /* (24bit counter) in nanoseconds */
171 /* min speed when only 1 channel (no burst counter) */
172 #define RTD_MIN_SPEED_1 5000000 /* 200Hz, in nanoseconds */
173
174 #include "rtd520.h"
175 #include "plx9080.h"
176
177 /* Setup continuous ring of 1/2 FIFO transfers.  See RTD manual p91 */
178 #define DMA_MODE_BITS (\
179                        PLX_LOCAL_BUS_16_WIDE_BITS \
180                        | PLX_DMA_EN_READYIN_BIT \
181                        | PLX_DMA_LOCAL_BURST_EN_BIT \
182                        | PLX_EN_CHAIN_BIT \
183                        | PLX_DMA_INTR_PCI_BIT \
184                        | PLX_LOCAL_ADDR_CONST_BIT \
185                        | PLX_DEMAND_MODE_BIT)
186
187 #define DMA_TRANSFER_BITS (\
188 /* descriptors in PCI memory*/  PLX_DESC_IN_PCI_BIT \
189 /* interrupt at end of block */ | PLX_INTR_TERM_COUNT \
190 /* from board to PCI */         | PLX_XFER_LOCAL_TO_PCI)
191
192 /*======================================================================
193   Comedi specific stuff
194 ======================================================================*/
195
196 /*
197   The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128)
198 */
199 static const comedi_lrange rtd_ai_7520_range = { 18, {
200                         /* +-5V input range gain steps */
201                         BIP_RANGE(5.0),
202                         BIP_RANGE(5.0 / 2),
203                         BIP_RANGE(5.0 / 4),
204                         BIP_RANGE(5.0 / 8),
205                         BIP_RANGE(5.0 / 16),
206                         BIP_RANGE(5.0 / 32),
207                         /* +-10V input range gain steps */
208                         BIP_RANGE(10.0),
209                         BIP_RANGE(10.0 / 2),
210                         BIP_RANGE(10.0 / 4),
211                         BIP_RANGE(10.0 / 8),
212                         BIP_RANGE(10.0 / 16),
213                         BIP_RANGE(10.0 / 32),
214                         /* +10V input range gain steps */
215                         UNI_RANGE(10.0),
216                         UNI_RANGE(10.0 / 2),
217                         UNI_RANGE(10.0 / 4),
218                         UNI_RANGE(10.0 / 8),
219                         UNI_RANGE(10.0 / 16),
220                         UNI_RANGE(10.0 / 32),
221
222         }
223 };
224
225 /* PCI4520 has two more gains (6 more entries) */
226 static const comedi_lrange rtd_ai_4520_range = { 24, {
227                         /* +-5V input range gain steps */
228                         BIP_RANGE(5.0),
229                         BIP_RANGE(5.0 / 2),
230                         BIP_RANGE(5.0 / 4),
231                         BIP_RANGE(5.0 / 8),
232                         BIP_RANGE(5.0 / 16),
233                         BIP_RANGE(5.0 / 32),
234                         BIP_RANGE(5.0 / 64),
235                         BIP_RANGE(5.0 / 128),
236                         /* +-10V input range gain steps */
237                         BIP_RANGE(10.0),
238                         BIP_RANGE(10.0 / 2),
239                         BIP_RANGE(10.0 / 4),
240                         BIP_RANGE(10.0 / 8),
241                         BIP_RANGE(10.0 / 16),
242                         BIP_RANGE(10.0 / 32),
243                         BIP_RANGE(10.0 / 64),
244                         BIP_RANGE(10.0 / 128),
245                         /* +10V input range gain steps */
246                         UNI_RANGE(10.0),
247                         UNI_RANGE(10.0 / 2),
248                         UNI_RANGE(10.0 / 4),
249                         UNI_RANGE(10.0 / 8),
250                         UNI_RANGE(10.0 / 16),
251                         UNI_RANGE(10.0 / 32),
252                         UNI_RANGE(10.0 / 64),
253                         UNI_RANGE(10.0 / 128),
254         }
255 };
256
257 /* Table order matches range values */
258 static const comedi_lrange rtd_ao_range = { 4, {
259                         RANGE(0, 5),
260                         RANGE(0, 10),
261                         RANGE(-5, 5),
262                         RANGE(-10, 10),
263         }
264 };
265
266 /*
267   Board descriptions
268  */
269 typedef struct rtdBoard_struct {
270         const char *name;       /* must be first */
271         int device_id;
272         int aiChans;
273         int aiBits;
274         int aiMaxGain;
275         int range10Start;       /* start of +-10V range */
276         int rangeUniStart;      /* start of +10V range */
277 } rtdBoard;
278
279 static const rtdBoard rtd520Boards[] = {
280         {
281               name:     "DM7520",
282               device_id:0x7520,
283               aiChans:  16,
284               aiBits:   12,
285               aiMaxGain:32,
286               range10Start:6,
287               rangeUniStart:12,
288                 },
289         {
290               name:     "PCI4520",
291               device_id:0x4520,
292               aiChans:  16,
293               aiBits:   12,
294               aiMaxGain:128,
295               range10Start:8,
296               rangeUniStart:16,
297                 },
298 };
299
300 static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
301         {PCI_VENDOR_ID_RTD, 0x7520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
302         {PCI_VENDOR_ID_RTD, 0x4520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
303         {0}
304 };
305
306 MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
307
308 /*
309  * Useful for shorthand access to the particular board structure
310  */
311 #define thisboard ((const rtdBoard *)dev->board_ptr)
312
313 /*
314    This structure is for data unique to this hardware driver.
315    This is also unique for each board in the system.
316 */
317 typedef struct {
318         /* memory mapped board structures */
319         void *las0;
320         void *las1;
321         void *lcfg;
322
323         unsigned long intCount; /* interrupt count */
324         long aiCount;           /* total transfer size (samples) */
325         int transCount;         /* # to tranfer data. 0->1/2FIFO */
326         int flags;              /* flag event modes */
327
328         /* PCI device info */
329         struct pci_dev *pci_dev;
330         int got_regions;        /* non-zero if PCI regions owned */
331
332         /* channel list info */
333         /* chanBipolar tracks whether a channel is bipolar (and needs +2048) */
334         unsigned char chanBipolar[RTD_MAX_CHANLIST / 8];        /* bit array */
335
336         /* read back data */
337         lsampl_t aoValue[2];    /* Used for AO read back */
338
339         /* timer gate (when enabled) */
340         u8 utcGate[4];          /* 1 extra allows simple range check */
341
342         /* shadow registers affect other registers, but cant be read back */
343         /* The macros below update these on writes */
344         u16 intMask;            /* interrupt mask */
345         u16 intClearMask;       /* interrupt clear mask */
346         u8 utcCtrl[4];          /* crtl mode for 3 utc + read back */
347         u8 dioStatus;           /* could be read back (dio0Ctrl) */
348 #ifdef USE_DMA
349         /* Always DMA 1/2 FIFO.  Buffer (dmaBuff?) is (at least) twice that size.
350            After transferring, interrupt processes 1/2 FIFO and passes to comedi */
351         s16 dma0Offset;         /* current processing offset (0, 1/2) */
352         uint16_t *dma0Buff[DMA_CHAIN_COUNT];    /* DMA buffers (for ADC) */
353         dma_addr_t dma0BuffPhysAddr[DMA_CHAIN_COUNT];   /* physical addresses */
354         struct plx_dma_desc *dma0Chain; /* DMA descriptor ring for dmaBuff */
355         dma_addr_t dma0ChainPhysAddr;   /* physical addresses */
356         /* shadow registers */
357         u8 dma0Control;
358         u8 dma1Control;
359 #endif                          /* USE_DMA */
360         unsigned fifoLen;
361 } rtdPrivate;
362
363 /* bit defines for "flags" */
364 #define SEND_EOS        0x01    /* send End Of Scan events */
365 #define DMA0_ACTIVE     0x02    /* DMA0 is active */
366 #define DMA1_ACTIVE     0x04    /* DMA1 is active */
367
368 /* Macros for accessing channel list bit array */
369 #define CHAN_ARRAY_TEST(array,index) \
370         (((array)[(index)/8] >> ((index) & 0x7)) & 0x1)
371 #define CHAN_ARRAY_SET(array,index) \
372         (((array)[(index)/8] |= 1 << ((index) & 0x7)))
373 #define CHAN_ARRAY_CLEAR(array,index) \
374         (((array)[(index)/8] &= ~(1 << ((index) & 0x7))))
375
376 /*
377  * most drivers define the following macro to make it easy to
378  * access the private structure.
379  */
380 #define devpriv ((rtdPrivate *)dev->private)
381
382 /* Macros to access registers */
383
384 /* Reset board */
385 #define RtdResetBoard(dev) \
386     writel (0, devpriv->las0+LAS0_BOARD_RESET)
387
388 /* Reset channel gain table read pointer */
389 #define RtdResetCGT(dev) \
390     writel (0, devpriv->las0+LAS0_CGT_RESET)
391
392 /* Reset channel gain table read and write pointers */
393 #define RtdClearCGT(dev) \
394     writel (0, devpriv->las0+LAS0_CGT_CLEAR)
395
396 /* Reset channel gain table read and write pointers */
397 #define RtdEnableCGT(dev,v) \
398     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)
399
400 /* Write channel gain table entry */
401 #define RtdWriteCGTable(dev,v) \
402     writel (v, devpriv->las0+LAS0_CGT_WRITE)
403
404 /* Write Channel Gain Latch */
405 #define RtdWriteCGLatch(dev,v) \
406     writel (v, devpriv->las0+LAS0_CGL_WRITE)
407
408 /* Reset ADC FIFO */
409 #define RtdAdcClearFifo(dev) \
410     writel (0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)
411
412 /* Set ADC start conversion source select (write only) */
413 #define RtdAdcConversionSource(dev,v) \
414     writel (v, devpriv->las0+LAS0_ADC_CONVERSION)
415
416 /* Set burst start source select (write only) */
417 #define RtdBurstStartSource(dev,v) \
418     writel (v, devpriv->las0+LAS0_BURST_START)
419
420 /* Set Pacer start source select (write only) */
421 #define RtdPacerStartSource(dev,v) \
422     writel (v, devpriv->las0+LAS0_PACER_START)
423
424 /* Set Pacer stop source select (write only) */
425 #define RtdPacerStopSource(dev,v) \
426     writel (v, devpriv->las0+LAS0_PACER_STOP)
427
428 /* Set Pacer clock source select (write only) 0=external 1=internal */
429 #define RtdPacerClockSource(dev,v) \
430     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)
431
432 /* Set sample counter source select (write only) */
433 #define RtdAdcSampleCounterSource(dev,v) \
434     writel (v, devpriv->las0+LAS0_ADC_SCNT_SRC)
435
436 /* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */
437 #define RtdPacerTriggerMode(dev,v) \
438     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)
439
440 /* Set About counter stop enable (write only) */
441 #define RtdAboutStopEnable(dev,v) \
442     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)
443
444 /* Set external trigger polarity (write only) 0=positive edge, 1=negative */
445 #define RtdTriggerPolarity(dev,v) \
446     writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)
447
448 /* Start single ADC conversion */
449 #define RtdAdcStart(dev) \
450     writew (0, devpriv->las0+LAS0_ADC)
451
452 /* Read one ADC data value (12bit (with sign extend) as 16bit) */
453 /* Note: matches what DMA would get.  Actual value >> 3 */
454 #define RtdAdcFifoGet(dev) \
455     readw (devpriv->las1+LAS1_ADC_FIFO)
456
457 /* Read two ADC data values (DOESNT WORK) */
458 #define RtdAdcFifoGet2(dev) \
459     readl (devpriv->las1+LAS1_ADC_FIFO)
460
461 /* FIFO status */
462 #define RtdFifoStatus(dev) \
463     readl (devpriv->las0+LAS0_ADC)
464
465 /* pacer start/stop read=start, write=stop*/
466 #define RtdPacerStart(dev) \
467     readl (devpriv->las0+LAS0_PACER)
468 #define RtdPacerStop(dev) \
469     writel (0, devpriv->las0+LAS0_PACER)
470
471 /* Interrupt status */
472 #define RtdInterruptStatus(dev) \
473     readw (devpriv->las0+LAS0_IT)
474
475 /* Interrupt mask */
476 #define RtdInterruptMask(dev,v) \
477     writew ((devpriv->intMask = (v)),devpriv->las0+LAS0_IT)
478
479 /* Interrupt status clear (only bits set in mask) */
480 #define RtdInterruptClear(dev) \
481     readw (devpriv->las0+LAS0_CLEAR)
482
483 /* Interrupt clear mask */
484 #define RtdInterruptClearMask(dev,v) \
485     writew ((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)
486
487 /* Interrupt overrun status */
488 #define RtdInterruptOverrunStatus(dev) \
489     readl (devpriv->las0+LAS0_OVERRUN)
490
491 /* Interrupt overrun clear */
492 #define RtdInterruptOverrunClear(dev) \
493     writel (0, devpriv->las0+LAS0_OVERRUN)
494
495 /* Pacer counter, 24bit */
496 #define RtdPacerCount(dev) \
497     readl (devpriv->las0+LAS0_PCLK)
498 #define RtdPacerCounter(dev,v) \
499     writel ((v) & 0xffffff,devpriv->las0+LAS0_PCLK)
500
501 /* Burst counter, 10bit */
502 #define RtdBurstCount(dev) \
503     readl (devpriv->las0+LAS0_BCLK)
504 #define RtdBurstCounter(dev,v) \
505     writel ((v) & 0x3ff,devpriv->las0+LAS0_BCLK)
506
507 /* Delay counter, 16bit */
508 #define RtdDelayCount(dev) \
509     readl (devpriv->las0+LAS0_DCLK)
510 #define RtdDelayCounter(dev,v) \
511     writel ((v) & 0xffff, devpriv->las0+LAS0_DCLK)
512
513 /* About counter, 16bit */
514 #define RtdAboutCount(dev) \
515     readl (devpriv->las0+LAS0_ACNT)
516 #define RtdAboutCounter(dev,v) \
517     writel ((v) & 0xffff, devpriv->las0+LAS0_ACNT)
518
519 /* ADC sample counter, 10bit */
520 #define RtdAdcSampleCount(dev) \
521     readl (devpriv->las0+LAS0_ADC_SCNT)
522 #define RtdAdcSampleCounter(dev,v) \
523     writel ((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)
524
525 /* User Timer/Counter (8254) */
526 #define RtdUtcCounterGet(dev,n) \
527     readb (devpriv->las0 \
528         + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
529
530 #define RtdUtcCounterPut(dev,n,v) \
531     writeb ((v) & 0xff, devpriv->las0 \
532         + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
533
534 /* Set UTC (8254) control byte  */
535 #define RtdUtcCtrlPut(dev,n,v) \
536     writeb (devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \
537       devpriv->las0 + LAS0_UTC_CTRL)
538
539 /* Set UTCn clock source (write only) */
540 #define RtdUtcClockSource(dev,n,v) \
541     writew (v, devpriv->las0 \
542         + ((n <= 0) ? LAS0_UTC0_CLOCK : \
543            ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))
544
545 /* Set UTCn gate source (write only) */
546 #define RtdUtcGateSource(dev,n,v) \
547     writew (v, devpriv->las0 \
548         + ((n <= 0) ? LAS0_UTC0_GATE : \
549            ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))
550
551 /* User output N source select (write only) */
552 #define RtdUsrOutSource(dev,n,v) \
553     writel (v,devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
554
555 /* Digital IO */
556 #define RtdDio0Read(dev) \
557     (readw (devpriv->las0+LAS0_DIO0) & 0xff)
558 #define RtdDio0Write(dev,v) \
559     writew ((v) & 0xff, devpriv->las0+LAS0_DIO0)
560
561 #define RtdDio1Read(dev) \
562     (readw (devpriv->las0+LAS0_DIO1) & 0xff)
563 #define RtdDio1Write(dev,v) \
564     writew ((v) & 0xff, devpriv->las0+LAS0_DIO1)
565
566 #define RtdDioStatusRead(dev) \
567     (readw (devpriv->las0+LAS0_DIO_STATUS) & 0xff)
568 #define RtdDioStatusWrite(dev,v) \
569     writew ((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)
570
571 #define RtdDio0CtrlRead(dev) \
572     (readw (devpriv->las0+LAS0_DIO0_CTRL) & 0xff)
573 #define RtdDio0CtrlWrite(dev,v) \
574     writew ((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)
575
576 /* Digital to Analog converter */
577 /* Write one data value (sign + 12bit + marker bits) */
578 /* Note: matches what DMA would put.  Actual value << 3 */
579 #define RtdDacFifoPut(dev,n,v) \
580     writew ((v), devpriv->las1 +(((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
581
582 /* Start single DAC conversion */
583 #define RtdDacUpdate(dev,n) \
584     writew (0, devpriv->las0 +(((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))
585
586 /* Start single DAC conversion on both DACs */
587 #define RtdDacBothUpdate(dev) \
588     writew (0, devpriv->las0+LAS0_DAC)
589
590 /* Set DAC output type and range */
591 #define RtdDacRange(dev,n,v) \
592     writew ((v) & 7, devpriv->las0 \
593         +(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))
594
595 /* Reset DAC FIFO */
596 #define RtdDacClearFifo(dev,n) \
597     writel (0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
598
599 /* Set source for DMA 0 (write only, shadow?) */
600 #define RtdDma0Source(dev,n) \
601     writel ((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)
602
603 /* Set source for DMA 1 (write only, shadow?) */
604 #define RtdDma1Source(dev,n) \
605     writel ((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)
606
607 /* Reset board state for DMA 0 */
608 #define RtdDma0Reset(dev) \
609     writel (0, devpriv->las0+LAS0_DMA0_RESET)
610
611 /* Reset board state for DMA 1 */
612 #define RtdDma1Reset(dev) \
613     writel (0, devpriv->las0+LAS0_DMA1_SRC)
614
615 /* PLX9080 interrupt mask and status */
616 #define RtdPlxInterruptRead(dev) \
617     readl (devpriv->lcfg+LCFG_ITCSR)
618 #define RtdPlxInterruptWrite(dev,v) \
619     writel (v, devpriv->lcfg+LCFG_ITCSR)
620
621 /* Set  mode for DMA 0 */
622 #define RtdDma0Mode(dev,m) \
623     writel ((m), devpriv->lcfg+LCFG_DMAMODE0)
624
625 /* Set PCI address for DMA 0 */
626 #define RtdDma0PciAddr(dev,a) \
627     writel ((a), devpriv->lcfg+LCFG_DMAPADR0)
628
629 /* Set local address for DMA 0 */
630 #define RtdDma0LocalAddr(dev,a) \
631     writel ((a), devpriv->lcfg+LCFG_DMALADR0)
632
633 /* Set byte count for DMA 0 */
634 #define RtdDma0Count(dev,c) \
635     writel ((c), devpriv->lcfg+LCFG_DMASIZ0)
636
637 /* Set next descriptor for DMA 0 */
638 #define RtdDma0Next(dev,a) \
639     writel ((a), devpriv->lcfg+LCFG_DMADPR0)
640
641 /* Set  mode for DMA 1 */
642 #define RtdDma1Mode(dev,m) \
643     writel ((m), devpriv->lcfg+LCFG_DMAMODE1)
644
645 /* Set PCI address for DMA 1 */
646 #define RtdDma1PciAddr(dev,a) \
647     writel ((a), devpriv->lcfg+LCFG_DMAADR1)
648
649 /* Set local address for DMA 1 */
650 #define RtdDma1LocalAddr(dev,a) \
651     writel ((a), devpriv->lcfg+LCFG_DMALADR1)
652
653 /* Set byte count for DMA 1 */
654 #define RtdDma1Count(dev,c) \
655     writel ((c), devpriv->lcfg+LCFG_DMASIZ1)
656
657 /* Set next descriptor for DMA 1 */
658 #define RtdDma1Next(dev,a) \
659     writel ((a), devpriv->lcfg+LCFG_DMADPR1)
660
661 /* Set control for DMA 0 (write only, shadow?) */
662 #define RtdDma0Control(dev,n) \
663     writeb (devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)
664
665 /* Get status for DMA 0 */
666 #define RtdDma0Status(dev) \
667     readb (devpriv->lcfg+LCFG_DMACSR0)
668
669 /* Set control for DMA 1 (write only, shadow?) */
670 #define RtdDma1Control(dev,n) \
671     writeb (devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)
672
673 /* Get status for DMA 1 */
674 #define RtdDma1Status(dev) \
675     readb (devpriv->lcfg+LCFG_DMACSR1)
676
677 /*
678  * The comedi_driver structure tells the Comedi core module
679  * which functions to call to configure/deconfigure (attac/detach)
680  * the board, and also about the kernel module that contains
681  * the device code.
682  */
683 static int rtd_attach(comedi_device * dev, comedi_devconfig * it);
684 static int rtd_detach(comedi_device * dev);
685
686 static comedi_driver rtd520Driver = {
687       driver_name: DRV_NAME,
688       module:THIS_MODULE,
689       attach:rtd_attach,
690       detach:rtd_detach,
691 };
692
693 static int rtd_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
694         comedi_insn * insn, lsampl_t * data);
695 static int rtd_ao_winsn(comedi_device * dev, comedi_subdevice * s,
696         comedi_insn * insn, lsampl_t * data);
697 static int rtd_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
698         comedi_insn * insn, lsampl_t * data);
699 static int rtd_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
700         comedi_insn * insn, lsampl_t * data);
701 static int rtd_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
702         comedi_insn * insn, lsampl_t * data);
703 static int rtd_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
704         comedi_cmd * cmd);
705 static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s);
706 static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s);
707 //static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s);
708 static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
709 static irqreturn_t rtd_interrupt(int irq, void *d PT_REGS_ARG);
710 static int rtd520_probe_fifo_depth(comedi_device *dev);
711
712 /*
713  * Attach is called by the Comedi core to configure the driver
714  * for a particular board.  If you specified a board_name array
715  * in the driver structure, dev->board_ptr contains that
716  * address.
717  */
718 static int rtd_attach(comedi_device * dev, comedi_devconfig * it)
719 {                               /* board name and options flags */
720         comedi_subdevice *s;
721         struct pci_dev *pcidev;
722         int ret;
723         resource_size_t physLas0;       /* configuation */
724         resource_size_t physLas1;       /* data area */
725         resource_size_t physLcfg;       /* PLX9080 */
726 #ifdef USE_DMA
727         int index;
728 #endif
729
730         printk("comedi%d: rtd520 attaching.\n", dev->minor);
731
732 #if defined (CONFIG_COMEDI_DEBUG) && defined (USE_DMA)
733         /* You can set this a load time: modprobe comedi comedi_debug=1 */
734         if (0 == comedi_debug)  /* force DMA debug printks */
735                 comedi_debug = 1;
736 #endif
737
738         /*
739          * Allocate the private structure area.  alloc_private() is a
740          * convenient macro defined in comedidev.h.
741          */
742         if (alloc_private(dev, sizeof(rtdPrivate)) < 0)
743                 return -ENOMEM;
744
745         /*
746          * Probe the device to determine what device in the series it is.
747          */
748         for (pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, NULL);
749                 pcidev != NULL;
750                 pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, pcidev)) {
751                 int i;
752
753                 if (it->options[0] || it->options[1]) {
754                         if (pcidev->bus->number != it->options[0]
755                                 || PCI_SLOT(pcidev->devfn) !=
756                                 it->options[1]) {
757                                 continue;
758                         }
759                 }
760                 for(i = 0; i < sizeof(rtd520Boards) / sizeof(rtd520Boards[0]); ++i)
761                 {
762                         if(pcidev->device == rtd520Boards[i].device_id)
763                         {
764                                 dev->board_ptr = &rtd520Boards[i];
765                                 break;
766                         }
767                 }
768                 if(dev->board_ptr) break;       /* found one */
769         }
770         if (!pcidev) {
771                 if (it->options[0] && it->options[1]) {
772                         printk("No RTD card at bus=%d slot=%d.\n",
773                                 it->options[0], it->options[1]);
774                 } else {
775                         printk("No RTD card found.\n");
776                 }
777                 return -EIO;
778         }
779         devpriv->pci_dev = pcidev;
780         dev->board_name = thisboard->name;
781
782         if ((ret = comedi_pci_enable(pcidev, DRV_NAME)) < 0) {
783                 printk("Failed to enable PCI device and request regions.\n");
784                 return ret;
785         }
786         devpriv->got_regions = 1;
787
788         /*
789          * Initialize base addresses
790          */
791         /* Get the physical address from PCI config */
792         physLas0 = pci_resource_start(devpriv->pci_dev, LAS0_PCIINDEX);
793         physLas1 = pci_resource_start(devpriv->pci_dev, LAS1_PCIINDEX);
794         physLcfg = pci_resource_start(devpriv->pci_dev, LCFG_PCIINDEX);
795         /* Now have the kernel map this into memory */
796         /* ASSUME page aligned */
797         devpriv->las0 = ioremap_nocache(physLas0, LAS0_PCISIZE);
798         devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE);
799         devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE);
800
801         if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) {
802                 return -ENOMEM;
803         }
804
805         DPRINTK("%s: LAS0=%llx, LAS1=%llx, CFG=%llx.\n", dev->board_name,
806                 (unsigned long long)physLas0, (unsigned long long)physLas1,
807                 (unsigned long long)physLcfg);
808         {                       /* The RTD driver does this */
809                 unsigned char pci_latency;
810                 u16 revision;
811                 /*uint32_t epld_version; */
812
813                 pci_read_config_word(devpriv->pci_dev, PCI_REVISION_ID,
814                         &revision);
815                 DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision);
816
817                 pci_read_config_byte(devpriv->pci_dev,
818                         PCI_LATENCY_TIMER, &pci_latency);
819                 if (pci_latency < 32) {
820                         printk("%s: PCI latency changed from %d to %d\n",
821                                 dev->board_name, pci_latency, 32);
822                         pci_write_config_byte(devpriv->pci_dev,
823                                 PCI_LATENCY_TIMER, 32);
824                 } else {
825                         DPRINTK("rtd520: PCI latency = %d\n", pci_latency);
826                 }
827
828                 /* Undocumented EPLD version (doesnt match RTD driver results) */
829                 /*DPRINTK ("rtd520: Reading epld from %p\n",
830                    devpriv->las0+0);
831                    epld_version = readl (devpriv->las0+0);
832                    if ((epld_version & 0xF0) >> 4 == 0x0F) {
833                    DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version);
834                    } else {
835                    DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4);
836                    } */
837         }
838
839         /* Show board configuration */
840         printk("%s:", dev->board_name);
841
842         /*
843          * Allocate the subdevice structures.  alloc_subdevice() is a
844          * convenient macro defined in comedidev.h.
845          */
846         if (alloc_subdevices(dev, 4) < 0) {
847                 return -ENOMEM;
848         }
849
850         s = dev->subdevices + 0;
851         dev->read_subdev = s;
852         /* analog input subdevice */
853         s->type = COMEDI_SUBD_AI;
854         s->subdev_flags =
855                 SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF |
856                 SDF_CMD_READ;
857         s->n_chan = thisboard->aiChans;
858         s->maxdata = (1 << thisboard->aiBits) - 1;
859         if (thisboard->aiMaxGain <= 32) {
860                 s->range_table = &rtd_ai_7520_range;
861         } else {
862                 s->range_table = &rtd_ai_4520_range;
863         }
864         s->len_chanlist = RTD_MAX_CHANLIST;     /* devpriv->fifoLen */
865         s->insn_read = rtd_ai_rinsn;
866         s->do_cmd = rtd_ai_cmd;
867         s->do_cmdtest = rtd_ai_cmdtest;
868         s->cancel = rtd_ai_cancel;
869         /*s->poll = rtd_ai_poll; *//* not ready yet */
870
871         s = dev->subdevices + 1;
872         /* analog output subdevice */
873         s->type = COMEDI_SUBD_AO;
874         s->subdev_flags = SDF_WRITABLE;
875         s->n_chan = 2;
876         s->maxdata = (1 << thisboard->aiBits) - 1;
877         s->range_table = &rtd_ao_range;
878         s->insn_write = rtd_ao_winsn;
879         s->insn_read = rtd_ao_rinsn;
880
881         s = dev->subdevices + 2;
882         /* digital i/o subdevice */
883         s->type = COMEDI_SUBD_DIO;
884         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
885         /* we only support port 0 right now.  Ignoring port 1 and user IO */
886         s->n_chan = 8;
887         s->maxdata = 1;
888         s->range_table = &range_digital;
889         s->insn_bits = rtd_dio_insn_bits;
890         s->insn_config = rtd_dio_insn_config;
891
892         /* timer/counter subdevices (not currently supported) */
893         s = dev->subdevices + 3;
894         s->type = COMEDI_SUBD_COUNTER;
895         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
896         s->n_chan = 3;
897         s->maxdata = 0xffff;
898
899         /* initialize board, per RTD spec */
900         /* also, initialize shadow registers */
901         RtdResetBoard(dev);
902         comedi_udelay(100);     /* needed? */
903         RtdPlxInterruptWrite(dev, 0);
904         RtdInterruptMask(dev, 0);       /* and sets shadow */
905         RtdInterruptClearMask(dev, ~0); /* and sets shadow */
906         RtdInterruptClear(dev); /* clears bits set by mask */
907         RtdInterruptOverrunClear(dev);
908         RtdClearCGT(dev);
909         RtdAdcClearFifo(dev);
910         RtdDacClearFifo(dev, 0);
911         RtdDacClearFifo(dev, 1);
912         /* clear digital IO fifo */
913         RtdDioStatusWrite(dev, 0);      /* safe state, set shadow */
914         RtdUtcCtrlPut(dev, 0, 0x30);    /* safe state, set shadow */
915         RtdUtcCtrlPut(dev, 1, 0x30);    /* safe state, set shadow */
916         RtdUtcCtrlPut(dev, 2, 0x30);    /* safe state, set shadow */
917         RtdUtcCtrlPut(dev, 3, 0);       /* safe state, set shadow */
918         /* TODO: set user out source ??? */
919
920         /* check if our interrupt is available and get it */
921         if ((ret = comedi_request_irq(devpriv->pci_dev->irq, rtd_interrupt,
922                                 IRQF_SHARED, DRV_NAME, dev)) < 0) {
923                 printk("Could not get interrupt! (%u)\n",
924                         devpriv->pci_dev->irq);
925                 return ret;
926         }
927         dev->irq = devpriv->pci_dev->irq;
928         printk("( irq=%u )", dev->irq);
929
930         ret = rtd520_probe_fifo_depth(dev);
931         if(ret < 0) {
932                 return ret;
933         }
934         devpriv->fifoLen = ret;
935         printk("( fifoLen=%d )", devpriv->fifoLen);
936
937 #ifdef USE_DMA
938         if (dev->irq > 0) {
939                 printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT);
940                 /* The PLX9080 has 2 DMA controllers, but there could be 4 sources:
941                    ADC, digital, DAC1, and DAC2.  Since only the ADC supports cmd mode
942                    right now, this isn't an issue (yet) */
943                 devpriv->dma0Offset = 0;
944
945                 for (index = 0; index < DMA_CHAIN_COUNT; index++) {
946                         devpriv->dma0Buff[index] =
947                                 pci_alloc_consistent(devpriv->pci_dev,
948                                 sizeof(u16) * devpriv->fifoLen / 2,
949                                 &devpriv->dma0BuffPhysAddr[index]);
950                         if (devpriv->dma0Buff[index] == NULL) {
951                                 ret = -ENOMEM;
952                                 goto rtd_attach_die_error;
953                         }
954                         /*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n",
955                            index,
956                            devpriv->dma0Buff[index], devpriv->dma0BuffPhysAddr[index]); */
957                 }
958
959                 /* setup DMA descriptor ring (use cpu_to_le32 for byte ordering?) */
960                 devpriv->dma0Chain =
961                         pci_alloc_consistent(devpriv->pci_dev,
962                         sizeof(struct plx_dma_desc) * DMA_CHAIN_COUNT,
963                         &devpriv->dma0ChainPhysAddr);
964                 for (index = 0; index < DMA_CHAIN_COUNT; index++) {
965                         devpriv->dma0Chain[index].pci_start_addr =
966                                 devpriv->dma0BuffPhysAddr[index];
967                         devpriv->dma0Chain[index].local_start_addr =
968                                 DMALADDR_ADC;
969                         devpriv->dma0Chain[index].transfer_size =
970                                 sizeof(u16) * devpriv->fifoLen / 2;
971                         devpriv->dma0Chain[index].next =
972                                 (devpriv->dma0ChainPhysAddr + ((index +
973                                                 1) % (DMA_CHAIN_COUNT))
974                                 * sizeof(devpriv->dma0Chain[0]))
975                                 | DMA_TRANSFER_BITS;
976                         /*DPRINTK ("ring[%d] @%lx PCI: %x, local: %x, N: 0x%x, next: %x\n",
977                            index,
978                            ((long)devpriv->dma0ChainPhysAddr
979                            + (index * sizeof(devpriv->dma0Chain[0]))),
980                            devpriv->dma0Chain[index].pci_start_addr,
981                            devpriv->dma0Chain[index].local_start_addr,
982                            devpriv->dma0Chain[index].transfer_size,
983                            devpriv->dma0Chain[index].next); */
984                 }
985
986                 if (devpriv->dma0Chain == NULL) {
987                         ret = -ENOMEM;
988                         goto rtd_attach_die_error;
989                 }
990
991                 RtdDma0Mode(dev, DMA_MODE_BITS);
992                 RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);      /* set DMA trigger source */
993         } else {
994                 printk("( no IRQ->no DMA )");
995         }
996 #endif /* USE_DMA */
997
998         if (dev->irq) {         /* enable plx9080 interrupts */
999                 RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE);
1000         }
1001
1002         printk("\ncomedi%d: rtd520 driver attached.\n", dev->minor);
1003
1004         return 1;
1005
1006 #if 0
1007         /* hit an error, clean up memory and return ret */
1008 //rtd_attach_die_error:
1009 #ifdef USE_DMA
1010         for (index = 0; index < DMA_CHAIN_COUNT; index++) {
1011                 if (NULL != devpriv->dma0Buff[index]) { /* free buffer memory */
1012                         pci_free_consistent(devpriv->pci_dev,
1013                                 sizeof(u16) * devpriv->fifoLen / 2,
1014                                 devpriv->dma0Buff[index],
1015                                 devpriv->dma0BuffPhysAddr[index]);
1016                         devpriv->dma0Buff[index] = NULL;
1017                 }
1018         }
1019         if (NULL != devpriv->dma0Chain) {
1020                 pci_free_consistent(devpriv->pci_dev,
1021                         sizeof(struct plx_dma_desc)
1022                         * DMA_CHAIN_COUNT,
1023                         devpriv->dma0Chain, devpriv->dma0ChainPhysAddr);
1024                 devpriv->dma0Chain = NULL;
1025         }
1026 #endif /* USE_DMA */
1027         /* subdevices and priv are freed by the core */
1028         if (dev->irq) {
1029                 /* disable interrupt controller */
1030                 RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev)
1031                         & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E));
1032                 comedi_free_irq(dev->irq, dev);
1033         }
1034
1035         /* release all regions that were allocated */
1036         if (devpriv->las0) {
1037                 iounmap(devpriv->las0);
1038         }
1039         if (devpriv->las1) {
1040                 iounmap(devpriv->las1);
1041         }
1042         if (devpriv->lcfg) {
1043                 iounmap(devpriv->lcfg);
1044         }
1045         if (devpriv->pci_dev) {
1046                 pci_dev_put(devpriv->pci_dev);
1047         }
1048         return ret;
1049 #endif
1050 }
1051
1052 /*
1053  * _detach is called to deconfigure a device.  It should deallocate
1054  * resources.
1055  * This function is also called when _attach() fails, so it should be
1056  * careful not to release resources that were not necessarily
1057  * allocated by _attach().  dev->private and dev->subdevices are
1058  * deallocated automatically by the core.
1059  */
1060 static int rtd_detach(comedi_device * dev)
1061 {
1062 #ifdef USE_DMA
1063         int index;
1064 #endif
1065
1066         DPRINTK("comedi%d: rtd520: removing (%ld ints)\n",
1067                 dev->minor, (devpriv ? devpriv->intCount : 0L));
1068         if (devpriv && devpriv->lcfg) {
1069                 DPRINTK("(int status 0x%x, overrun status 0x%x, fifo status 0x%x)...\n", 0xffff & RtdInterruptStatus(dev), 0xffff & RtdInterruptOverrunStatus(dev), (0xffff & RtdFifoStatus(dev)) ^ 0x6666);
1070         }
1071
1072         if (devpriv) {
1073                 /* Shut down any board ops by resetting it */
1074 #ifdef USE_DMA
1075                 if (devpriv->lcfg) {
1076                         RtdDma0Control(dev, 0); /* disable DMA */
1077                         RtdDma1Control(dev, 0); /* disable DMA */
1078                         RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE);
1079                 }
1080 #endif /* USE_DMA */
1081                 if (devpriv->las0) {
1082                         RtdResetBoard(dev);
1083                         RtdInterruptMask(dev, 0);
1084                         RtdInterruptClearMask(dev, ~0);
1085                         RtdInterruptClear(dev); /* clears bits set by mask */
1086                 }
1087 #ifdef USE_DMA
1088                 /* release DMA */
1089                 for (index = 0; index < DMA_CHAIN_COUNT; index++) {
1090                         if (NULL != devpriv->dma0Buff[index]) {
1091                                 pci_free_consistent(devpriv->pci_dev,
1092                                         sizeof(u16) * devpriv->fifoLen / 2,
1093                                         devpriv->dma0Buff[index],
1094                                         devpriv->dma0BuffPhysAddr[index]);
1095                                 devpriv->dma0Buff[index] = NULL;
1096                         }
1097                 }
1098                 if (NULL != devpriv->dma0Chain) {
1099                         pci_free_consistent(devpriv->pci_dev,
1100                                 sizeof(struct plx_dma_desc) * DMA_CHAIN_COUNT,
1101                                 devpriv->dma0Chain, devpriv->dma0ChainPhysAddr);
1102                         devpriv->dma0Chain = NULL;
1103                 }
1104 #endif /* USE_DMA */
1105
1106                 /* release IRQ */
1107                 if (dev->irq) {
1108                         /* disable interrupt controller */
1109                         RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev)
1110                                 & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E));
1111                         comedi_free_irq(dev->irq, dev);
1112                 }
1113
1114                 /* release all regions that were allocated */
1115                 if (devpriv->las0) {
1116                         iounmap(devpriv->las0);
1117                 }
1118                 if (devpriv->las1) {
1119                         iounmap(devpriv->las1);
1120                 }
1121                 if (devpriv->lcfg) {
1122                         iounmap(devpriv->lcfg);
1123                 }
1124                 if (devpriv->pci_dev) {
1125                         if (devpriv->got_regions) {
1126                                 comedi_pci_disable(devpriv->pci_dev);
1127                         }
1128                         pci_dev_put(devpriv->pci_dev);
1129                 }
1130         }
1131
1132         printk("comedi%d: rtd520: removed.\n", dev->minor);
1133
1134         return 0;
1135 }
1136
1137 /*
1138   Convert a single comedi channel-gain entry to a RTD520 table entry
1139 */
1140 static unsigned short rtdConvertChanGain(comedi_device * dev,
1141         unsigned int comediChan, int chanIndex)
1142 {                               /* index in channel list */
1143         unsigned int chan, range, aref;
1144         unsigned short r = 0;
1145
1146         chan = CR_CHAN(comediChan);
1147         range = CR_RANGE(comediChan);
1148         aref = CR_AREF(comediChan);
1149
1150         r |= chan & 0xf;
1151
1152         /* Note: we also setup the channel list bipolar flag array */
1153         if (range < thisboard->range10Start) {  /* first batch are +-5 */
1154                 r |= 0x000;     /* +-5 range */
1155                 r |= (range & 0x7) << 4;        /* gain */
1156                 CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
1157         } else if (range < thisboard->rangeUniStart) {  /* second batch are +-10 */
1158                 r |= 0x100;     /* +-10 range */
1159                 r |= ((range - thisboard->range10Start) & 0x7) << 4;    /* gain */
1160                 CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
1161         } else {                /* last batch is +10 */
1162                 r |= 0x200;     /* +10 range */
1163                 r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;   /* gain */
1164                 CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
1165         }
1166
1167         switch (aref) {
1168         case AREF_GROUND:       /* on-board ground */
1169                 break;
1170
1171         case AREF_COMMON:
1172                 r |= 0x80;      /* ref external analog common */
1173                 break;
1174
1175         case AREF_DIFF:
1176                 r |= 0x400;     /* differential inputs */
1177                 break;
1178
1179         case AREF_OTHER:        /* ??? */
1180                 break;
1181         }
1182         /*printk ("chan=%d r=%d a=%d -> 0x%x\n",
1183            chan, range, aref, r); */
1184         return r;
1185 }
1186
1187 /*
1188   Setup the channel-gain table from a comedi list
1189 */
1190 static void rtd_load_channelgain_list(comedi_device * dev,
1191         unsigned int n_chan, unsigned int *list)
1192 {
1193         if (n_chan > 1) {       /* setup channel gain table */
1194                 int ii;
1195                 RtdClearCGT(dev);
1196                 RtdEnableCGT(dev, 1);   /* enable table */
1197                 for (ii = 0; ii < n_chan; ii++) {
1198                         RtdWriteCGTable(dev, rtdConvertChanGain(dev, list[ii],
1199                                         ii));
1200                 }
1201         } else {                /* just use the channel gain latch */
1202                 RtdEnableCGT(dev, 0);   /* disable table, enable latch */
1203                 RtdWriteCGLatch(dev, rtdConvertChanGain(dev, list[0], 0));
1204         }
1205 }
1206
1207 /* determine fifo size by doing adc conversions until the fifo half
1208 empty status flag clears */
1209 static int rtd520_probe_fifo_depth(comedi_device *dev)
1210 {
1211         lsampl_t chanspec = CR_PACK(0, 0, AREF_GROUND);
1212         unsigned i;
1213         static const unsigned limit = 0x2000;
1214         unsigned fifo_size = 0;
1215
1216         RtdAdcClearFifo(dev);
1217         rtd_load_channelgain_list(dev, 1, &chanspec);
1218         RtdAdcConversionSource(dev, 0); /* software */
1219         /* convert  samples */
1220         for (i = 0; i < limit; ++i) {
1221                 unsigned fifo_status;
1222                 /* trigger conversion */
1223                 RtdAdcStart(dev);
1224                 comedi_udelay(1);
1225                 fifo_status = RtdFifoStatus(dev);
1226                 if((fifo_status & FS_ADC_HEMPTY) == 0) {
1227                         fifo_size = 2 * i;
1228                         break;
1229                 }
1230         }
1231         if(i == limit)
1232         {
1233                 rt_printk("\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
1234                 return -EIO;
1235         }
1236         RtdAdcClearFifo(dev);
1237         if(fifo_size != 0x400 || fifo_size != 0x2000)
1238         {
1239                 rt_printk("\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
1240                         DRV_NAME, fifo_size);
1241                 return -EIO;
1242         }
1243         return fifo_size;
1244 }
1245
1246 /*
1247   "instructions" read/write data in "one-shot" or "software-triggered"
1248   mode (simplest case).
1249   This doesnt use interrupts.
1250
1251   Note, we don't do any settling delays.  Use a instruction list to
1252   select, delay, then read.
1253  */
1254 static int rtd_ai_rinsn(comedi_device * dev,
1255         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
1256 {
1257         int n, ii;
1258         int stat;
1259
1260         /* clear any old fifo data */
1261         RtdAdcClearFifo(dev);
1262
1263         /* write channel to multiplexer and clear channel gain table */
1264         rtd_load_channelgain_list(dev, 1, &insn->chanspec);
1265
1266         /* set conversion source */
1267         RtdAdcConversionSource(dev, 0); /* software */
1268
1269         /* convert n samples */
1270         for (n = 0; n < insn->n; n++) {
1271                 s16 d;
1272                 /* trigger conversion */
1273                 RtdAdcStart(dev);
1274
1275                 for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) {
1276                         stat = RtdFifoStatus(dev);
1277                         if (stat & FS_ADC_NOT_EMPTY)    /* 1 -> not empty */
1278                                 break;
1279                         WAIT_QUIETLY;
1280                 }
1281                 if (ii >= RTD_ADC_TIMEOUT) {
1282                         DPRINTK("rtd520: Error: ADC never finished! FifoStatus=0x%x\n", stat ^ 0x6666);
1283                         return -ETIMEDOUT;
1284                 }
1285
1286                 /* read data */
1287                 d = RtdAdcFifoGet(dev); /* get 2s comp value */
1288                 /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */
1289                 d = d >> 3;     /* low 3 bits are marker lines */
1290                 if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0)) {
1291                         data[n] = d + 2048;     /* convert to comedi unsigned data */
1292                 } else {
1293                         data[n] = d;
1294                 }
1295         }
1296
1297         /* return the number of samples read/written */
1298         return n;
1299 }
1300
1301 /*
1302   Get what we know is there.... Fast!
1303   This uses 1/2 the bus cycles of read_dregs (below).
1304
1305   The manual claims that we can do a lword read, but it doesn't work here.
1306 */
1307 static int ai_read_n(comedi_device * dev, comedi_subdevice * s, int count)
1308 {
1309         int ii;
1310
1311         for (ii = 0; ii < count; ii++) {
1312                 sampl_t sample;
1313                 s16 d;
1314
1315                 if (0 == devpriv->aiCount) {    /* done */
1316                         d = RtdAdcFifoGet(dev); /* Read N and discard */
1317                         continue;
1318                 }
1319 #if 0
1320                 if (0 == (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY)) {     /* DEBUG */
1321                         DPRINTK("comedi: READ OOPS on %d of %d\n", ii + 1,
1322                                 count);
1323                         break;
1324                 }
1325 #endif
1326                 d = RtdAdcFifoGet(dev); /* get 2s comp value */
1327
1328                 d = d >> 3;     /* low 3 bits are marker lines */
1329                 if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
1330                         sample = d + 2048;      /* convert to comedi unsigned data */
1331                 } else {
1332                         sample = d;
1333                 }
1334                 if (!comedi_buf_put(s->async, sample))
1335                         return -1;
1336
1337                 if (devpriv->aiCount > 0)       /* < 0, means read forever */
1338                         devpriv->aiCount--;
1339         }
1340         return 0;
1341 }
1342
1343 /*
1344   unknown amout of data is waiting in fifo.
1345 */
1346 static int ai_read_dregs(comedi_device * dev, comedi_subdevice * s)
1347 {
1348         while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */
1349                 sampl_t sample;
1350                 s16 d = RtdAdcFifoGet(dev);     /* get 2s comp value */
1351
1352                 if (0 == devpriv->aiCount) {    /* done */
1353                         continue;       /* read rest */
1354                 }
1355
1356                 d = d >> 3;     /* low 3 bits are marker lines */
1357                 if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
1358                         sample = d + 2048;      /* convert to comedi unsigned data */
1359                 } else {
1360                         sample = d;
1361                 }
1362                 if (!comedi_buf_put(s->async, sample))
1363                         return -1;
1364
1365                 if (devpriv->aiCount > 0)       /* < 0, means read forever */
1366                         devpriv->aiCount--;
1367         }
1368         return 0;
1369 }
1370
1371 #ifdef USE_DMA
1372 /*
1373   Terminate a DMA transfer and wait for everything to quiet down
1374 */
1375 void abort_dma(comedi_device * dev, unsigned int channel)
1376 {                               /* DMA channel 0, 1 */
1377         unsigned long dma_cs_addr;      /* the control/status register */
1378         uint8_t status;
1379         unsigned int ii;
1380         //unsigned long flags;
1381
1382         dma_cs_addr = (unsigned long)devpriv->lcfg
1383                 + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1);
1384
1385         // spinlock for plx dma control/status reg
1386         //comedi_spin_lock_irqsave( &dev->spinlock, flags );
1387
1388         // abort dma transfer if necessary
1389         status = readb(dma_cs_addr);
1390         if ((status & PLX_DMA_EN_BIT) == 0) {   /* not enabled (Error?) */
1391                 DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n",
1392                         channel, status);
1393                 goto abortDmaExit;
1394         }
1395
1396         /* wait to make sure done bit is zero (needed?) */
1397         for (ii = 0; (status & PLX_DMA_DONE_BIT) && ii < RTD_DMA_TIMEOUT; ii++) {
1398                 WAIT_QUIETLY;
1399                 status = readb(dma_cs_addr);
1400         }
1401         if (status & PLX_DMA_DONE_BIT) {
1402                 printk("rtd520: Timeout waiting for dma %i done clear\n",
1403                         channel);
1404                 goto abortDmaExit;
1405         }
1406
1407         /* disable channel (required) */
1408         writeb(0, dma_cs_addr);
1409         comedi_udelay(1);       /* needed?? */
1410         /* set abort bit for channel */
1411         writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
1412
1413         // wait for dma done bit to be set
1414         status = readb(dma_cs_addr);
1415         for (ii = 0;
1416                 (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT;
1417                 ii++) {
1418                 status = readb(dma_cs_addr);
1419                 WAIT_QUIETLY;
1420         }
1421         if ((status & PLX_DMA_DONE_BIT) == 0) {
1422                 printk("rtd520: Timeout waiting for dma %i done set\n",
1423                         channel);
1424         }
1425
1426       abortDmaExit:
1427         //comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
1428 }
1429
1430 /*
1431   Process what is in the DMA transfer buffer and pass to comedi
1432   Note: this is not re-entrant
1433 */
1434 static int ai_process_dma(comedi_device * dev, comedi_subdevice * s)
1435 {
1436         int ii, n;
1437         s16 *dp;
1438
1439         if (devpriv->aiCount == 0)      /* transfer already complete */
1440                 return 0;
1441
1442         dp = devpriv->dma0Buff[devpriv->dma0Offset];
1443         for (ii = 0; ii < devpriv->fifoLen / 2;) {      /* convert samples */
1444                 sampl_t sample;
1445
1446                 if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
1447                         sample = (*dp >> 3) + 2048;     /* convert to comedi unsigned data */
1448                 } else {
1449                         sample = *dp >> 3;      /* low 3 bits are marker lines */
1450                 }
1451                 *dp++ = sample; /* put processed value back */
1452
1453                 if (++s->async->cur_chan >= s->async->cmd.chanlist_len)
1454                         s->async->cur_chan = 0;
1455
1456                 ++ii;           /* number ready to transfer */
1457                 if (devpriv->aiCount > 0) {     /* < 0, means read forever */
1458                         if (--devpriv->aiCount == 0) {  /* done */
1459                                 /*DPRINTK ("rtd520: Final %d samples\n", ii); */
1460                                 break;
1461                         }
1462                 }
1463         }
1464
1465         /* now pass the whole array to the comedi buffer */
1466         dp = devpriv->dma0Buff[devpriv->dma0Offset];
1467         n = comedi_buf_write_alloc(s->async, ii * sizeof(s16));
1468         if (n < (ii * sizeof(s16))) {   /* any residual is an error */
1469                 DPRINTK("rtd520:ai_process_dma buffer overflow %d samples!\n",
1470                         ii - (n / sizeof(s16)));
1471                 s->async->events |= COMEDI_CB_ERROR;
1472                 return -1;
1473         }
1474         comedi_buf_memcpy_to(s->async, 0, dp, n);
1475         comedi_buf_write_free(s->async, n);
1476
1477         /* always at least 1 scan -- 1/2 FIFO is larger than our max scan list */
1478         s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
1479
1480         if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) { /* next buffer */
1481                 devpriv->dma0Offset = 0;
1482         }
1483         return 0;
1484 }
1485 #endif /* USE_DMA */
1486
1487 /*
1488   Handle all rtd520 interrupts.
1489   Runs atomically and is never re-entered.
1490   This is a "slow handler";  other interrupts may be active.
1491   The data conversion may someday happen in a "bottom half".
1492 */
1493 static irqreturn_t rtd_interrupt(int irq,       /* interrupt number (ignored) */
1494         void *d                 /* our data */
1495         PT_REGS_ARG)
1496 {                               /* cpu context (ignored) */
1497         comedi_device *dev = d; /* must be called "dev" for devpriv */
1498         u16 status;
1499         u16 fifoStatus;
1500         comedi_subdevice *s = dev->subdevices + 0;      /* analog in subdevice */
1501
1502         if (!dev->attached) {
1503                 return IRQ_NONE;
1504         }
1505
1506         devpriv->intCount++;    /* DEBUG statistics */
1507
1508         fifoStatus = RtdFifoStatus(dev);
1509         /* check for FIFO full, this automatically halts the ADC! */
1510         if (!(fifoStatus & FS_ADC_NOT_FULL)) {  /* 0 -> full */
1511                 DPRINTK("rtd520: FIFO full! fifo_status=0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);       /* should be all 0s */
1512                 goto abortTransfer;
1513         }
1514 #ifdef USE_DMA
1515         if (devpriv->flags & DMA0_ACTIVE) {     /* Check DMA */
1516                 u32 istatus = RtdPlxInterruptRead(dev);
1517
1518                 if (istatus & ICS_DMA0_A) {
1519                         if (ai_process_dma(dev, s) < 0) {
1520                                 DPRINTK("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n", devpriv->aiCount);
1521                                 RtdDma0Control(dev,
1522                                         (devpriv->
1523                                                 dma0Control &
1524                                                 ~PLX_DMA_START_BIT)
1525                                         | PLX_CLEAR_DMA_INTR_BIT);
1526                                 goto abortTransfer;
1527                         }
1528
1529                         /*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n",
1530                            devpriv->aiCount, istatus); */
1531                         RtdDma0Control(dev,
1532                                 (devpriv->dma0Control & ~PLX_DMA_START_BIT)
1533                                 | PLX_CLEAR_DMA_INTR_BIT);
1534                         if (0 == devpriv->aiCount) {    /* counted down */
1535                                 DPRINTK("rtd520: Samples Done (DMA).\n");
1536                                 goto transferDone;
1537                         }
1538                         comedi_event(dev, s);
1539                 } else {
1540                         /*DPRINTK ("rtd520: No DMA ready: istatus %x\n", istatus); */
1541                 }
1542         }
1543         /* Fall through and check for other interrupt sources */
1544 #endif /* USE_DMA */
1545
1546         status = RtdInterruptStatus(dev);
1547         /* if interrupt was not caused by our board, or handled above */
1548         if (0 == status) {
1549                 return IRQ_HANDLED;
1550         }
1551
1552         if (status & IRQM_ADC_ABOUT_CNT) {      /* sample count -> read FIFO */
1553                 /* since the priority interrupt controller may have queued a sample
1554                    counter interrupt, even though we have already finished,
1555                    we must handle the possibility that there is no data here */
1556                 if (!(fifoStatus & FS_ADC_HEMPTY)) {    /* 0 -> 1/2 full */
1557                         /*DPRINTK("rtd520: Sample int, reading 1/2FIFO.  fifo_status 0x%x\n",
1558                            (fifoStatus ^ 0x6666) & 0x7777); */
1559                         if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0) {
1560                                 DPRINTK("rtd520: comedi read buffer overflow (1/2FIFO) with %ld to go!\n", devpriv->aiCount);
1561                                 goto abortTransfer;
1562                         }
1563                         if (0 == devpriv->aiCount) {    /* counted down */
1564                                 DPRINTK("rtd520: Samples Done (1/2). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);  /* should be all 0s */
1565                                 goto transferDone;
1566                         }
1567                         comedi_event(dev, s);
1568                 } else if (devpriv->transCount > 0) {   /* read often */
1569                         /*DPRINTK("rtd520: Sample int, reading %d  fifo_status 0x%x\n",
1570                            devpriv->transCount, (fifoStatus ^ 0x6666) & 0x7777); */
1571                         if (fifoStatus & FS_ADC_NOT_EMPTY) {    /* 1 -> not empty */
1572                                 if (ai_read_n(dev, s, devpriv->transCount) < 0) {
1573                                         DPRINTK("rtd520: comedi read buffer overflow (N) with %ld to go!\n", devpriv->aiCount);
1574                                         goto abortTransfer;
1575                                 }
1576                                 if (0 == devpriv->aiCount) {    /* counted down */
1577                                         DPRINTK("rtd520: Samples Done (N). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);
1578                                         goto transferDone;
1579                                 }
1580                                 comedi_event(dev, s);
1581                         }
1582                 } else {        /* wait for 1/2 FIFO (old) */
1583                         DPRINTK("rtd520: Sample int.  Wait for 1/2. fifo_status 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);
1584                 }
1585         } else {
1586                 DPRINTK("rtd520: unknown interrupt source!\n");
1587         }
1588
1589         if (0xffff & RtdInterruptOverrunStatus(dev)) {  /* interrupt overrun */
1590                 DPRINTK("rtd520: Interrupt overrun with %ld to go! over_status=0x%x\n", devpriv->aiCount, 0xffff & RtdInterruptOverrunStatus(dev));
1591                 goto abortTransfer;
1592         }
1593
1594         /* clear the interrupt */
1595         RtdInterruptClearMask(dev, status);
1596         RtdInterruptClear(dev);
1597         return IRQ_HANDLED;
1598
1599       abortTransfer:
1600         RtdAdcClearFifo(dev);   /* clears full flag */
1601         s->async->events |= COMEDI_CB_ERROR;
1602         devpriv->aiCount = 0;   /* stop and don't transfer any more */
1603         /* fall into transferDone */
1604
1605       transferDone:
1606         RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
1607         RtdPacerStop(dev);      /* Stop PACER */
1608         RtdAdcConversionSource(dev, 0); /* software trigger only */
1609         RtdInterruptMask(dev, 0);       /* mask out SAMPLE */
1610 #ifdef USE_DMA
1611         if (devpriv->flags & DMA0_ACTIVE) {
1612                 RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
1613                         RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
1614                 abort_dma(dev, 0);
1615                 devpriv->flags &= ~DMA0_ACTIVE;
1616                 /* if Using DMA, then we should have read everything by now */
1617                 if (devpriv->aiCount > 0) {
1618                         DPRINTK("rtd520: Lost DMA data! %ld remain\n",
1619                                 devpriv->aiCount);
1620                 }
1621         }
1622 #endif /* USE_DMA */
1623
1624         if (devpriv->aiCount > 0) {     /* there shouldn't be anything left */
1625                 fifoStatus = RtdFifoStatus(dev);
1626                 DPRINTK("rtd520: Finishing up. %ld remain, fifoStat=%x\n", devpriv->aiCount, (fifoStatus ^ 0x6666) & 0x7777);   /* should read all 0s */
1627                 ai_read_dregs(dev, s);  /* read anything left in FIFO */
1628         }
1629
1630         s->async->events |= COMEDI_CB_EOA;      /* signal end to comedi */
1631         comedi_event(dev, s);
1632
1633         /* clear the interrupt */
1634         status = RtdInterruptStatus(dev);
1635         RtdInterruptClearMask(dev, status);
1636         RtdInterruptClear(dev);
1637
1638         fifoStatus = RtdFifoStatus(dev);        /* DEBUG */
1639         DPRINTK("rtd520: Acquisition complete. %ld ints, intStat=%x, overStat=%x\n", devpriv->intCount, status, 0xffff & RtdInterruptOverrunStatus(dev));
1640
1641         return IRQ_HANDLED;
1642 }
1643
1644 #if 0
1645 /*
1646   return the number of samples available
1647 */
1648 static int rtd_ai_poll(comedi_device * dev, comedi_subdevice * s)
1649 {
1650         /* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
1651         /* Not sure what to do if DMA is active */
1652         return s->async->buf_write_count - s->async->buf_read_count;
1653 }
1654 #endif
1655
1656 /*
1657   cmdtest tests a particular command to see if it is valid.
1658   Using the cmdtest ioctl, a user can create a valid cmd
1659   and then have it executed by the cmd ioctl (asyncronously).
1660
1661   cmdtest returns 1,2,3,4 or 0, depending on which tests
1662   the command passes.
1663 */
1664
1665 static int rtd_ai_cmdtest(comedi_device * dev,
1666         comedi_subdevice * s, comedi_cmd * cmd)
1667 {
1668         int err = 0;
1669         int tmp;
1670
1671         /* step 1: make sure trigger sources are trivially valid */
1672
1673         tmp = cmd->start_src;
1674         cmd->start_src &= TRIG_NOW;
1675         if (!cmd->start_src || tmp != cmd->start_src) {
1676                 err++;
1677         }
1678
1679         tmp = cmd->scan_begin_src;
1680         cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
1681         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) {
1682                 err++;
1683         }
1684
1685         tmp = cmd->convert_src;
1686         cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1687         if (!cmd->convert_src || tmp != cmd->convert_src) {
1688                 err++;
1689         }
1690
1691         tmp = cmd->scan_end_src;
1692         cmd->scan_end_src &= TRIG_COUNT;
1693         if (!cmd->scan_end_src || tmp != cmd->scan_end_src) {
1694                 err++;
1695         }
1696
1697         tmp = cmd->stop_src;
1698         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1699         if (!cmd->stop_src || tmp != cmd->stop_src) {
1700                 err++;
1701         }
1702
1703         if (err)
1704                 return 1;
1705
1706         /* step 2: make sure trigger sources are unique
1707            and mutually compatible */
1708         /* note that mutual compatiblity is not an issue here */
1709         if (cmd->scan_begin_src != TRIG_TIMER &&
1710                 cmd->scan_begin_src != TRIG_EXT) {
1711                 err++;
1712         }
1713         if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) {
1714                 err++;
1715         }
1716         if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) {
1717                 err++;
1718         }
1719
1720         if (err) {
1721                 return 2;
1722         }
1723
1724         /* step 3: make sure arguments are trivially compatible */
1725
1726         if (cmd->start_arg != 0) {
1727                 cmd->start_arg = 0;
1728                 err++;
1729         }
1730
1731         if (cmd->scan_begin_src == TRIG_TIMER) {
1732                 /* Note: these are time periods, not actual rates */
1733                 if (1 == cmd->chanlist_len) {   /* no scanning */
1734                         if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) {
1735                                 cmd->scan_begin_arg = RTD_MAX_SPEED_1;
1736                                 rtd_ns_to_timer(&cmd->scan_begin_arg,
1737                                         TRIG_ROUND_UP);
1738                                 err++;
1739                         }
1740                         if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) {
1741                                 cmd->scan_begin_arg = RTD_MIN_SPEED_1;
1742                                 rtd_ns_to_timer(&cmd->scan_begin_arg,
1743                                         TRIG_ROUND_DOWN);
1744                                 err++;
1745                         }
1746                 } else {
1747                         if (cmd->scan_begin_arg < RTD_MAX_SPEED) {
1748                                 cmd->scan_begin_arg = RTD_MAX_SPEED;
1749                                 rtd_ns_to_timer(&cmd->scan_begin_arg,
1750                                         TRIG_ROUND_UP);
1751                                 err++;
1752                         }
1753                         if (cmd->scan_begin_arg > RTD_MIN_SPEED) {
1754                                 cmd->scan_begin_arg = RTD_MIN_SPEED;
1755                                 rtd_ns_to_timer(&cmd->scan_begin_arg,
1756                                         TRIG_ROUND_DOWN);
1757                                 err++;
1758                         }
1759                 }
1760         } else {
1761                 /* external trigger */
1762                 /* should be level/edge, hi/lo specification here */
1763                 /* should specify multiple external triggers */
1764                 if (cmd->scan_begin_arg > 9) {
1765                         cmd->scan_begin_arg = 9;
1766                         err++;
1767                 }
1768         }
1769         if (cmd->convert_src == TRIG_TIMER) {
1770                 if (1 == cmd->chanlist_len) {   /* no scanning */
1771                         if (cmd->convert_arg < RTD_MAX_SPEED_1) {
1772                                 cmd->convert_arg = RTD_MAX_SPEED_1;
1773                                 rtd_ns_to_timer(&cmd->convert_arg,
1774                                         TRIG_ROUND_UP);
1775                                 err++;
1776                         }
1777                         if (cmd->convert_arg > RTD_MIN_SPEED_1) {
1778                                 cmd->convert_arg = RTD_MIN_SPEED_1;
1779                                 rtd_ns_to_timer(&cmd->convert_arg,
1780                                         TRIG_ROUND_DOWN);
1781                                 err++;
1782                         }
1783                 } else {
1784                         if (cmd->convert_arg < RTD_MAX_SPEED) {
1785                                 cmd->convert_arg = RTD_MAX_SPEED;
1786                                 rtd_ns_to_timer(&cmd->convert_arg,
1787                                         TRIG_ROUND_UP);
1788                                 err++;
1789                         }
1790                         if (cmd->convert_arg > RTD_MIN_SPEED) {
1791                                 cmd->convert_arg = RTD_MIN_SPEED;
1792                                 rtd_ns_to_timer(&cmd->convert_arg,
1793                                         TRIG_ROUND_DOWN);
1794                                 err++;
1795                         }
1796                 }
1797         } else {
1798                 /* external trigger */
1799                 /* see above */
1800                 if (cmd->convert_arg > 9) {
1801                         cmd->convert_arg = 9;
1802                         err++;
1803                 }
1804         }
1805
1806 #if 0
1807         if (cmd->scan_end_arg != cmd->chanlist_len) {
1808                 cmd->scan_end_arg = cmd->chanlist_len;
1809                 err++;
1810         }
1811 #endif
1812         if (cmd->stop_src == TRIG_COUNT) {
1813                 /* TODO check for rounding error due to counter wrap */
1814
1815         } else {
1816                 /* TRIG_NONE */
1817                 if (cmd->stop_arg != 0) {
1818                         cmd->stop_arg = 0;
1819                         err++;
1820                 }
1821         }
1822
1823         if (err) {
1824                 return 3;
1825         }
1826
1827         /* step 4: fix up any arguments */
1828
1829         if (cmd->chanlist_len > RTD_MAX_CHANLIST) {
1830                 cmd->chanlist_len = RTD_MAX_CHANLIST;
1831                 err++;
1832         }
1833         if (cmd->scan_begin_src == TRIG_TIMER) {
1834                 tmp = cmd->scan_begin_arg;
1835                 rtd_ns_to_timer(&cmd->scan_begin_arg,
1836                         cmd->flags & TRIG_ROUND_MASK);
1837                 if (tmp != cmd->scan_begin_arg) {
1838                         err++;
1839                 }
1840         }
1841         if (cmd->convert_src == TRIG_TIMER) {
1842                 tmp = cmd->convert_arg;
1843                 rtd_ns_to_timer(&cmd->convert_arg,
1844                         cmd->flags & TRIG_ROUND_MASK);
1845                 if (tmp != cmd->convert_arg) {
1846                         err++;
1847                 }
1848                 if (cmd->scan_begin_src == TRIG_TIMER
1849                         && (cmd->scan_begin_arg
1850                                 < (cmd->convert_arg * cmd->scan_end_arg))) {
1851                         cmd->scan_begin_arg =
1852                                 cmd->convert_arg * cmd->scan_end_arg;
1853                         err++;
1854                 }
1855         }
1856
1857         if (err) {
1858                 return 4;
1859         }
1860
1861         return 0;
1862 }
1863
1864 /*
1865   Execute a analog in command with many possible triggering options.
1866   The data get stored in the async structure of the subdevice.
1867   This is usually done by an interrupt handler.
1868   Userland gets to the data using read calls.
1869 */
1870 static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s)
1871 {
1872         comedi_cmd *cmd = &s->async->cmd;
1873         int timer;
1874
1875         /* stop anything currently running */
1876         RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
1877         RtdPacerStop(dev);      /* make sure PACER is stopped */
1878         RtdAdcConversionSource(dev, 0); /* software trigger only */
1879         RtdInterruptMask(dev, 0);
1880 #ifdef USE_DMA
1881         if (devpriv->flags & DMA0_ACTIVE) {     /* cancel anything running */
1882                 RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
1883                         RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
1884                 abort_dma(dev, 0);
1885                 devpriv->flags &= ~DMA0_ACTIVE;
1886                 if (RtdPlxInterruptRead(dev) & ICS_DMA0_A) {    /*clear pending int */
1887                         RtdDma0Control(dev, PLX_CLEAR_DMA_INTR_BIT);
1888                 }
1889         }
1890         RtdDma0Reset(dev);      /* reset onboard state */
1891 #endif /* USE_DMA */
1892         RtdAdcClearFifo(dev);   /* clear any old data */
1893         RtdInterruptOverrunClear(dev);
1894         devpriv->intCount = 0;
1895
1896         if (!dev->irq) {        /* we need interrupts for this */
1897                 DPRINTK("rtd520: ERROR! No interrupt available!\n");
1898                 return -ENXIO;
1899         }
1900
1901         /* start configuration */
1902         /* load channel list and reset CGT */
1903         rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
1904
1905         /* setup the common case and override if needed */
1906         if (cmd->chanlist_len > 1) {
1907                 /*DPRINTK ("rtd520: Multi channel setup\n"); */
1908                 RtdPacerStartSource(dev, 0);    /* software triggers pacer */
1909                 RtdBurstStartSource(dev, 1);    /* PACER triggers burst */
1910                 RtdAdcConversionSource(dev, 2); /* BURST triggers ADC */
1911         } else {                /* single channel */
1912                 /*DPRINTK ("rtd520: single channel setup\n"); */
1913                 RtdPacerStartSource(dev, 0);    /* software triggers pacer */
1914                 RtdAdcConversionSource(dev, 1); /* PACER triggers ADC */
1915         }
1916         RtdAboutCounter(dev, devpriv->fifoLen / 2 - 1); /* 1/2 FIFO */
1917
1918         if (TRIG_TIMER == cmd->scan_begin_src) {
1919                 /* scan_begin_arg is in nanoseconds */
1920                 /* find out how many samples to wait before transferring */
1921                 if (cmd->flags & TRIG_WAKE_EOS) {
1922                         /* this may generate un-sustainable interrupt rates */
1923                         /* the application is responsible for doing the right thing */
1924                         devpriv->transCount = cmd->chanlist_len;
1925                         devpriv->flags |= SEND_EOS;
1926                 } else {
1927                         /* arrange to transfer data periodically */
1928                         devpriv->transCount
1929                                 =
1930                                 (TRANS_TARGET_PERIOD * cmd->chanlist_len) /
1931                                 cmd->scan_begin_arg;
1932                         if (devpriv->transCount < cmd->chanlist_len) {
1933                                 /* tranfer after each scan (and avoid 0) */
1934                                 devpriv->transCount = cmd->chanlist_len;
1935                         } else {        /* make a multiple of scan length */
1936                                 devpriv->transCount =
1937                                         (devpriv->transCount +
1938                                         cmd->chanlist_len - 1)
1939                                         / cmd->chanlist_len;
1940                                 devpriv->transCount *= cmd->chanlist_len;
1941                         }
1942                         devpriv->flags |= SEND_EOS;
1943                 }
1944                 if (devpriv->transCount >= (devpriv->fifoLen / 2)) {
1945                         /* out of counter range, use 1/2 fifo instead */
1946                         devpriv->transCount = 0;
1947                         devpriv->flags &= ~SEND_EOS;
1948                 } else {
1949                         /* interrupt for each tranfer */
1950                         RtdAboutCounter(dev, devpriv->transCount - 1);
1951                 }
1952
1953                 DPRINTK("rtd520: scanLen=%d tranferCount=%d fifoLen=%d\n  scanTime(ns)=%d flags=0x%x\n", cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen, cmd->scan_begin_arg, devpriv->flags);
1954         } else {                /* unknown timing, just use 1/2 FIFO */
1955                 devpriv->transCount = 0;
1956                 devpriv->flags &= ~SEND_EOS;
1957         }
1958         RtdPacerClockSource(dev, 1);    /* use INTERNAL 8Mhz clock source */
1959         RtdAboutStopEnable(dev, 1);     /* just interrupt, dont stop */
1960
1961         /* BUG??? these look like enumerated values, but they are bit fields */
1962
1963         /* First, setup when to stop */
1964         switch (cmd->stop_src) {
1965         case TRIG_COUNT:        /* stop after N scans */
1966                 devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len;
1967                 if ((devpriv->transCount > 0)
1968                         && (devpriv->transCount > devpriv->aiCount)) {
1969                         devpriv->transCount = devpriv->aiCount;
1970                 }
1971                 break;
1972
1973         case TRIG_NONE: /* stop when cancel is called */
1974                 devpriv->aiCount = -1;  /* read forever */
1975                 break;
1976
1977         default:
1978                 DPRINTK("rtd520: Warning! ignoring stop_src mode %d\n",
1979                         cmd->stop_src);
1980         }
1981
1982         /* Scan timing */
1983         switch (cmd->scan_begin_src) {
1984         case TRIG_TIMER:        /* periodic scanning */
1985                 timer = rtd_ns_to_timer(&cmd->scan_begin_arg,
1986                         TRIG_ROUND_NEAREST);
1987                 /* set PACER clock */
1988                 /*DPRINTK ("rtd520: loading %d into pacer\n", timer); */
1989                 RtdPacerCounter(dev, timer);
1990
1991                 break;
1992
1993         case TRIG_EXT:
1994                 RtdPacerStartSource(dev, 1);    /* EXTERNALy trigger pacer */
1995                 break;
1996
1997         default:
1998                 DPRINTK("rtd520: Warning! ignoring scan_begin_src mode %d\n",
1999                         cmd->scan_begin_src);
2000         }
2001
2002         /* Sample timing within a scan */
2003         switch (cmd->convert_src) {
2004         case TRIG_TIMER:        /* periodic */
2005                 if (cmd->chanlist_len > 1) {    /* only needed for multi-channel */
2006                         timer = rtd_ns_to_timer(&cmd->convert_arg,
2007                                 TRIG_ROUND_NEAREST);
2008                         /* setup BURST clock */
2009                         /*DPRINTK ("rtd520: loading %d into burst\n", timer); */
2010                         RtdBurstCounter(dev, timer);
2011                 }
2012
2013                 break;
2014
2015         case TRIG_EXT:          /* external */
2016                 RtdBurstStartSource(dev, 2);    /* EXTERNALy trigger burst */
2017                 break;
2018
2019         default:
2020                 DPRINTK("rtd520: Warning! ignoring convert_src mode %d\n",
2021                         cmd->convert_src);
2022         }
2023         /* end configuration */
2024
2025         /* This doesn't seem to work.  There is no way to clear an interrupt
2026            that the priority controller has queued! */
2027         RtdInterruptClearMask(dev, ~0); /* clear any existing flags */
2028         RtdInterruptClear(dev);
2029
2030         /* TODO: allow multiple interrupt sources */
2031         if (devpriv->transCount > 0) {  /* transfer every N samples */
2032                 RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
2033                 DPRINTK("rtd520: Transferring every %d\n", devpriv->transCount);
2034         } else {                /* 1/2 FIFO transfers */
2035 #ifdef USE_DMA
2036                 devpriv->flags |= DMA0_ACTIVE;
2037
2038                 /* point to first transfer in ring */
2039                 devpriv->dma0Offset = 0;
2040                 RtdDma0Mode(dev, DMA_MODE_BITS);
2041                 RtdDma0Next(dev,        /* point to first block */
2042                         devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next);
2043                 RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);      /* set DMA trigger source */
2044
2045                 RtdPlxInterruptWrite(dev,       /* enable interrupt */
2046                         RtdPlxInterruptRead(dev) | ICS_DMA0_E);
2047                 /* Must be 2 steps.  See PLX app note about "Starting a DMA transfer" */
2048                 RtdDma0Control(dev, PLX_DMA_EN_BIT);    /* enable DMA (clear INTR?) */
2049                 RtdDma0Control(dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT);        /*start DMA */
2050                 DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n",
2051                         RtdPlxInterruptRead(dev), devpriv->intMask);
2052 #else /* USE_DMA */
2053                 RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
2054                 DPRINTK("rtd520: Transferring every 1/2 FIFO\n");
2055 #endif /* USE_DMA */
2056         }
2057
2058         /* BUG: start_src is ASSUMED to be TRIG_NOW */
2059         /* BUG? it seems like things are running before the "start" */
2060         RtdPacerStart(dev);     /* Start PACER */
2061         return 0;
2062 }
2063
2064 /*
2065   Stop a running data aquisition.
2066 */
2067 static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s)
2068 {
2069         u16 status;
2070
2071         RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
2072         RtdPacerStop(dev);      /* Stop PACER */
2073         RtdAdcConversionSource(dev, 0); /* software trigger only */
2074         RtdInterruptMask(dev, 0);
2075         devpriv->aiCount = 0;   /* stop and don't transfer any more */
2076 #ifdef USE_DMA
2077         if (devpriv->flags & DMA0_ACTIVE) {
2078                 RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
2079                         RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
2080                 abort_dma(dev, 0);
2081                 devpriv->flags &= ~DMA0_ACTIVE;
2082         }
2083 #endif /* USE_DMA */
2084         status = RtdInterruptStatus(dev);
2085         DPRINTK("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n", devpriv->intCount, status, 0xffff & RtdInterruptOverrunStatus(dev));
2086         return 0;
2087 }
2088
2089 /*
2090   Given a desired period and the clock period (both in ns),
2091   return the proper counter value (divider-1).
2092   Sets the original period to be the true value.
2093   Note: you have to check if the value is larger than the counter range!
2094 */
2095 static int rtd_ns_to_timer_base(unsigned int *nanosec,  /* desired period (in ns) */
2096         int round_mode, int base)
2097 {                               /* clock period (in ns) */
2098         int divider;
2099
2100         switch (round_mode) {
2101         case TRIG_ROUND_NEAREST:
2102         default:
2103                 divider = (*nanosec + base / 2) / base;
2104                 break;
2105         case TRIG_ROUND_DOWN:
2106                 divider = (*nanosec) / base;
2107                 break;
2108         case TRIG_ROUND_UP:
2109                 divider = (*nanosec + base - 1) / base;
2110                 break;
2111         }
2112         if (divider < 2)
2113                 divider = 2;    /* min is divide by 2 */
2114
2115         /* Note: we don't check for max, because different timers
2116            have different ranges */
2117
2118         *nanosec = base * divider;
2119         return divider - 1;     /* countdown is divisor+1 */
2120 }
2121
2122 /*
2123   Given a desired period (in ns),
2124   return the proper counter value (divider-1) for the internal clock.
2125   Sets the original period to be the true value.
2126 */
2127 static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
2128 {
2129         return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE);
2130 }
2131
2132 /*
2133   Output one (or more) analog values to a single port as fast as possible.
2134 */
2135 static int rtd_ao_winsn(comedi_device * dev,
2136         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
2137 {
2138         int i;
2139         int chan = CR_CHAN(insn->chanspec);
2140         int range = CR_RANGE(insn->chanspec);
2141
2142         /* Configure the output range (table index matches the range values) */
2143         RtdDacRange(dev, chan, range);
2144
2145         /* Writing a list of values to an AO channel is probably not
2146          * very useful, but that's how the interface is defined. */
2147         for (i = 0; i < insn->n; ++i) {
2148                 int val = data[i] << 3;
2149                 int stat = 0;   /* initialize to avoid bogus warning */
2150                 int ii;
2151
2152                 /* VERIFY: comedi range and offset conversions */
2153
2154                 if ((range > 1) /* bipolar */
2155                         &&(data[i] < 2048)) {
2156                         /* offset and sign extend */
2157                         val = (((int)data[i]) - 2048) << 3;
2158                 } else {        /* unipolor */
2159                         val = data[i] << 3;
2160                 }
2161
2162                 DPRINTK("comedi: rtd520 DAC chan=%d range=%d writing %d as 0x%x\n", chan, range, data[i], val);
2163
2164                 /* a typical programming sequence */
2165                 RtdDacFifoPut(dev, chan, val);  /* put the value in */
2166                 RtdDacUpdate(dev, chan);        /* trigger the conversion */
2167
2168                 devpriv->aoValue[chan] = data[i];       /* save for read back */
2169
2170                 for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) {
2171                         stat = RtdFifoStatus(dev);
2172                         /* 1 -> not empty */
2173                         if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY :
2174                                         FS_DAC2_NOT_EMPTY))
2175                                 break;
2176                         WAIT_QUIETLY;
2177                 }
2178                 if (ii >= RTD_DAC_TIMEOUT) {
2179                         DPRINTK("rtd520: Error: DAC never finished! FifoStatus=0x%x\n", stat ^ 0x6666);
2180                         return -ETIMEDOUT;
2181                 }
2182         }
2183
2184         /* return the number of samples read/written */
2185         return i;
2186 }
2187
2188 /* AO subdevices should have a read insn as well as a write insn.
2189  * Usually this means copying a value stored in devpriv. */
2190 static int rtd_ao_rinsn(comedi_device * dev,
2191         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
2192 {
2193         int i;
2194         int chan = CR_CHAN(insn->chanspec);
2195
2196         for (i = 0; i < insn->n; i++) {
2197                 data[i] = devpriv->aoValue[chan];
2198         }
2199
2200         return i;
2201 }
2202
2203 /*
2204    Write a masked set of bits and the read back the port.
2205    We track what the bits should be (i.e. we don't read the port first).
2206
2207    DIO devices are slightly special.  Although it is possible to
2208  * implement the insn_read/insn_write interface, it is much more
2209  * useful to applications if you implement the insn_bits interface.
2210  * This allows packed reading/writing of the DIO channels.  The
2211  * comedi core can convert between insn_bits and insn_read/write
2212  */
2213 static int rtd_dio_insn_bits(comedi_device * dev,
2214         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
2215 {
2216         if (insn->n != 2)
2217                 return -EINVAL;
2218
2219         /* The insn data is a mask in data[0] and the new data
2220          * in data[1], each channel cooresponding to a bit. */
2221         if (data[0]) {
2222                 s->state &= ~data[0];
2223                 s->state |= data[0] & data[1];
2224
2225                 /* Write out the new digital output lines */
2226                 RtdDio0Write(dev, s->state);
2227         }
2228         /* on return, data[1] contains the value of the digital
2229          * input lines. */
2230         data[1] = RtdDio0Read(dev);
2231
2232         /*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */
2233
2234         return 2;
2235 }
2236
2237 /*
2238   Configure one bit on a IO port as Input or Output (hence the name :-).
2239 */
2240 static int rtd_dio_insn_config(comedi_device * dev,
2241         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
2242 {
2243         int chan = CR_CHAN(insn->chanspec);
2244
2245         /* The input or output configuration of each digital line is
2246          * configured by a special insn_config instruction.  chanspec
2247          * contains the channel to be changed, and data[0] contains the
2248          * value COMEDI_INPUT or COMEDI_OUTPUT. */
2249         switch (data[0]) {
2250         case INSN_CONFIG_DIO_OUTPUT:
2251                 s->io_bits |= 1 << chan;        /* 1 means Out */
2252                 break;
2253         case INSN_CONFIG_DIO_INPUT:
2254                 s->io_bits &= ~(1 << chan);
2255                 break;
2256         case INSN_CONFIG_DIO_QUERY:
2257                 data[1] =
2258                         (s->
2259                         io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
2260                 return insn->n;
2261                 break;
2262         default:
2263                 return -EINVAL;
2264         }
2265
2266         DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits);
2267         /* TODO support digital match interrupts and strobes */
2268         RtdDioStatusWrite(dev, 0x01);   /* make Dio0Ctrl point to direction */
2269         RtdDio0CtrlWrite(dev, s->io_bits);      /* set direction 1 means Out */
2270         RtdDioStatusWrite(dev, 0);      /* make Dio0Ctrl clear interrupts */
2271
2272         /* port1 can only be all input or all output */
2273
2274         /* there are also 2 user input lines and 2 user output lines */
2275
2276         return 1;
2277 }
2278
2279 /*
2280  * A convenient macro that defines init_module() and cleanup_module(),
2281  * as necessary.
2282  */
2283 COMEDI_PCI_INITCLEANUP(rtd520Driver, rtd520_pci_table);