hwdrv_apci3501.c revision da91b2692e0939b307f9047192d2b9fe07793e7a
1/**
2@verbatim
3
4Copyright (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
14This 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
16This 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
18You 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
20You 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
76int 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*/
124int 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*/
164int 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*/
251int 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*/
301int 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*/
339int 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*/
413int 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
514int 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
616int 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
657int 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*/
708void 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}
744