ef21f03fc961f5e8e78bf1c133d671c595d2afdf
[safe/jmp/linux-2.6] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci3501.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 shoud 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-3501       | Compiler   : GCC                      |
33   | Module name : hwdrv_apci3501.c| Version    : 2.96                     |
34   +-------------------------------+---------------------------------------+
35   | Project manager: Eric Stolz   | Date       :  02/12/2002              |
36   +-------------------------------+---------------------------------------+
37   | Description :   Hardware Layer Acces For APCI-3501                    |
38   +-----------------------------------------------------------------------+
39   |                             UPDATES                                   |
40   +----------+-----------+------------------------------------------------+
41   |   Date   |   Author  |          Description of updates                |
42   +----------+-----------+------------------------------------------------+
43   |          |           |                                                |
44   |          |           |                                                |
45   |          |           |                                                |
46   +----------+-----------+------------------------------------------------+
47 */
48
49 /*
50 +----------------------------------------------------------------------------+
51 |                               Included files                               |
52 +----------------------------------------------------------------------------+
53 */
54 #include "hwdrv_apci3501.h"
55
56 /*
57 +----------------------------------------------------------------------------+
58 | Function   Name   : int i_APCI3501_ReadDigitalInput                    |
59 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
60 |                      struct comedi_insn *insn,unsigned int *data)                     |
61 +----------------------------------------------------------------------------+
62 | Task              : Read  value  of the selected channel or port           |
63 +----------------------------------------------------------------------------+
64 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
65 |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
66 |                     unsigned int *data              : Data Pointer to read status  |
67 +----------------------------------------------------------------------------+
68 | Output Parameters :   --                                                                                                       |
69 +----------------------------------------------------------------------------+
70 | Return Value      : TRUE  : No error occur                                 |
71 |                           : FALSE : Error occur. Return the error          |
72 |                                                                                |
73 +----------------------------------------------------------------------------+
74 */
75
76 int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
77         struct comedi_insn *insn, unsigned int *data)
78 {
79         unsigned int ui_Temp;
80         unsigned int ui_NoOfChannel;
81         ui_NoOfChannel = CR_CHAN(insn->chanspec);
82         ui_Temp = data[0];
83         *data = inl(devpriv->iobase + APCI3501_DIGITAL_IP);
84         if (ui_Temp == 0) {
85                 *data = (*data >> ui_NoOfChannel) & 0x1;
86         }                       /* if  (ui_Temp==0) */
87         else {
88                 if (ui_Temp == 1) {
89
90                         *data = *data & 0x3;
91                 }               /* if  (ui_Temp==1) */
92                 else {
93                         printk("\nSpecified channel not supported \n");
94                 }               /* elseif  (ui_Temp==1) */
95         }                       /* elseif  (ui_Temp==0) */
96         return insn->n;
97 }
98
99 /*
100 +----------------------------------------------------------------------------+
101 | Function   Name   : int i_APCI3501_ConfigDigitalOutput                     |
102 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
103 |                      struct comedi_insn *insn,unsigned int *data)                     |
104 +----------------------------------------------------------------------------+
105 | Task              : Configures The Digital Output Subdevice.               |
106 +----------------------------------------------------------------------------+
107 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
108 |                     unsigned int *data         : Data Pointer contains             |
109 |                                          configuration parameters as below |
110 |                                                                            |
111 |                                         data[1]            : 1 Enable  VCC  Interrupt  |
112 |                                                                                  0 Disable VCC  Interrupt  |
113 |                                         data[2]            : 1 Enable  CC  Interrupt   |
114 |                                                                                  0 Disable CC  Interrupt   |
115 |                                                                                                                                        |
116 +----------------------------------------------------------------------------+
117 | Output Parameters :   --                                                                                                       |
118 +----------------------------------------------------------------------------+
119 | Return Value      : TRUE  : No error occur                                 |
120 |                           : FALSE : Error occur. Return the error          |
121 |                                                                                |
122 +----------------------------------------------------------------------------+
123 */
124 int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
125         struct comedi_insn *insn, unsigned int *data)
126 {
127
128         if ((data[0] != 0) && (data[0] != 1)) {
129                 comedi_error(dev,
130                         "Not a valid Data !!! ,Data should be 1 or 0\n");
131                 return -EINVAL;
132         }                       /* if  ( (data[0]!=0) && (data[0]!=1) ) */
133         if (data[0]) {
134                 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
135         }                       /*  if  (data[0]) */
136         else {
137                 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
138         }                       /* else if  (data[0]) */
139         return insn->n;
140 }
141
142 /*
143 +----------------------------------------------------------------------------+
144 | Function   Name   : int i_APCI3501_WriteDigitalOutput                      |
145 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
146 |                      struct comedi_insn *insn,unsigned int *data)                     |
147 +----------------------------------------------------------------------------+
148 | Task              : writes To the digital Output Subdevice                 |
149 +----------------------------------------------------------------------------+
150 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
151 |                     struct comedi_subdevice *s     : Subdevice Pointer            |
152 |                     struct comedi_insn *insn       : Insn Structure Pointer       |
153 |                     unsigned int *data          : Data Pointer contains        |
154 |                                          configuration parameters as below |
155 |                                                                            |
156 +----------------------------------------------------------------------------+
157 | Output Parameters :   --                                                                                                       |
158 +----------------------------------------------------------------------------+
159 | Return Value      : TRUE  : No error occur                                 |
160 |                           : FALSE : Error occur. Return the error          |
161 |                                                                                |
162 +----------------------------------------------------------------------------+
163 */
164 int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
165         struct comedi_insn *insn, unsigned int *data)
166 {
167         unsigned int ui_Temp, ui_Temp1;
168         unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
169         if (devpriv->b_OutputMemoryStatus) {
170                 ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
171         }                       /* if(devpriv->b_OutputMemoryStatus ) */
172         else {
173                 ui_Temp = 0;
174         }                       /* if(devpriv->b_OutputMemoryStatus ) */
175         if (data[3] == 0) {
176                 if (data[1] == 0) {
177                         data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
178                         outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP);
179                 }               /* if(data[1]==0) */
180                 else {
181                         if (data[1] == 1) {
182                                 data[0] = (data[0] << (2 * data[2])) | ui_Temp;
183                                 outl(data[0],
184                                         devpriv->iobase + APCI3501_DIGITAL_OP);
185                         }       /*  if(data[1]==1) */
186                         else {
187                                 printk("\nSpecified channel not supported\n");
188                         }       /* else if(data[1]==1) */
189                 }               /* elseif(data[1]==0) */
190         }                       /* if(data[3]==0) */
191         else {
192                 if (data[3] == 1) {
193                         if (data[1] == 0) {
194                                 data[0] = ~data[0] & 0x1;
195                                 ui_Temp1 = 1;
196                                 ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
197                                 ui_Temp = ui_Temp | ui_Temp1;
198                                 data[0] =
199                                         (data[0] << ui_NoOfChannel) ^
200                                         0xffffffff;
201                                 data[0] = data[0] & ui_Temp;
202                                 outl(data[0],
203                                         devpriv->iobase + APCI3501_DIGITAL_OP);
204                         }       /* if(data[1]==0) */
205                         else {
206                                 if (data[1] == 1) {
207                                         data[0] = ~data[0] & 0x3;
208                                         ui_Temp1 = 3;
209                                         ui_Temp1 = ui_Temp1 << 2 * data[2];
210                                         ui_Temp = ui_Temp | ui_Temp1;
211                                         data[0] =
212                                                 ((data[0] << (2 *
213                                                                 data[2])) ^
214                                                 0xffffffff) & ui_Temp;
215                                         outl(data[0],
216                                                 devpriv->iobase +
217                                                 APCI3501_DIGITAL_OP);
218                                 }       /*  if(data[1]==1) */
219                                 else {
220                                         printk("\nSpecified channel not supported\n");
221                                 }       /* else if(data[1]==1) */
222                         }       /* elseif(data[1]==0) */
223                 }               /* if(data[3]==1); */
224                 else {
225                         printk("\nSpecified functionality does not exist\n");
226                         return -EINVAL;
227                 }               /* if else data[3]==1) */
228         }                       /* if else data[3]==0) */
229         return insn->n;
230 }
231
232 /*
233 +----------------------------------------------------------------------------+
234 | Function   Name   : int i_APCI3501_ReadDigitalOutput                       |
235 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
236 |                      struct comedi_insn *insn,unsigned int *data)                     |
237 +----------------------------------------------------------------------------+
238 | Task              : Read  value  of the selected channel or port           |
239 +----------------------------------------------------------------------------+
240 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
241 |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
242 |                     unsigned int *data              : Data Pointer to read status  |
243 +----------------------------------------------------------------------------+
244 | Output Parameters :   --                                                                                                       |
245 +----------------------------------------------------------------------------+
246 | Return Value      : TRUE  : No error occur                                 |
247 |                           : FALSE : Error occur. Return the error          |
248 |                                                                                |
249 +----------------------------------------------------------------------------+
250 */
251 int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
252         struct comedi_insn *insn, unsigned int *data)
253 {
254         unsigned int ui_Temp;
255         unsigned int ui_NoOfChannel;
256
257         ui_NoOfChannel = CR_CHAN(insn->chanspec);
258         ui_Temp = data[0];
259         *data = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
260         if (ui_Temp == 0) {
261                 *data = (*data >> ui_NoOfChannel) & 0x1;
262         }                       /*  if  (ui_Temp==0) */
263         else {
264                 if (ui_Temp == 1) {
265                         *data = *data & 0x3;
266
267                 }               /*  if  (ui_Temp==1) */
268                 else {
269                         printk("\nSpecified channel not supported \n");
270                 }               /*  else if (ui_Temp==1) */
271         }                       /*  else if  (ui_Temp==0) */
272         return insn->n;
273 }
274
275 /*
276 +----------------------------------------------------------------------------+
277 | Function   Name   : int i_APCI3501_ConfigAnalogOutput                      |
278 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
279 |                      struct comedi_insn *insn,unsigned int *data)                     |
280 +----------------------------------------------------------------------------+
281 | Task              : Configures The Analog Output Subdevice                 |
282 +----------------------------------------------------------------------------+
283 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
284 |                     struct comedi_subdevice *s     : Subdevice Pointer            |
285 |                     struct comedi_insn *insn       : Insn Structure Pointer       |
286 |                     unsigned int *data          : Data Pointer contains        |
287 |                                          configuration parameters as below |
288 |                                                                            |
289 |                                       data[0]            : Voltage Mode                |
290 |                                                0:Mode 0                    |
291 |                                                1:Mode 1                    |
292 |                                                                            |
293 +----------------------------------------------------------------------------+
294 | Output Parameters :   --                                                                                                       |
295 +----------------------------------------------------------------------------+
296 | Return Value      : TRUE  : No error occur                                 |
297 |                           : FALSE : Error occur. Return the error          |
298 |                                                                                |
299 +----------------------------------------------------------------------------+
300 */
301 int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
302         struct comedi_insn *insn, unsigned int *data)
303 {
304         outl(data[0],
305                 devpriv->iobase + APCI3501_ANALOG_OUTPUT +
306                 APCI3501_AO_VOLT_MODE);
307
308         if (data[0]) {
309                 devpriv->b_InterruptMode = MODE1;
310         } else {
311                 devpriv->b_InterruptMode = MODE0;
312         }
313         return insn->n;
314 }
315
316 /*
317 +----------------------------------------------------------------------------+
318 | Function   Name   : int i_APCI3501_WriteAnalogOutput                       |
319 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
320 |                      struct comedi_insn *insn,unsigned int *data)                     |
321 +----------------------------------------------------------------------------+
322 | Task              : Writes To the Selected Anlog Output Channel            |
323 +----------------------------------------------------------------------------+
324 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
325 |                     struct comedi_subdevice *s     : Subdevice Pointer            |
326 |                     struct comedi_insn *insn       : Insn Structure Pointer       |
327 |                     unsigned int *data          : Data Pointer contains        |
328 |                                          configuration parameters as below |
329 |                                                                            |
330 |                                                                            |
331 +----------------------------------------------------------------------------+
332 | Output Parameters :   --                                                                                                       |
333 +----------------------------------------------------------------------------+
334 | Return Value      : TRUE  : No error occur                                 |
335 |                           : FALSE : Error occur. Return the error          |
336 |                                                                                |
337 +----------------------------------------------------------------------------+
338 */
339 int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
340         struct comedi_insn *insn, unsigned int *data)
341 {
342         unsigned int ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
343
344         ul_Channel_no = CR_CHAN(insn->chanspec);
345
346         if (devpriv->b_InterruptMode == MODE1) {
347                 ul_Polarity = 0x80000000;
348                 if ((*data < 0) || (*data > 16384)) {
349                         printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
350                 }
351
352         }                       /*  end if(devpriv->b_InterruptMode==MODE1) */
353         else {
354                 ul_Polarity = 0;
355                 if ((*data < 0) || (*data > 8192)) {
356                         printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
357                 }
358
359         }                       /*  end else */
360
361         if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) {
362                 printk("\nIn WriteAnalogOutput :: Not Valid Channel\n");
363         }                       /*  end if((ul_Channel_no<0)||(ul_Channel_no>7)) */
364
365         ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
366
367         while (ul_DAC_Ready == 0) {
368                 ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
369                 ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
370         }
371
372         if (ul_DAC_Ready) {
373 /* Output the Value on the output channels. */
374                 ul_Command1 =
375                         (unsigned int) ((unsigned int) (ul_Channel_no & 0xFF) |
376                         (unsigned int) ((*data << 0x8) & 0x7FFFFF00L) |
377                         (unsigned int) (ul_Polarity));
378                 outl(ul_Command1,
379                         devpriv->iobase + APCI3501_ANALOG_OUTPUT +
380                         APCI3501_AO_PROG);
381         }
382
383         return insn->n;
384 }
385
386 /*
387 +----------------------------------------------------------------------------+
388 | Function   Name   : int i_APCI3501_ConfigTimerCounterWatchdog              |
389 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
390 |                      struct comedi_insn *insn,unsigned int *data)                     |
391 +----------------------------------------------------------------------------+
392 | Task              : Configures The Timer , Counter or Watchdog             |
393 +----------------------------------------------------------------------------+
394 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
395 |                     unsigned int *data         : Data Pointer contains             |
396 |                                          configuration parameters as below |
397 |                                                                            |
398 |                                         data[0]            : 0 Configure As Timer      |
399 |                                                                                  1 Configure As Counter    |
400 |                                                                                  2 Configure As Watchdog   |
401 |                                         data[1]            : 1 Enable  Interrupt       |
402 |                                                                                  0 Disable Interrupt       |
403 |                                         data[2]            : Time Unit                 |
404 |                                         data[3]                        : Reload Value                      |
405 +----------------------------------------------------------------------------+
406 | Output Parameters :   --                                                                                                       |
407 +----------------------------------------------------------------------------+
408 | Return Value      : TRUE  : No error occur                                 |
409 |                           : FALSE : Error occur. Return the error          |
410 |                                                                                |
411 +----------------------------------------------------------------------------+
412 */
413 int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
414         struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
415 {
416         unsigned int ul_Command1 = 0;
417         devpriv->tsk_Current = current;
418         if (data[0] == ADDIDATA_WATCHDOG) {
419
420                 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
421                 /* Disable the watchdog */
422                 outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     /* disable Wa */
423
424                 if (data[1] == 1) {
425                         /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
426                         outl(0x02,
427                                 devpriv->iobase + APCI3501_WATCHDOG +
428                                 APCI3501_TCW_PROG);
429                 } else {
430                         outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     /* disable Timer interrupt */
431                 }
432
433                 /* Loading the Timebase value */
434                 outl(data[2],
435                         devpriv->iobase + APCI3501_WATCHDOG +
436                         APCI3501_TCW_TIMEBASE);
437
438                 /* Loading the Reload value */
439                 outl(data[3],
440                         devpriv->iobase + APCI3501_WATCHDOG +
441                         APCI3501_TCW_RELOAD_VALUE);
442                 /* Set the mode */
443                 ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL;      /* e2->e0 */
444                 outl(ul_Command1,
445                         devpriv->iobase + APCI3501_WATCHDOG +
446                         APCI3501_TCW_PROG);
447         }                       /* end if(data[0]==ADDIDATA_WATCHDOG) */
448
449         else if (data[0] == ADDIDATA_TIMER) {
450                 /* First Stop The Timer */
451                 ul_Command1 =
452                         inl(devpriv->iobase + APCI3501_WATCHDOG +
453                         APCI3501_TCW_PROG);
454                 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
455                 outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     /* Stop The Timer */
456                 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
457                 if (data[1] == 1) {
458                         /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
459                         outl(0x02,
460                                 devpriv->iobase + APCI3501_WATCHDOG +
461                                 APCI3501_TCW_PROG);
462                 } else {
463                         outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     /* disable Timer interrupt */
464                 }
465
466                 /*  Loading Timebase */
467                 outl(data[2],
468                         devpriv->iobase + APCI3501_WATCHDOG +
469                         APCI3501_TCW_TIMEBASE);
470
471                 /* Loading the Reload value */
472                 outl(data[3],
473                         devpriv->iobase + APCI3501_WATCHDOG +
474                         APCI3501_TCW_RELOAD_VALUE);
475
476                 /*  printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG)); */
477                 ul_Command1 =
478                         inl(devpriv->iobase + APCI3501_WATCHDOG +
479                         APCI3501_TCW_PROG);
480                 ul_Command1 =
481                         (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
482                 outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     /* mode 2 */
483
484         }                       /* end if(data[0]==ADDIDATA_TIMER) */
485
486         return insn->n;
487 }
488
489 /*
490 +----------------------------------------------------------------------------+
491 | Function   Name   : int i_APCI3501_StartStopWriteTimerCounterWatchdog      |
492 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
493 |                      struct comedi_insn *insn,unsigned int *data)                     |
494 +----------------------------------------------------------------------------+
495 | Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
496 +----------------------------------------------------------------------------+
497 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
498 |                     unsigned int *data         : Data Pointer contains             |
499 |                                          configuration parameters as below |
500 |                                                                            |
501 |                                         data[0]            : 0 Timer                   |
502 |                                                                                  1 Counter                 |
503 |                                                                                  2 Watchdog                    |                             |                                         data[1]            : 1 Start                   |
504 |                                                                                  0 Stop                                |                                                                                                                    2 Trigger                 |
505 +----------------------------------------------------------------------------+
506 | Output Parameters :   --                                                                                                       |
507 +----------------------------------------------------------------------------+
508 | Return Value      : TRUE  : No error occur                                 |
509 |                           : FALSE : Error occur. Return the error          |
510 |                                                                                |
511 +----------------------------------------------------------------------------+
512 */
513
514 int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
515         struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
516 {
517         unsigned int ul_Command1 = 0;
518         int i_Temp;
519         if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
520
521                 if (data[1] == 1) {
522                         ul_Command1 =
523                                 inl(devpriv->iobase + APCI3501_WATCHDOG +
524                                 APCI3501_TCW_PROG);
525                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
526                         /* Enable the Watchdog */
527                         outl(ul_Command1,
528                                 devpriv->iobase + APCI3501_WATCHDOG +
529                                 APCI3501_TCW_PROG);
530                 }
531
532                 else if (data[1] == 0)  /* Stop The Watchdog */
533                 {
534                         /* Stop The Watchdog */
535                         ul_Command1 =
536                                 inl(devpriv->iobase + APCI3501_WATCHDOG +
537                                 APCI3501_TCW_PROG);
538                         ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
539                         outl(0x0,
540                                 devpriv->iobase + APCI3501_WATCHDOG +
541                                 APCI3501_TCW_PROG);
542                 } else if (data[1] == 2) {
543                         ul_Command1 =
544                                 inl(devpriv->iobase + APCI3501_WATCHDOG +
545                                 APCI3501_TCW_PROG);
546                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
547                         outl(ul_Command1,
548                                 devpriv->iobase + APCI3501_WATCHDOG +
549                                 APCI3501_TCW_PROG);
550                 }               /* if(data[1]==2) */
551         }                       /*  end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
552
553         if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
554                 if (data[1] == 1) {
555
556                         ul_Command1 =
557                                 inl(devpriv->iobase + APCI3501_WATCHDOG +
558                                 APCI3501_TCW_PROG);
559                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
560                         /* Enable the Timer */
561                         outl(ul_Command1,
562                                 devpriv->iobase + APCI3501_WATCHDOG +
563                                 APCI3501_TCW_PROG);
564                 } else if (data[1] == 0) {
565                         /* Stop The Timer */
566                         ul_Command1 =
567                                 inl(devpriv->iobase + APCI3501_WATCHDOG +
568                                 APCI3501_TCW_PROG);
569                         ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
570                         outl(ul_Command1,
571                                 devpriv->iobase + APCI3501_WATCHDOG +
572                                 APCI3501_TCW_PROG);
573                 }
574
575                 else if (data[1] == 2) {
576                         /* Trigger the Timer */
577                         ul_Command1 =
578                                 inl(devpriv->iobase + APCI3501_WATCHDOG +
579                                 APCI3501_TCW_PROG);
580                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
581                         outl(ul_Command1,
582                                 devpriv->iobase + APCI3501_WATCHDOG +
583                                 APCI3501_TCW_PROG);
584                 }
585
586         }                       /*  end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
587         i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
588                 APCI3501_TCW_TRIG_STATUS) & 0x1;
589         return insn->n;
590 }
591
592 /*
593 +----------------------------------------------------------------------------+
594 | Function   Name   : int i_APCI3501_ReadTimerCounterWatchdog                |
595 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
596 |                      struct comedi_insn *insn,unsigned int *data)                     |
597 +----------------------------------------------------------------------------+
598 | Task              : Read The Selected Timer , Counter or Watchdog          |
599 +----------------------------------------------------------------------------+
600 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
601 |                     unsigned int *data         : Data Pointer contains             |
602 |                                          configuration parameters as below |
603 |                                                                            |
604 |                                         data[0]            : 0 Timer                   |
605 |                                                                                  1 Counter                 |
606 |                                                                                  2 Watchdog                |                             |                                      data[1]             : Timer Counter Watchdog Number   |
607 +----------------------------------------------------------------------------+
608 | Output Parameters :   --                                                                                                       |
609 +----------------------------------------------------------------------------+
610 | Return Value      : TRUE  : No error occur                                 |
611 |                           : FALSE : Error occur. Return the error          |
612 |                                                                                |
613 +----------------------------------------------------------------------------+
614 */
615
616 int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
617         struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
618 {
619
620         if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
621                 data[0] =
622                         inl(devpriv->iobase + APCI3501_WATCHDOG +
623                         APCI3501_TCW_TRIG_STATUS) & 0x1;
624                 data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
625         }                       /*  end if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
626
627         else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
628                 data[0] =
629                         inl(devpriv->iobase + APCI3501_WATCHDOG +
630                         APCI3501_TCW_TRIG_STATUS) & 0x1;
631                 data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
632         }                       /*  end if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
633
634         else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
635                 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
636                 printk("\nIn ReadTimerCounterWatchdog :: Invalid Subdevice \n");
637         }
638         return insn->n;
639 }
640
641 /*
642 +----------------------------------------------------------------------------+
643 | Function   Name   :  int i_APCI3501_Reset(struct comedi_device *dev)                       |
644 |                                                                                        |
645 +----------------------------------------------------------------------------+
646 | Task              :Resets the registers of the card                        |
647 +----------------------------------------------------------------------------+
648 | Input Parameters  :                                                        |
649 +----------------------------------------------------------------------------+
650 | Output Parameters :   --                                                                                                       |
651 +----------------------------------------------------------------------------+
652 | Return Value      :                                                        |
653 |                                                                                |
654 +----------------------------------------------------------------------------+
655 */
656
657 int i_APCI3501_Reset(struct comedi_device *dev)
658 {
659         int i_Count = 0, i_temp = 0;
660         unsigned int ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
661         outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
662         outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
663                 APCI3501_AO_VOLT_MODE);
664
665         ul_Polarity = 0x80000000;
666
667         for (i_Count = 0; i_Count <= 7; i_Count++) {
668                 ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
669
670                 while (ul_DAC_Ready == 0) {
671                         ul_DAC_Ready =
672                                 inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
673                         ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
674                 }
675
676                 if (ul_DAC_Ready) {
677                         /*  Output the Value on the output channels. */
678                         ul_Command1 =
679                                 (unsigned int) ((unsigned int) (i_Count & 0xFF) |
680                                 (unsigned int) ((i_temp << 0x8) & 0x7FFFFF00L) |
681                                 (unsigned int) (ul_Polarity));
682                         outl(ul_Command1,
683                                 devpriv->iobase + APCI3501_ANALOG_OUTPUT +
684                                 APCI3501_AO_PROG);
685                 }
686         }
687
688         return 0;
689 }
690
691 /*
692 +----------------------------------------------------------------------------+
693 | Function   Name   : static void v_APCI3501_Interrupt                                       |
694 |                                         (int irq , void *d)      |
695 +----------------------------------------------------------------------------+
696 | Task              : Interrupt processing Routine                           |
697 +----------------------------------------------------------------------------+
698 | Input Parameters  : int irq                 : irq number                   |
699 |                     void *d                 : void pointer                 |
700 +----------------------------------------------------------------------------+
701 | Output Parameters :   --                                                                                                       |
702 +----------------------------------------------------------------------------+
703 | Return Value      : TRUE  : No error occur                                 |
704 |                           : FALSE : Error occur. Return the error          |
705 |                                                                                |
706 +----------------------------------------------------------------------------+
707 */
708 void v_APCI3501_Interrupt(int irq, void *d)
709 {
710         int i_temp;
711         struct comedi_device *dev = d;
712         unsigned int ui_Timer_AOWatchdog;
713         unsigned long ul_Command1;
714         /*  Disable Interrupt */
715         ul_Command1 =
716                 inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
717
718         ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
719         outl(ul_Command1,
720                 devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
721
722         ui_Timer_AOWatchdog =
723                 inl(devpriv->iobase + APCI3501_WATCHDOG +
724                 APCI3501_TCW_IRQ) & 0x1;
725
726         if ((!ui_Timer_AOWatchdog)) {
727                 comedi_error(dev, "IRQ from unknow source");
728                 return;
729         }
730
731 /*
732 * Enable Interrupt Send a signal to from kernel to user space
733 */
734         send_sig(SIGIO, devpriv->tsk_Current, 0);
735         ul_Command1 =
736                 inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
737         ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1);
738         outl(ul_Command1,
739                 devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
740         i_temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
741                 APCI3501_TCW_TRIG_STATUS) & 0x1;
742         return;
743 }