Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci1564.c
1 /**
2 @verbatim
3
4 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5
6         ADDI-DATA GmbH
7         Dieselstrasse 3
8         D-77833 Ottersweier
9         Tel: +19(0)7223/9493-0
10         Fax: +49(0)7223/9493-92
11         http://www.addi-data.com
12         info@addi-data.com
13
14 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 You should also find the complete GPL in the COPYING file accompanying this source code.
21
22 @endverbatim
23 */
24 /*
25
26   +-----------------------------------------------------------------------+
27   | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
28   +-----------------------------------------------------------------------+
29   | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
30   | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
31   +-------------------------------+---------------------------------------+
32   | Project     : APCI-1564       | Compiler   : GCC                      |
33   | Module name : hwdrv_apci1564.c| Version    : 2.96                     |
34   +-------------------------------+---------------------------------------+
35   | Project manager: Eric Stolz   | Date       :  02/12/2002              |
36   +-------------------------------+---------------------------------------+
37   | Description :   Hardware Layer Access For APCI-1564                   |
38   +-----------------------------------------------------------------------+
39   |                             UPDATES                                   |
40   +----------+-----------+------------------------------------------------+
41   |   Date   |   Author  |          Description of updates                |
42   +----------+-----------+------------------------------------------------+
43   |          |           |                                                |
44   |          |           |                                                |
45   |          |           |                                                |
46   +----------+-----------+------------------------------------------------+
47 */
48
49 /*********      Definitions for APCI-1564 card  *****/
50
51 #define APCI1564_ADDRESS_RANGE                          128
52
53 /* DIGITAL INPUT-OUTPUT DEFINE */
54 /* Input defines */
55 #define APCI1564_DIGITAL_IP                             0x04
56 #define APCI1564_DIGITAL_IP_INTERRUPT_MODE1             4
57 #define APCI1564_DIGITAL_IP_INTERRUPT_MODE2             8
58 #define APCI1564_DIGITAL_IP_IRQ                         16
59
60 /* Output defines */
61 #define APCI1564_DIGITAL_OP                             0x18
62 #define APCI1564_DIGITAL_OP_RW                          0
63 #define APCI1564_DIGITAL_OP_INTERRUPT                   4
64 #define APCI1564_DIGITAL_OP_IRQ                         12
65
66 /* Digital Input IRQ Function Selection */
67 #define ADDIDATA_OR                                     0
68 #define ADDIDATA_AND                                    1
69
70 /* Digital Input Interrupt Status */
71 #define APCI1564_DIGITAL_IP_INTERRUPT_STATUS            12
72
73 /* Digital Output Interrupt Status */
74 #define APCI1564_DIGITAL_OP_INTERRUPT_STATUS            8
75
76 /* Digital Input Interrupt Enable Disable. */
77 #define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE            0x4
78 #define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE           0xfffffffb
79
80 /* Digital Output Interrupt Enable Disable. */
81 #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE        0x1
82 #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE       0xfffffffe
83 #define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE         0x2
84 #define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE        0xfffffffd
85
86 /* TIMER COUNTER WATCHDOG DEFINES */
87
88 #define ADDIDATA_TIMER                                  0
89 #define ADDIDATA_COUNTER                                1
90 #define ADDIDATA_WATCHDOG                               2
91 #define APCI1564_DIGITAL_OP_WATCHDOG                    0x28
92 #define APCI1564_TIMER                                  0x48
93 #define APCI1564_COUNTER1                               0x0
94 #define APCI1564_COUNTER2                               0x20
95 #define APCI1564_COUNTER3                               0x40
96 #define APCI1564_COUNTER4                               0x60
97 #define APCI1564_TCW_SYNC_ENABLEDISABLE                 0
98 #define APCI1564_TCW_RELOAD_VALUE                       4
99 #define APCI1564_TCW_TIMEBASE                           8
100 #define APCI1564_TCW_PROG                               12
101 #define APCI1564_TCW_TRIG_STATUS                        16
102 #define APCI1564_TCW_IRQ                                20
103 #define APCI1564_TCW_WARN_TIMEVAL                       24
104 #define APCI1564_TCW_WARN_TIMEBASE                      28
105
106 /* Global variables */
107 static unsigned int ui_InterruptStatus_1564 = 0;
108 static unsigned int ui_InterruptData, ui_Type;
109
110 /*
111 +----------------------------------------------------------------------------+
112 | Function   Name   : int i_APCI1564_ConfigDigitalInput                      |
113 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
114 |                      struct comedi_insn *insn,unsigned int *data)                     |
115 +----------------------------------------------------------------------------+
116 | Task              : Configures the digital input Subdevice                 |
117 +----------------------------------------------------------------------------+
118 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
119 |                     unsigned int *data         : Data Pointer contains         |
120 |                                          configuration parameters as below |
121 |                                                                            |
122 |                         data[0]            : 1 Enable  Digital Input Interrupt |
123 |                                                                  0 Disable Digital Input Interrupt |
124 |                         data[1]            : 0 ADDIDATA Interrupt OR LOGIC     |
125 |                                                                : 1 ADDIDATA Interrupt AND LOGIC    |
126 |                         data[2]                        : Interrupt mask for the mode 1         |
127 |                         data[3]                        : Interrupt mask for the mode 2         |
128 |                                                                                                                                        |
129 +----------------------------------------------------------------------------+
130 | Output Parameters :   --                                                                                                       |
131 +----------------------------------------------------------------------------+
132 | Return Value      : TRUE  : No error occur                                 |
133 |                           : FALSE : Error occur. Return the error          |
134 |                                                                                |
135 +----------------------------------------------------------------------------+
136 */
137 static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev,
138                                          struct comedi_subdevice *s,
139                                          struct comedi_insn *insn,
140                                          unsigned int *data)
141 {
142         struct addi_private *devpriv = dev->private;
143
144         devpriv->tsk_Current = current;
145    /*******************************/
146         /* Set the digital input logic */
147    /*******************************/
148         if (data[0] == ADDIDATA_ENABLE) {
149                 data[2] = data[2] << 4;
150                 data[3] = data[3] << 4;
151                 outl(data[2],
152                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
153                         APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
154                 outl(data[3],
155                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
156                         APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
157                 if (data[1] == ADDIDATA_OR) {
158                         outl(0x4,
159                                 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
160                                 APCI1564_DIGITAL_IP_IRQ);
161                 }               /*  if  (data[1] == ADDIDATA_OR) */
162                 else {
163                         outl(0x6,
164                                 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
165                                 APCI1564_DIGITAL_IP_IRQ);
166                 }               /*  else if  (data[1] == ADDIDATA_OR) */
167         }                       /*  if  (data[0] == ADDIDATA_ENABLE) */
168         else {
169                 outl(0x0,
170                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
171                         APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
172                 outl(0x0,
173                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
174                         APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
175                 outl(0x0,
176                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
177                         APCI1564_DIGITAL_IP_IRQ);
178         }                       /*  else if  (data[0] == ADDIDATA_ENABLE) */
179
180         return insn->n;
181 }
182
183 static int apci1564_di_insn_bits(struct comedi_device *dev,
184                                  struct comedi_subdevice *s,
185                                  struct comedi_insn *insn,
186                                  unsigned int *data)
187 {
188         struct addi_private *devpriv = dev->private;
189
190         data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
191
192         return insn->n;
193 }
194
195 /*
196 +----------------------------------------------------------------------------+
197 | Function   Name   : int i_APCI1564_ConfigDigitalOutput                     |
198 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
199 |                      struct comedi_insn *insn,unsigned int *data)                     |
200 +----------------------------------------------------------------------------+
201 | Task              : Configures The Digital Output Subdevice.               |
202 +----------------------------------------------------------------------------+
203 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
204 |                     unsigned int *data         : Data Pointer contains             |
205 |                                          configuration parameters as below |
206 |                                                                            |
207 |                                         data[1]            : 1 Enable  VCC  Interrupt  |
208 |                                                                                  0 Disable VCC  Interrupt  |
209 |                                         data[2]            : 1 Enable  CC  Interrupt   |
210 |                                                                                  0 Disable CC  Interrupt   |
211 |                                                                                                                                        |
212 +----------------------------------------------------------------------------+
213 | Output Parameters :   --                                                                                                       |
214 +----------------------------------------------------------------------------+
215 | Return Value      : TRUE  : No error occur                                 |
216 |                           : FALSE : Error occur. Return the error          |
217 |                                                                                |
218 +----------------------------------------------------------------------------+
219 */
220 static int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev,
221                                           struct comedi_subdevice *s,
222                                           struct comedi_insn *insn,
223                                           unsigned int *data)
224 {
225         struct addi_private *devpriv = dev->private;
226         unsigned int ul_Command = 0;
227
228         if ((data[0] != 0) && (data[0] != 1)) {
229                 comedi_error(dev,
230                         "Not a valid Data !!! ,Data should be 1 or 0\n");
231                 return -EINVAL;
232         }                       /*  if  ((data[0]!=0) && (data[0]!=1)) */
233         if (data[0]) {
234                 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
235         }                       /*  if  (data[0]) */
236         else {
237                 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
238         }                       /*  else if  (data[0]) */
239         if (data[1] == ADDIDATA_ENABLE) {
240                 ul_Command = ul_Command | 0x1;
241         }                       /*  if  (data[1] == ADDIDATA_ENABLE) */
242         else {
243                 ul_Command = ul_Command & 0xFFFFFFFE;
244         }                       /*  else if  (data[1] == ADDIDATA_ENABLE) */
245         if (data[2] == ADDIDATA_ENABLE) {
246                 ul_Command = ul_Command | 0x2;
247         }                       /*  if  (data[2] == ADDIDATA_ENABLE) */
248         else {
249                 ul_Command = ul_Command & 0xFFFFFFFD;
250         }                       /*  else if  (data[2] == ADDIDATA_ENABLE) */
251         outl(ul_Command,
252                 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
253                 APCI1564_DIGITAL_OP_INTERRUPT);
254         ui_InterruptData =
255                 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
256                 APCI1564_DIGITAL_OP_INTERRUPT);
257         devpriv->tsk_Current = current;
258         return insn->n;
259 }
260
261 static int apci1564_do_insn_bits(struct comedi_device *dev,
262                                  struct comedi_subdevice *s,
263                                  struct comedi_insn *insn,
264                                  unsigned int *data)
265 {
266         struct addi_private *devpriv = dev->private;
267         unsigned int mask = data[0];
268         unsigned int bits = data[1];
269
270         s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
271                         APCI1564_DIGITAL_OP_RW);
272         if (mask) {
273                 s->state &= ~mask;
274                 s->state |= (bits & mask);
275
276                 outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
277                         APCI1564_DIGITAL_OP_RW);
278         }
279
280         data[1] = s->state;
281
282         return insn->n;
283 }
284
285 /*
286 +----------------------------------------------------------------------------+
287 | Function   Name   : int i_APCI1564_ConfigTimerCounterWatchdog              |
288 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
289 |                      struct comedi_insn *insn,unsigned int *data)                     |
290 +----------------------------------------------------------------------------+
291 | Task              : Configures The Timer , Counter or Watchdog             |
292 +----------------------------------------------------------------------------+
293 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
294 |                     unsigned int *data         : Data Pointer contains             |
295 |                                          configuration parameters as below |
296 |                                                                            |
297 |                                         data[0]            : 0 Configure As Timer      |
298 |                                                                                  1 Configure As Counter    |
299 |                                                                                  2 Configure As Watchdog   |
300 |                                         data[1]            : 1 Enable  Interrupt       |
301 |                                                                                  0 Disable Interrupt       |
302 |                                         data[2]            : Time Unit                 |
303 |                                         data[3]                        : Reload Value                      |
304 |                                         data[4]            : Timer Mode                |
305 |                                         data[5]                        : Timer Counter Watchdog Number|
306                               data[6]            :  Counter Direction
307 +----------------------------------------------------------------------------+
308 | Output Parameters :   --                                                                                                       |
309 +----------------------------------------------------------------------------+
310 | Return Value      : TRUE  : No error occur                                 |
311 |                           : FALSE : Error occur. Return the error          |
312 |                                                                                |
313 +----------------------------------------------------------------------------+
314 */
315 static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
316                                                  struct comedi_subdevice *s,
317                                                  struct comedi_insn *insn,
318                                                  unsigned int *data)
319 {
320         struct addi_private *devpriv = dev->private;
321         unsigned int ul_Command1 = 0;
322
323         devpriv->tsk_Current = current;
324         if (data[0] == ADDIDATA_WATCHDOG) {
325                 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
326
327                 /* Disable the watchdog */
328                 outl(0x0,
329                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
330                         APCI1564_TCW_PROG);
331                 /* Loading the Reload value */
332                 outl(data[3],
333                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
334                         APCI1564_TCW_RELOAD_VALUE);
335         }                       /*  if  (data[0]==ADDIDATA_WATCHDOG) */
336         else if (data[0] == ADDIDATA_TIMER) {
337                 /* First Stop The Timer */
338                 ul_Command1 =
339                         inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
340                         APCI1564_TCW_PROG);
341                 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
342                 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);  /* Stop The Timer */
343
344                 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
345                 if (data[1] == 1) {
346                         outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
347                         outl(0x0,
348                                 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
349                                 APCI1564_DIGITAL_IP_IRQ);
350                         outl(0x0,
351                                 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
352                                 APCI1564_DIGITAL_OP_IRQ);
353                         outl(0x0,
354                                 devpriv->i_IobaseAmcc +
355                                 APCI1564_DIGITAL_OP_WATCHDOG +
356                                 APCI1564_TCW_IRQ);
357                         outl(0x0,
358                                 devpriv->iobase + APCI1564_COUNTER1 +
359                                 APCI1564_TCW_IRQ);
360                         outl(0x0,
361                                 devpriv->iobase + APCI1564_COUNTER2 +
362                                 APCI1564_TCW_IRQ);
363                         outl(0x0,
364                                 devpriv->iobase + APCI1564_COUNTER3 +
365                                 APCI1564_TCW_IRQ);
366                         outl(0x0,
367                                 devpriv->iobase + APCI1564_COUNTER4 +
368                                 APCI1564_TCW_IRQ);
369                 }               /*  if  (data[1]==1) */
370                 else {
371                         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);  /* disable Timer interrupt */
372                 }               /*  else if  (data[1]==1) */
373
374                 /*  Loading Timebase */
375
376                 outl(data[2],
377                         devpriv->i_IobaseAmcc + APCI1564_TIMER +
378                         APCI1564_TCW_TIMEBASE);
379
380                 /* Loading the Reload value */
381                 outl(data[3],
382                         devpriv->i_IobaseAmcc + APCI1564_TIMER +
383                         APCI1564_TCW_RELOAD_VALUE);
384
385                 ul_Command1 =
386                         inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
387                         APCI1564_TCW_PROG);
388                 ul_Command1 =
389                         (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
390                 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);  /* mode 2 */
391         }                       /*  else if  (data[0]==ADDIDATA_TIMER) */
392         else if (data[0] == ADDIDATA_COUNTER) {
393                 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
394                 devpriv->b_ModeSelectRegister = data[5];
395
396                 /* First Stop The Counter */
397                 ul_Command1 =
398                         inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
399                         APCI1564_TCW_PROG);
400                 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
401                 outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG);        /* Stop The Timer */
402
403       /************************/
404                 /* Set the reload value */
405       /************************/
406                 outl(data[3],
407                         devpriv->iobase + ((data[5] - 1) * 0x20) +
408                         APCI1564_TCW_RELOAD_VALUE);
409
410       /******************************/
411                 /* Set the mode :             */
412                 /* - Disable the hardware     */
413                 /* - Disable the counter mode */
414                 /* - Disable the warning      */
415                 /* - Disable the reset        */
416                 /* - Disable the timer mode   */
417                 /* - Enable the counter mode  */
418       /******************************/
419                 ul_Command1 =
420                         (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
421                         (unsigned int) ((unsigned int) data[4] << 16UL);
422                 outl(ul_Command1,
423                         devpriv->iobase + ((data[5] - 1) * 0x20) +
424                         APCI1564_TCW_PROG);
425
426                 /*  Enable or Disable Interrupt */
427                 ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
428                 outl(ul_Command1,
429                         devpriv->iobase + ((data[5] - 1) * 0x20) +
430                         APCI1564_TCW_PROG);
431
432       /*****************************/
433                 /* Set the Up/Down selection */
434       /*****************************/
435                 ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
436                 outl(ul_Command1,
437                         devpriv->iobase + ((data[5] - 1) * 0x20) +
438                         APCI1564_TCW_PROG);
439         }                       /*  else if  (data[0]==ADDIDATA_COUNTER) */
440         else {
441                 printk(" Invalid subdevice.");
442         }                       /*  else if  (data[0]==ADDIDATA_WATCHDOG) */
443
444         return insn->n;
445 }
446
447 /*
448 +----------------------------------------------------------------------------+
449 | Function   Name   : int i_APCI1564_StartStopWriteTimerCounterWatchdog      |
450 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
451 |                      struct comedi_insn *insn,unsigned int *data)                     |
452 +----------------------------------------------------------------------------+
453 | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
454 +----------------------------------------------------------------------------+
455 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
456 |                     unsigned int *data         : Data Pointer contains             |
457 |                                          configuration parameters as below |
458 |                                                                            |
459 |                                         data[0]            : 0 Timer                   |
460 |                                                                                  1 Counter                 |
461 |                                                                                  2 Watchdog                    |                             |                                                 data[1]            : 1 Start                   |
462 |                                                                                  0 Stop                    |
463 |                                                  2 Trigger                     |
464 |                                                    Clear (Only Counter)    |
465 +----------------------------------------------------------------------------+
466 | Output Parameters :   --                                                                                                       |
467 +----------------------------------------------------------------------------+
468 | Return Value      : TRUE  : No error occur                                 |
469 |                           : FALSE : Error occur. Return the error          |
470 |                                                                                |
471 +----------------------------------------------------------------------------+
472 */
473 static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
474                                                          struct comedi_subdevice *s,
475                                                          struct comedi_insn *insn,
476                                                          unsigned int *data)
477 {
478         struct addi_private *devpriv = dev->private;
479         unsigned int ul_Command1 = 0;
480
481         if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
482                 switch (data[1]) {
483                 case 0: /* stop the watchdog */
484                         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG);    /* disable the watchdog */
485                         break;
486                 case 1: /* start the watchdog */
487                         outl(0x0001,
488                                 devpriv->i_IobaseAmcc +
489                                 APCI1564_DIGITAL_OP_WATCHDOG +
490                                 APCI1564_TCW_PROG);
491                         break;
492                 case 2: /* Software trigger */
493                         outl(0x0201,
494                                 devpriv->i_IobaseAmcc +
495                                 APCI1564_DIGITAL_OP_WATCHDOG +
496                                 APCI1564_TCW_PROG);
497                         break;
498                 default:
499                         printk("\nSpecified functionality does not exist\n");
500                         return -EINVAL;
501                 }               /*  switch (data[1]) */
502         }                       /*  if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
503         if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
504                 if (data[1] == 1) {
505                         ul_Command1 =
506                                 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
507                                 APCI1564_TCW_PROG);
508                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
509
510                         /* Enable the Timer */
511                         outl(ul_Command1,
512                                 devpriv->i_IobaseAmcc + APCI1564_TIMER +
513                                 APCI1564_TCW_PROG);
514                 }               /*  if  (data[1]==1) */
515                 else if (data[1] == 0) {
516                         /* Stop The Timer */
517
518                         ul_Command1 =
519                                 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
520                                 APCI1564_TCW_PROG);
521                         ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
522                         outl(ul_Command1,
523                                 devpriv->i_IobaseAmcc + APCI1564_TIMER +
524                                 APCI1564_TCW_PROG);
525                 }               /*  else if(data[1]==0) */
526         }                       /*  if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
527         if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
528                 ul_Command1 =
529                         inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
530                                         1) * 0x20) + APCI1564_TCW_PROG);
531                 if (data[1] == 1) {
532                         /* Start the Counter subdevice */
533                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
534                 }               /*  if  (data[1] == 1) */
535                 else if (data[1] == 0) {
536                         /*  Stops the Counter subdevice */
537                         ul_Command1 = 0;
538
539                 }               /*  else if  (data[1] == 0) */
540                 else if (data[1] == 2) {
541                         /*  Clears the Counter subdevice */
542                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
543                 }               /*  else if  (data[1] == 3) */
544                 outl(ul_Command1,
545                         devpriv->iobase + ((devpriv->b_ModeSelectRegister -
546                                         1) * 0x20) + APCI1564_TCW_PROG);
547         }                       /*  if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
548         return insn->n;
549 }
550
551 /*
552 +----------------------------------------------------------------------------+
553 | Function   Name   : int i_APCI1564_ReadTimerCounterWatchdog                |
554 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
555 |                      struct comedi_insn *insn,unsigned int *data)                     |
556 +----------------------------------------------------------------------------+
557 | Task              : Read The Selected Timer , Counter or Watchdog          |
558 +----------------------------------------------------------------------------+
559 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
560 |                     unsigned int *data         : Data Pointer contains             |
561 |                                          configuration parameters as below |
562 |                                                                            |
563
564 +----------------------------------------------------------------------------+
565 | Output Parameters :   --                                                                                                       |
566 +----------------------------------------------------------------------------+
567 | Return Value      : TRUE  : No error occur                                 |
568 |                           : FALSE : Error occur. Return the error          |
569 |                                                                                |
570 +----------------------------------------------------------------------------+
571 */
572 static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
573                                                struct comedi_subdevice *s,
574                                                struct comedi_insn *insn,
575                                                unsigned int *data)
576 {
577         struct addi_private *devpriv = dev->private;
578         unsigned int ul_Command1 = 0;
579
580         if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
581                 /*  Stores the status of the Watchdog */
582                 data[0] =
583                         inl(devpriv->i_IobaseAmcc +
584                         APCI1564_DIGITAL_OP_WATCHDOG +
585                         APCI1564_TCW_TRIG_STATUS) & 0x1;
586                 data[1] =
587                         inl(devpriv->i_IobaseAmcc +
588                         APCI1564_DIGITAL_OP_WATCHDOG);
589         }                       /*  if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
590         else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
591                 /*  Stores the status of the Timer */
592                 data[0] =
593                         inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
594                         APCI1564_TCW_TRIG_STATUS) & 0x1;
595
596                 /*  Stores the Actual value of the Timer */
597                 data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
598         }                       /*  else if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
599         else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
600                 /*  Read the Counter Actual Value. */
601                 data[0] =
602                         inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
603                                         1) * 0x20) +
604                         APCI1564_TCW_SYNC_ENABLEDISABLE);
605                 ul_Command1 =
606                         inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
607                                         1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
608
609       /***********************************/
610                 /* Get the software trigger status */
611       /***********************************/
612                 data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
613
614       /***********************************/
615                 /* Get the hardware trigger status */
616       /***********************************/
617                 data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
618
619       /*********************************/
620                 /* Get the software clear status */
621       /*********************************/
622                 data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
623
624       /***************************/
625                 /* Get the overflow status */
626       /***************************/
627                 data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
628         }                       /*  else  if  (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
629         else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
630                 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
631                 && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
632                 printk("\n Invalid Subdevice !!!\n");
633         }                       /*  else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) */
634         return insn->n;
635 }
636
637 /*
638 +----------------------------------------------------------------------------+
639 | Function   Name   :  int i_APCI1564_ReadInterruptStatus                    |
640 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
641 |                      struct comedi_insn *insn,unsigned int *data)                     |
642 +----------------------------------------------------------------------------+
643 | Task              :Reads the interrupt status register                     |
644 +----------------------------------------------------------------------------+
645 | Input Parameters  :                                                        |
646 +----------------------------------------------------------------------------+
647 | Output Parameters :   --                                                                                                       |
648 +----------------------------------------------------------------------------+
649 | Return Value      :                                                        |
650 |                                                                                |
651 +----------------------------------------------------------------------------+
652 */
653
654 static int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev,
655                                           struct comedi_subdevice *s,
656                                           struct comedi_insn *insn,
657                                           unsigned int *data)
658 {
659         *data = ui_Type;
660         return insn->n;
661 }
662
663 /*
664 +----------------------------------------------------------------------------+
665 | Function   Name   : static void v_APCI1564_Interrupt                                       |
666 |                                         (int irq , void *d)      |
667 +----------------------------------------------------------------------------+
668 | Task              : Interrupt handler for the interruptible digital inputs |
669 +----------------------------------------------------------------------------+
670 | Input Parameters  : int irq                 : irq number                   |
671 |                     void *d                 : void pointer                 |
672 +----------------------------------------------------------------------------+
673 | Output Parameters :   --                                                                                                       |
674 +----------------------------------------------------------------------------+
675 | Return Value      : TRUE  : No error occur                                 |
676 |                           : FALSE : Error occur. Return the error          |
677 |                                                                                |
678 +----------------------------------------------------------------------------+
679 */
680 static void v_APCI1564_Interrupt(int irq, void *d)
681 {
682         struct comedi_device *dev = d;
683         struct addi_private *devpriv = dev->private;
684         unsigned int ui_DO, ui_DI;
685         unsigned int ui_Timer;
686         unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
687         unsigned int ul_Command2 = 0;
688
689         ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
690                 APCI1564_DIGITAL_IP_IRQ) & 0x01;
691         ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
692                 APCI1564_DIGITAL_OP_IRQ) & 0x01;
693         ui_Timer =
694                 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
695                 APCI1564_TCW_IRQ) & 0x01;
696         ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 +
697                 APCI1564_TCW_IRQ) & 0x1;
698         ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 +
699                 APCI1564_TCW_IRQ) & 0x1;
700         ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 +
701                 APCI1564_TCW_IRQ) & 0x1;
702         ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 +
703                 APCI1564_TCW_IRQ) & 0x1;
704         if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
705                 && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
706                 printk("\nInterrupt from unknown source\n");
707         }                       /*  if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) */
708
709         if (ui_DI == 1) {
710                 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
711                         APCI1564_DIGITAL_IP_IRQ);
712                 outl(0x0,
713                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
714                         APCI1564_DIGITAL_IP_IRQ);
715                 ui_InterruptStatus_1564 =
716                         inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
717                         APCI1564_DIGITAL_IP_INTERRUPT_STATUS);
718                 ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
719                 send_sig(SIGIO, devpriv->tsk_Current, 0);       /*  send signal to the sample */
720                 outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ);     /* enable the interrupt */
721                 return;
722         }
723
724         if (ui_DO == 1) {
725                 /*  Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
726                 ui_Type =
727                         inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
728                         APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
729                 /* Disable the  Interrupt */
730                 outl(0x0,
731                         devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
732                         APCI1564_DIGITAL_OP_INTERRUPT);
733
734                 /* Sends signal to user space */
735                 send_sig(SIGIO, devpriv->tsk_Current, 0);
736
737         }                       /*  if  (ui_DO) */
738
739         if (ui_Timer == 1) {
740                 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
741                 if (devpriv->b_TimerSelectMode) {
742
743                         /*  Disable Timer Interrupt */
744                         ul_Command2 =
745                                 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
746                                     APCI1564_TCW_PROG);
747                         outl(0x0,
748                              devpriv->i_IobaseAmcc + APCI1564_TIMER +
749                              APCI1564_TCW_PROG);
750
751                         /* Send a signal to from kernel to user space */
752                         send_sig(SIGIO, devpriv->tsk_Current, 0);
753
754                         /*  Enable Timer Interrupt */
755
756                         outl(ul_Command2,
757                              devpriv->i_IobaseAmcc + APCI1564_TIMER +
758                              APCI1564_TCW_PROG);
759                 }
760         }/* if  (ui_Timer == 1) */
761
762
763         if (ui_C1 == 1) {
764                 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
765                 if (devpriv->b_TimerSelectMode) {
766
767                         /*  Disable Counter Interrupt */
768                         ul_Command2 =
769                                 inl(devpriv->iobase + APCI1564_COUNTER1 +
770                                     APCI1564_TCW_PROG);
771                         outl(0x0,
772                              devpriv->iobase + APCI1564_COUNTER1 +
773                              APCI1564_TCW_PROG);
774
775                         /* Send a signal to from kernel to user space */
776                         send_sig(SIGIO, devpriv->tsk_Current, 0);
777
778                         /*  Enable Counter Interrupt */
779                         outl(ul_Command2,
780                              devpriv->iobase + APCI1564_COUNTER1 +
781                              APCI1564_TCW_PROG);
782                 }
783         } /* if  (ui_C1 == 1) */
784
785         if (ui_C2 == 1) {
786                 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
787                 if (devpriv->b_TimerSelectMode) {
788
789                         /*  Disable Counter Interrupt */
790                         ul_Command2 =
791                                 inl(devpriv->iobase + APCI1564_COUNTER2 +
792                                     APCI1564_TCW_PROG);
793                         outl(0x0,
794                              devpriv->iobase + APCI1564_COUNTER2 +
795                              APCI1564_TCW_PROG);
796
797                         /* Send a signal to from kernel to user space */
798                         send_sig(SIGIO, devpriv->tsk_Current, 0);
799
800                         /*  Enable Counter Interrupt */
801                         outl(ul_Command2,
802                              devpriv->iobase + APCI1564_COUNTER2 +
803                              APCI1564_TCW_PROG);
804                 }
805         } /*  if  ((ui_C2 == 1) */
806
807         if (ui_C3 == 1) {
808                 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
809                 if (devpriv->b_TimerSelectMode) {
810
811                         /*  Disable Counter Interrupt */
812                         ul_Command2 =
813                                 inl(devpriv->iobase + APCI1564_COUNTER3 +
814                                     APCI1564_TCW_PROG);
815                         outl(0x0,
816                              devpriv->iobase + APCI1564_COUNTER3 +
817                              APCI1564_TCW_PROG);
818
819                         /* Send a signal to from kernel to user space */
820                         send_sig(SIGIO, devpriv->tsk_Current, 0);
821
822                         /*  Enable Counter Interrupt */
823                         outl(ul_Command2,
824                              devpriv->iobase + APCI1564_COUNTER3 +
825                              APCI1564_TCW_PROG);
826                 }
827         }       /*  if ((ui_C3 == 1) */
828
829         if (ui_C4 == 1) {
830                 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
831                 if (devpriv->b_TimerSelectMode) {
832
833                         /*  Disable Counter Interrupt */
834                         ul_Command2 =
835                                 inl(devpriv->iobase + APCI1564_COUNTER4 +
836                                     APCI1564_TCW_PROG);
837                         outl(0x0,
838                              devpriv->iobase + APCI1564_COUNTER4 +
839                              APCI1564_TCW_PROG);
840
841                         /* Send a signal to from kernel to user space */
842                         send_sig(SIGIO, devpriv->tsk_Current, 0);
843
844                         /*  Enable Counter Interrupt */
845                         outl(ul_Command2,
846                              devpriv->iobase + APCI1564_COUNTER4 +
847                              APCI1564_TCW_PROG);
848                 }
849         }       /*  if (ui_C4 == 1) */
850         return;
851 }
852
853 /*
854 +----------------------------------------------------------------------------+
855 | Function   Name   : int i_APCI1564_Reset(struct comedi_device *dev)               |                                                       |
856 +----------------------------------------------------------------------------+
857 | Task              :resets all the registers                                |
858 +----------------------------------------------------------------------------+
859 | Input Parameters  : struct comedi_device *dev
860 +----------------------------------------------------------------------------+
861 | Output Parameters :   --                                                                                                       |
862 +----------------------------------------------------------------------------+
863 | Return Value      :                                                        |
864 |                                                                                |
865 +----------------------------------------------------------------------------+
866 */
867
868 static int i_APCI1564_Reset(struct comedi_device *dev)
869 {
870         struct addi_private *devpriv = dev->private;
871
872         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);     /* disable the interrupts */
873         inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);      /* Reset the interrupt status register */
874         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); /* Disable the and/or interrupt */
875         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
876         devpriv->b_DigitalOutputRegister = 0;
877         ui_Type = 0;
878         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); /* Resets the output channels */
879         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT);       /* Disables the interrupt. */
880         outl(0x0,
881                 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
882                 APCI1564_TCW_RELOAD_VALUE);
883         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER);
884         outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);
885
886         outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG);
887         outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG);
888         outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG);
889         outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG);
890         return 0;
891 }