4 Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
10 Fax: +49(0)7223/9493-92
11 http://www.addi-data-com
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.
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.
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
20 You shoud also find the complete GPL in the COPYING file accompanying this source code.
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 Acces For APCI-1564 |
38 +-----------------------------------------------------------------------+
40 +----------+-----------+------------------------------------------------+
41 | Date | Author | Description of updates |
42 +----------+-----------+------------------------------------------------+
46 +----------+-----------+------------------------------------------------+
50 +----------------------------------------------------------------------------+
52 +----------------------------------------------------------------------------+
55 #include <linux/delay.h>
56 #include "hwdrv_apci1564.h"
59 UINT ui_InterruptStatus_1564
= 0;
60 UINT ui_InterruptData
, ui_Type
;
63 +----------------------------------------------------------------------------+
64 | Function Name : int i_APCI1564_ConfigDigitalInput |
65 | (struct comedi_device *dev,struct comedi_subdevice *s, |
66 | comedi_insn *insn,unsigned int *data) |
67 +----------------------------------------------------------------------------+
68 | Task : Configures the digital input Subdevice |
69 +----------------------------------------------------------------------------+
70 | Input Parameters : struct comedi_device *dev : Driver handle |
71 | unsigned int *data : Data Pointer contains |
72 | configuration parameters as below |
74 | data[0] : 1 Enable Digital Input Interrupt |
75 | 0 Disable Digital Input Interrupt |
76 | data[1] : 0 ADDIDATA Interrupt OR LOGIC |
77 | : 1 ADDIDATA Interrupt AND LOGIC |
78 | data[2] : Interrupt mask for the mode 1 |
79 | data[3] : Interrupt mask for the mode 2 |
81 +----------------------------------------------------------------------------+
82 | Output Parameters : -- |
83 +----------------------------------------------------------------------------+
84 | Return Value : TRUE : No error occur |
85 | : FALSE : Error occur. Return the error |
87 +----------------------------------------------------------------------------+
89 INT
i_APCI1564_ConfigDigitalInput(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
90 comedi_insn
* insn
, unsigned int * data
)
92 devpriv
->tsk_Current
= current
;
93 /*******************************/
94 /* Set the digital input logic */
95 /*******************************/
96 if (data
[0] == ADDIDATA_ENABLE
) {
97 data
[2] = data
[2] << 4;
98 data
[3] = data
[3] << 4;
100 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
101 APCI1564_DIGITAL_IP_INTERRUPT_MODE1
);
103 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
104 APCI1564_DIGITAL_IP_INTERRUPT_MODE2
);
105 if (data
[1] == ADDIDATA_OR
) {
107 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
108 APCI1564_DIGITAL_IP_IRQ
);
109 } // if (data[1] == ADDIDATA_OR)
112 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
113 APCI1564_DIGITAL_IP_IRQ
);
114 } // else if (data[1] == ADDIDATA_OR)
115 } // if (data[0] == ADDIDATA_ENABLE)
118 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
119 APCI1564_DIGITAL_IP_INTERRUPT_MODE1
);
121 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
122 APCI1564_DIGITAL_IP_INTERRUPT_MODE2
);
124 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
125 APCI1564_DIGITAL_IP_IRQ
);
126 } // else if (data[0] == ADDIDATA_ENABLE)
132 +----------------------------------------------------------------------------+
133 | Function Name : int i_APCI1564_Read1DigitalInput |
134 | (struct comedi_device *dev,struct comedi_subdevice *s, |
135 | comedi_insn *insn,unsigned int *data) |
136 +----------------------------------------------------------------------------+
137 | Task : Return the status of the digital input |
138 +----------------------------------------------------------------------------+
139 | Input Parameters : struct comedi_device *dev : Driver handle |
140 | UINT ui_Channel : Channel number to read |
141 | unsigned int *data : Data Pointer to read status |
142 +----------------------------------------------------------------------------+
143 | Output Parameters : -- |
144 +----------------------------------------------------------------------------+
145 | Return Value : TRUE : No error occur |
146 | : FALSE : Error occur. Return the error |
148 +----------------------------------------------------------------------------+
150 INT
i_APCI1564_Read1DigitalInput(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
151 comedi_insn
* insn
, unsigned int * data
)
153 UINT ui_TmpValue
= 0;
156 ui_Channel
= CR_CHAN(insn
->chanspec
);
157 if (ui_Channel
>= 0 && ui_Channel
<= 31) {
159 (UINT
) inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
);
160 // since only 1 channel reqd to bring it to last bit it is rotated
161 // 8 +(chan - 1) times then ANDed with 1 for last bit.
162 *data
= (ui_TmpValue
>> ui_Channel
) & 0x1;
163 } // if (ui_Channel >= 0 && ui_Channel <=31)
165 comedi_error(dev
, "Not a valid channel number !!! \n");
166 return -EINVAL
; // "sorry channel spec wrong "
167 } //else if (ui_Channel >= 0 && ui_Channel <=31)
172 +----------------------------------------------------------------------------+
173 | Function Name : int i_APCI1564_ReadMoreDigitalInput |
174 | (struct comedi_device *dev,struct comedi_subdevice *s, |
175 | comedi_insn *insn,unsigned int *data) |
176 +----------------------------------------------------------------------------+
177 | Task : Return the status of the Requested digital inputs |
178 +----------------------------------------------------------------------------+
179 | Input Parameters : struct comedi_device *dev : Driver handle |
180 | UINT ui_NoOfChannels : No Of Channels To be Read |
181 | UINT *data : Data Pointer to read status |
182 +----------------------------------------------------------------------------+
183 | Output Parameters : -- |
184 +----------------------------------------------------------------------------+
185 | Return Value : TRUE : No error occur |
186 | : FALSE : Error occur. Return the error |
188 +----------------------------------------------------------------------------+
190 INT
i_APCI1564_ReadMoreDigitalInput(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
191 comedi_insn
* insn
, unsigned int * data
)
193 UINT ui_PortValue
= data
[0];
195 UINT ui_NoOfChannels
;
197 ui_NoOfChannels
= CR_CHAN(insn
->chanspec
);
199 *data
= (UINT
) inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
);
200 switch (ui_NoOfChannels
) {
203 *data
= (*data
>> (2 * ui_PortValue
)) & ui_Mask
;
207 *data
= (*data
>> (4 * ui_PortValue
)) & ui_Mask
;
211 *data
= (*data
>> (8 * ui_PortValue
)) & ui_Mask
;
215 *data
= (*data
>> (16 * ui_PortValue
)) & ui_Mask
;
220 comedi_error(dev
, "Not a valid Channel number !!!\n");
221 return -EINVAL
; // "sorry channel spec wrong "
223 } // switch (ui_NoOfChannels)
227 *data
= ui_InterruptStatus_1564
;
229 } // else if (data[1]==0)
234 +----------------------------------------------------------------------------+
235 | Function Name : int i_APCI1564_ConfigDigitalOutput |
236 | (struct comedi_device *dev,struct comedi_subdevice *s, |
237 | comedi_insn *insn,unsigned int *data) |
238 +----------------------------------------------------------------------------+
239 | Task : Configures The Digital Output Subdevice. |
240 +----------------------------------------------------------------------------+
241 | Input Parameters : struct comedi_device *dev : Driver handle |
242 | UINT *data : Data Pointer contains |
243 | configuration parameters as below |
245 | data[1] : 1 Enable VCC Interrupt |
246 | 0 Disable VCC Interrupt |
247 | data[2] : 1 Enable CC Interrupt |
248 | 0 Disable CC Interrupt |
250 +----------------------------------------------------------------------------+
251 | Output Parameters : -- |
252 +----------------------------------------------------------------------------+
253 | Return Value : TRUE : No error occur |
254 | : FALSE : Error occur. Return the error |
256 +----------------------------------------------------------------------------+
258 INT
i_APCI1564_ConfigDigitalOutput(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
259 comedi_insn
* insn
, unsigned int * data
)
261 ULONG ul_Command
= 0;
263 if ((data
[0] != 0) && (data
[0] != 1)) {
265 "Not a valid Data !!! ,Data should be 1 or 0\n");
267 } // if ((data[0]!=0) && (data[0]!=1))
269 devpriv
->b_OutputMemoryStatus
= ADDIDATA_ENABLE
;
272 devpriv
->b_OutputMemoryStatus
= ADDIDATA_DISABLE
;
273 } // else if (data[0])
274 if (data
[1] == ADDIDATA_ENABLE
) {
275 ul_Command
= ul_Command
| 0x1;
276 } // if (data[1] == ADDIDATA_ENABLE)
278 ul_Command
= ul_Command
& 0xFFFFFFFE;
279 } // else if (data[1] == ADDIDATA_ENABLE)
280 if (data
[2] == ADDIDATA_ENABLE
) {
281 ul_Command
= ul_Command
| 0x2;
282 } // if (data[2] == ADDIDATA_ENABLE)
284 ul_Command
= ul_Command
& 0xFFFFFFFD;
285 } // else if (data[2] == ADDIDATA_ENABLE)
287 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
288 APCI1564_DIGITAL_OP_INTERRUPT
);
290 inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
291 APCI1564_DIGITAL_OP_INTERRUPT
);
292 devpriv
->tsk_Current
= current
;
297 +----------------------------------------------------------------------------+
298 | Function Name : int i_APCI1564_WriteDigitalOutput |
299 | (struct comedi_device *dev,struct comedi_subdevice *s, |
300 | comedi_insn *insn,unsigned int *data) |
301 +----------------------------------------------------------------------------+
302 | Task : Writes port value To the selected port |
303 +----------------------------------------------------------------------------+
304 | Input Parameters : struct comedi_device *dev : Driver handle |
305 | UINT ui_NoOfChannels : No Of Channels To Write |
306 | UINT *data : Data Pointer to read status |
307 +----------------------------------------------------------------------------+
308 | Output Parameters : -- |
309 +----------------------------------------------------------------------------+
310 | Return Value : TRUE : No error occur |
311 | : FALSE : Error occur. Return the error |
313 +----------------------------------------------------------------------------+
315 INT
i_APCI1564_WriteDigitalOutput(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
316 comedi_insn
* insn
, unsigned int * data
)
318 UINT ui_Temp
, ui_Temp1
;
321 ui_NoOfChannel
= CR_CHAN(insn
->chanspec
);
322 if (devpriv
->b_OutputMemoryStatus
) {
324 inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
325 APCI1564_DIGITAL_OP_RW
);
326 } // if (devpriv->b_OutputMemoryStatus )
329 } // else if (devpriv->b_OutputMemoryStatus )
332 data
[0] = (data
[0] << ui_NoOfChannel
) | ui_Temp
;
334 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
335 APCI1564_DIGITAL_OP_RW
);
339 switch (ui_NoOfChannel
) {
361 data
[0] = data
[0] | ui_Temp
;
364 comedi_error(dev
, " chan spec wrong");
365 return -EINVAL
; // "sorry channel spec wrong "
366 } // switch (ui_NoOfChannels)
368 devpriv
->i_IobaseAmcc
+
369 APCI1564_DIGITAL_OP
+
370 APCI1564_DIGITAL_OP_RW
);
373 printk("\nSpecified channel not supported\n");
374 } // else if (data[1]==1)
375 } // else if (data[1]==0)
380 data
[0] = ~data
[0] & 0x1;
382 ui_Temp1
= ui_Temp1
<< ui_NoOfChannel
;
383 ui_Temp
= ui_Temp
| ui_Temp1
;
385 (data
[0] << ui_NoOfChannel
) ^
387 data
[0] = data
[0] & ui_Temp
;
389 devpriv
->i_IobaseAmcc
+
390 APCI1564_DIGITAL_OP
+
391 APCI1564_DIGITAL_OP_RW
);
395 switch (ui_NoOfChannel
) {
397 data
[0] = ~data
[0] & 0x3;
400 ui_Temp1
<< 2 * data
[2];
401 ui_Temp
= ui_Temp
| ui_Temp1
;
406 0xffffffff) & ui_Temp
;
409 data
[0] = ~data
[0] & 0xf;
412 ui_Temp1
<< 4 * data
[2];
413 ui_Temp
= ui_Temp
| ui_Temp1
;
418 0xffffffff) & ui_Temp
;
421 data
[0] = ~data
[0] & 0xff;
424 ui_Temp1
<< 8 * data
[2];
425 ui_Temp
= ui_Temp
| ui_Temp1
;
430 0xffffffff) & ui_Temp
;
433 data
[0] = ~data
[0] & 0xffff;
438 ui_Temp
= ui_Temp
| ui_Temp1
;
443 0xffffffff) & ui_Temp
;
450 return -EINVAL
; // "sorry channel spec wrong "
451 } //switch(ui_NoOfChannels)
453 devpriv
->i_IobaseAmcc
+
454 APCI1564_DIGITAL_OP
+
455 APCI1564_DIGITAL_OP_RW
);
458 printk("\nSpecified channel not supported\n");
459 } // else if (data[1]==1)
460 } // else if (data[1]==0)
461 } // if (data[3]==1);
463 printk("\nSpecified functionality does not exist\n");
465 } // else if (data[3]==1)
466 } // else if (data[3]==0)
471 +----------------------------------------------------------------------------+
472 | Function Name : int i_APCI1564_ReadDigitalOutput |
473 | (struct comedi_device *dev,struct comedi_subdevice *s, |
474 | comedi_insn *insn,unsigned int *data) |
475 +----------------------------------------------------------------------------+
476 | Task : Read value of the selected channel or port |
477 +----------------------------------------------------------------------------+
478 | Input Parameters : struct comedi_device *dev : Driver handle |
479 | UINT ui_NoOfChannels : No Of Channels To read |
480 | UINT *data : Data Pointer to read status |
481 +----------------------------------------------------------------------------+
482 | Output Parameters : -- |
483 +----------------------------------------------------------------------------+
484 | Return Value : TRUE : No error occur |
485 | : FALSE : Error occur. Return the error |
487 +----------------------------------------------------------------------------+
489 INT
i_APCI1564_ReadDigitalOutput(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
490 comedi_insn
* insn
, unsigned int * data
)
495 ui_NoOfChannel
= CR_CHAN(insn
->chanspec
);
497 *data
= inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
498 APCI1564_DIGITAL_OP_RW
);
500 *data
= (*data
>> ui_NoOfChannel
) & 0x1;
504 switch (ui_NoOfChannel
) {
506 *data
= (*data
>> (2 * data
[1])) & 3;
510 *data
= (*data
>> (4 * data
[1])) & 15;
514 *data
= (*data
>> (8 * data
[1])) & 255;
518 *data
= (*data
>> (16 * data
[1])) & 65535;
525 comedi_error(dev
, " chan spec wrong");
526 return -EINVAL
; // "sorry channel spec wrong "
528 } // switch(ui_NoOfChannels)
531 printk("\nSpecified channel not supported \n");
532 } // else if (ui_Temp==1)
533 } // else if (ui_Temp==0)
538 +----------------------------------------------------------------------------+
539 | Function Name : int i_APCI1564_ConfigTimerCounterWatchdog |
540 | (struct comedi_device *dev,struct comedi_subdevice *s, |
541 | comedi_insn *insn,unsigned int *data) |
542 +----------------------------------------------------------------------------+
543 | Task : Configures The Timer , Counter or Watchdog |
544 +----------------------------------------------------------------------------+
545 | Input Parameters : struct comedi_device *dev : Driver handle |
546 | UINT *data : Data Pointer contains |
547 | configuration parameters as below |
549 | data[0] : 0 Configure As Timer |
550 | 1 Configure As Counter |
551 | 2 Configure As Watchdog |
552 | data[1] : 1 Enable Interrupt |
553 | 0 Disable Interrupt |
554 | data[2] : Time Unit |
555 | data[3] : Reload Value |
556 | data[4] : Timer Mode |
557 | data[5] : Timer Counter Watchdog Number|
558 data[6] : Counter Direction
559 +----------------------------------------------------------------------------+
560 | Output Parameters : -- |
561 +----------------------------------------------------------------------------+
562 | Return Value : TRUE : No error occur |
563 | : FALSE : Error occur. Return the error |
565 +----------------------------------------------------------------------------+
567 INT
i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device
* dev
,
568 struct comedi_subdevice
* s
, comedi_insn
* insn
, unsigned int * data
)
570 ULONG ul_Command1
= 0;
571 devpriv
->tsk_Current
= current
;
572 if (data
[0] == ADDIDATA_WATCHDOG
) {
573 devpriv
->b_TimerSelectMode
= ADDIDATA_WATCHDOG
;
575 //Disable the watchdog
577 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP_WATCHDOG
+
579 //Loading the Reload value
581 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP_WATCHDOG
+
582 APCI1564_TCW_RELOAD_VALUE
);
583 } // if (data[0]==ADDIDATA_WATCHDOG)
584 else if (data
[0] == ADDIDATA_TIMER
) {
585 //First Stop The Timer
587 inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
589 ul_Command1
= ul_Command1
& 0xFFFFF9FEUL
;
590 outl(ul_Command1
, devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+ APCI1564_TCW_PROG
); //Stop The Timer
592 devpriv
->b_TimerSelectMode
= ADDIDATA_TIMER
;
594 outl(0x02, devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+ APCI1564_TCW_PROG
); //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
596 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
597 APCI1564_DIGITAL_IP_IRQ
);
599 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
600 APCI1564_DIGITAL_OP_IRQ
);
602 devpriv
->i_IobaseAmcc
+
603 APCI1564_DIGITAL_OP_WATCHDOG
+
606 devpriv
->iobase
+ APCI1564_COUNTER1
+
609 devpriv
->iobase
+ APCI1564_COUNTER2
+
612 devpriv
->iobase
+ APCI1564_COUNTER3
+
615 devpriv
->iobase
+ APCI1564_COUNTER4
+
619 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+ APCI1564_TCW_PROG
); //disable Timer interrupt
620 } // else if (data[1]==1)
625 devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
626 APCI1564_TCW_TIMEBASE
);
628 //Loading the Reload value
630 devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
631 APCI1564_TCW_RELOAD_VALUE
);
634 inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
637 (ul_Command1
& 0xFFF719E2UL
) | 2UL << 13UL | 0x10UL
;
638 outl(ul_Command1
, devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+ APCI1564_TCW_PROG
); //mode 2
639 } // else if (data[0]==ADDIDATA_TIMER)
640 else if (data
[0] == ADDIDATA_COUNTER
) {
641 devpriv
->b_TimerSelectMode
= ADDIDATA_COUNTER
;
642 devpriv
->b_ModeSelectRegister
= data
[5];
644 //First Stop The Counter
646 inl(devpriv
->iobase
+ ((data
[5] - 1) * 0x20) +
648 ul_Command1
= ul_Command1
& 0xFFFFF9FEUL
;
649 outl(ul_Command1
, devpriv
->iobase
+ ((data
[5] - 1) * 0x20) + APCI1564_TCW_PROG
); //Stop The Timer
651 /************************/
652 /* Set the reload value */
653 /************************/
655 devpriv
->iobase
+ ((data
[5] - 1) * 0x20) +
656 APCI1564_TCW_RELOAD_VALUE
);
658 /******************************/
660 /* - Disable the hardware */
661 /* - Disable the counter mode */
662 /* - Disable the warning */
663 /* - Disable the reset */
664 /* - Disable the timer mode */
665 /* - Enable the counter mode */
666 /******************************/
668 (ul_Command1
& 0xFFFC19E2UL
) | 0x80000UL
|
669 (ULONG
) ((ULONG
) data
[4] << 16UL);
671 devpriv
->iobase
+ ((data
[5] - 1) * 0x20) +
674 // Enable or Disable Interrupt
675 ul_Command1
= (ul_Command1
& 0xFFFFF9FD) | (data
[1] << 1);
677 devpriv
->iobase
+ ((data
[5] - 1) * 0x20) +
680 /*****************************/
681 /* Set the Up/Down selection */
682 /*****************************/
683 ul_Command1
= (ul_Command1
& 0xFFFBF9FFUL
) | (data
[6] << 18);
685 devpriv
->iobase
+ ((data
[5] - 1) * 0x20) +
687 } // else if (data[0]==ADDIDATA_COUNTER)
689 printk(" Invalid subdevice.");
690 } // else if (data[0]==ADDIDATA_WATCHDOG)
696 +----------------------------------------------------------------------------+
697 | Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog |
698 | (struct comedi_device *dev,struct comedi_subdevice *s, |
699 | comedi_insn *insn,unsigned int *data) |
700 +----------------------------------------------------------------------------+
701 | Task : Start / Stop The Selected Timer , Counter or Watchdog |
702 +----------------------------------------------------------------------------+
703 | Input Parameters : struct comedi_device *dev : Driver handle |
704 | UINT *data : Data Pointer contains |
705 | configuration parameters as below |
707 | data[0] : 0 Timer |
709 | 2 Watchdog | | data[1] : 1 Start |
712 | Clear (Only Counter) |
713 +----------------------------------------------------------------------------+
714 | Output Parameters : -- |
715 +----------------------------------------------------------------------------+
716 | Return Value : TRUE : No error occur |
717 | : FALSE : Error occur. Return the error |
719 +----------------------------------------------------------------------------+
721 INT
i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device
* dev
,
722 struct comedi_subdevice
* s
, comedi_insn
* insn
, unsigned int * data
)
724 ULONG ul_Command1
= 0;
725 if (devpriv
->b_TimerSelectMode
== ADDIDATA_WATCHDOG
) {
727 case 0: //stop the watchdog
728 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP_WATCHDOG
+ APCI1564_TCW_PROG
); //disable the watchdog
730 case 1: //start the watchdog
732 devpriv
->i_IobaseAmcc
+
733 APCI1564_DIGITAL_OP_WATCHDOG
+
736 case 2: //Software trigger
738 devpriv
->i_IobaseAmcc
+
739 APCI1564_DIGITAL_OP_WATCHDOG
+
743 printk("\nSpecified functionality does not exist\n");
745 } // switch (data[1])
746 } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
747 if (devpriv
->b_TimerSelectMode
== ADDIDATA_TIMER
) {
750 inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
752 ul_Command1
= (ul_Command1
& 0xFFFFF9FFUL
) | 0x1UL
;
756 devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
759 else if (data
[1] == 0) {
763 inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
765 ul_Command1
= ul_Command1
& 0xFFFFF9FEUL
;
767 devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
769 } // else if(data[1]==0)
770 } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
771 if (devpriv
->b_TimerSelectMode
== ADDIDATA_COUNTER
) {
773 inl(devpriv
->iobase
+ ((devpriv
->b_ModeSelectRegister
-
774 1) * 0x20) + APCI1564_TCW_PROG
);
776 //Start the Counter subdevice
777 ul_Command1
= (ul_Command1
& 0xFFFFF9FFUL
) | 0x1UL
;
778 } // if (data[1] == 1)
779 else if (data
[1] == 0) {
780 // Stops the Counter subdevice
783 } // else if (data[1] == 0)
784 else if (data
[1] == 2) {
785 // Clears the Counter subdevice
786 ul_Command1
= (ul_Command1
& 0xFFFFF9FFUL
) | 0x400;
787 } // else if (data[1] == 3)
789 devpriv
->iobase
+ ((devpriv
->b_ModeSelectRegister
-
790 1) * 0x20) + APCI1564_TCW_PROG
);
791 } // if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
796 +----------------------------------------------------------------------------+
797 | Function Name : int i_APCI1564_ReadTimerCounterWatchdog |
798 | (struct comedi_device *dev,struct comedi_subdevice *s, |
799 | comedi_insn *insn,unsigned int *data) |
800 +----------------------------------------------------------------------------+
801 | Task : Read The Selected Timer , Counter or Watchdog |
802 +----------------------------------------------------------------------------+
803 | Input Parameters : struct comedi_device *dev : Driver handle |
804 | UINT *data : Data Pointer contains |
805 | configuration parameters as below |
808 +----------------------------------------------------------------------------+
809 | Output Parameters : -- |
810 +----------------------------------------------------------------------------+
811 | Return Value : TRUE : No error occur |
812 | : FALSE : Error occur. Return the error |
814 +----------------------------------------------------------------------------+
816 INT
i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device
* dev
,
817 struct comedi_subdevice
* s
, comedi_insn
* insn
, unsigned int * data
)
819 ULONG ul_Command1
= 0;
821 if (devpriv
->b_TimerSelectMode
== ADDIDATA_WATCHDOG
) {
822 // Stores the status of the Watchdog
824 inl(devpriv
->i_IobaseAmcc
+
825 APCI1564_DIGITAL_OP_WATCHDOG
+
826 APCI1564_TCW_TRIG_STATUS
) & 0x1;
828 inl(devpriv
->i_IobaseAmcc
+
829 APCI1564_DIGITAL_OP_WATCHDOG
);
830 } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
831 else if (devpriv
->b_TimerSelectMode
== ADDIDATA_TIMER
) {
832 // Stores the status of the Timer
834 inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
835 APCI1564_TCW_TRIG_STATUS
) & 0x1;
837 // Stores the Actual value of the Timer
838 data
[1] = inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
);
839 } // else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
840 else if (devpriv
->b_TimerSelectMode
== ADDIDATA_COUNTER
) {
841 // Read the Counter Actual Value.
843 inl(devpriv
->iobase
+ ((devpriv
->b_ModeSelectRegister
-
845 APCI1564_TCW_SYNC_ENABLEDISABLE
);
847 inl(devpriv
->iobase
+ ((devpriv
->b_ModeSelectRegister
-
848 1) * 0x20) + APCI1564_TCW_TRIG_STATUS
);
850 /***********************************/
851 /* Get the software trigger status */
852 /***********************************/
853 data
[1] = (BYTE
) ((ul_Command1
>> 1) & 1);
855 /***********************************/
856 /* Get the hardware trigger status */
857 /***********************************/
858 data
[2] = (BYTE
) ((ul_Command1
>> 2) & 1);
860 /*********************************/
861 /* Get the software clear status */
862 /*********************************/
863 data
[3] = (BYTE
) ((ul_Command1
>> 3) & 1);
865 /***************************/
866 /* Get the overflow status */
867 /***************************/
868 data
[4] = (BYTE
) ((ul_Command1
>> 0) & 1);
869 } // else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
870 else if ((devpriv
->b_TimerSelectMode
!= ADDIDATA_TIMER
)
871 && (devpriv
->b_TimerSelectMode
!= ADDIDATA_WATCHDOG
)
872 && (devpriv
->b_TimerSelectMode
!= ADDIDATA_COUNTER
)) {
873 printk("\n Invalid Subdevice !!!\n");
874 } // else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER))
879 +----------------------------------------------------------------------------+
880 | Function Name : int i_APCI1564_ReadInterruptStatus |
881 | (struct comedi_device *dev,struct comedi_subdevice *s, |
882 | comedi_insn *insn,unsigned int *data) |
883 +----------------------------------------------------------------------------+
884 | Task :Reads the interrupt status register |
885 +----------------------------------------------------------------------------+
886 | Input Parameters : |
887 +----------------------------------------------------------------------------+
888 | Output Parameters : -- |
889 +----------------------------------------------------------------------------+
892 +----------------------------------------------------------------------------+
895 int i_APCI1564_ReadInterruptStatus(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
896 comedi_insn
* insn
, unsigned int * data
)
903 +----------------------------------------------------------------------------+
904 | Function Name : static void v_APCI1564_Interrupt |
905 | (int irq , void *d) |
906 +----------------------------------------------------------------------------+
907 | Task : Interrupt handler for the interruptible digital inputs |
908 +----------------------------------------------------------------------------+
909 | Input Parameters : int irq : irq number |
910 | void *d : void pointer |
911 +----------------------------------------------------------------------------+
912 | Output Parameters : -- |
913 +----------------------------------------------------------------------------+
914 | Return Value : TRUE : No error occur |
915 | : FALSE : Error occur. Return the error |
917 +----------------------------------------------------------------------------+
919 static VOID
v_APCI1564_Interrupt(int irq
, void *d
)
921 struct comedi_device
*dev
= d
;
924 UINT ui_C1
, ui_C2
, ui_C3
, ui_C4
;
925 ULONG ul_Command2
= 0;
926 ui_DI
= inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
927 APCI1564_DIGITAL_IP_IRQ
) & 0x01;
928 ui_DO
= inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
929 APCI1564_DIGITAL_OP_IRQ
) & 0x01;
931 inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
932 APCI1564_TCW_IRQ
) & 0x01;
933 ui_C1
= inl(devpriv
->iobase
+ APCI1564_COUNTER1
+
934 APCI1564_TCW_IRQ
) & 0x1;
935 ui_C2
= inl(devpriv
->iobase
+ APCI1564_COUNTER2
+
936 APCI1564_TCW_IRQ
) & 0x1;
937 ui_C3
= inl(devpriv
->iobase
+ APCI1564_COUNTER3
+
938 APCI1564_TCW_IRQ
) & 0x1;
939 ui_C4
= inl(devpriv
->iobase
+ APCI1564_COUNTER4
+
940 APCI1564_TCW_IRQ
) & 0x1;
941 if (ui_DI
== 0 && ui_DO
== 0 && ui_Timer
== 0 && ui_C1
== 0
942 && ui_C2
== 0 && ui_C3
== 0 && ui_C4
== 0) {
943 printk("\nInterrupt from unknown source\n");
944 } // if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0)
947 ui_DI
= inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
948 APCI1564_DIGITAL_IP_IRQ
);
950 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
951 APCI1564_DIGITAL_IP_IRQ
);
952 ui_InterruptStatus_1564
=
953 inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+
954 APCI1564_DIGITAL_IP_INTERRUPT_STATUS
);
955 ui_InterruptStatus_1564
= ui_InterruptStatus_1564
& 0X000FFFF0;
956 send_sig(SIGIO
, devpriv
->tsk_Current
, 0); // send signal to the sample
957 outl(ui_DI
, devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP
+ APCI1564_DIGITAL_IP_IRQ
); //enable the interrupt
962 // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
964 inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
965 APCI1564_DIGITAL_OP_INTERRUPT_STATUS
) & 0x3;
966 //Disable the Interrupt
968 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
+
969 APCI1564_DIGITAL_OP_INTERRUPT
);
971 //Sends signal to user space
972 send_sig(SIGIO
, devpriv
->tsk_Current
, 0);
976 if ((ui_Timer
== 1) && (devpriv
->b_TimerSelectMode
= ADDIDATA_TIMER
)) {
977 // Disable Timer Interrupt
979 inl(devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
982 devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
985 //Send a signal to from kernel to user space
986 send_sig(SIGIO
, devpriv
->tsk_Current
, 0);
988 // Enable Timer Interrupt
991 devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+
993 } // if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER))
995 if ((ui_C1
== 1) && (devpriv
->b_TimerSelectMode
= ADDIDATA_COUNTER
)) {
996 // Disable Counter Interrupt
998 inl(devpriv
->iobase
+ APCI1564_COUNTER1
+
1001 devpriv
->iobase
+ APCI1564_COUNTER1
+
1004 //Send a signal to from kernel to user space
1005 send_sig(SIGIO
, devpriv
->tsk_Current
, 0);
1007 // Enable Counter Interrupt
1009 devpriv
->iobase
+ APCI1564_COUNTER1
+
1011 } // if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER))
1013 if ((ui_C2
== 1) && (devpriv
->b_TimerSelectMode
= ADDIDATA_COUNTER
)) {
1014 // Disable Counter Interrupt
1016 inl(devpriv
->iobase
+ APCI1564_COUNTER2
+
1019 devpriv
->iobase
+ APCI1564_COUNTER2
+
1022 //Send a signal to from kernel to user space
1023 send_sig(SIGIO
, devpriv
->tsk_Current
, 0);
1025 // Enable Counter Interrupt
1027 devpriv
->iobase
+ APCI1564_COUNTER2
+
1029 } // if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
1031 if ((ui_C3
== 1) && (devpriv
->b_TimerSelectMode
= ADDIDATA_COUNTER
)) {
1032 // Disable Counter Interrupt
1034 inl(devpriv
->iobase
+ APCI1564_COUNTER3
+
1037 devpriv
->iobase
+ APCI1564_COUNTER3
+
1040 //Send a signal to from kernel to user space
1041 send_sig(SIGIO
, devpriv
->tsk_Current
, 0);
1043 // Enable Counter Interrupt
1045 devpriv
->iobase
+ APCI1564_COUNTER3
+
1047 } // if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
1049 if ((ui_C4
== 1) && (devpriv
->b_TimerSelectMode
= ADDIDATA_COUNTER
)) {
1050 // Disable Counter Interrupt
1052 inl(devpriv
->iobase
+ APCI1564_COUNTER4
+
1055 devpriv
->iobase
+ APCI1564_COUNTER4
+
1058 //Send a signal to from kernel to user space
1059 send_sig(SIGIO
, devpriv
->tsk_Current
, 0);
1061 // Enable Counter Interrupt
1063 devpriv
->iobase
+ APCI1564_COUNTER4
+
1065 } // if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
1070 +----------------------------------------------------------------------------+
1071 | Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | |
1072 +----------------------------------------------------------------------------+
1073 | Task :resets all the registers |
1074 +----------------------------------------------------------------------------+
1075 | Input Parameters : struct comedi_device *dev
1076 +----------------------------------------------------------------------------+
1077 | Output Parameters : -- |
1078 +----------------------------------------------------------------------------+
1081 +----------------------------------------------------------------------------+
1084 INT
i_APCI1564_Reset(struct comedi_device
* dev
)
1086 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP_IRQ
); //disable the interrupts
1087 inl(devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP_INTERRUPT_STATUS
); //Reset the interrupt status register
1088 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP_INTERRUPT_MODE1
); //Disable the and/or interrupt
1089 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_IP_INTERRUPT_MODE2
);
1090 devpriv
->b_DigitalOutputRegister
= 0;
1092 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP
); //Resets the output channels
1093 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP_INTERRUPT
); //Disables the interrupt.
1095 devpriv
->i_IobaseAmcc
+ APCI1564_DIGITAL_OP_WATCHDOG
+
1096 APCI1564_TCW_RELOAD_VALUE
);
1097 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
);
1098 outl(0x0, devpriv
->i_IobaseAmcc
+ APCI1564_TIMER
+ APCI1564_TCW_PROG
);
1100 outl(0x0, devpriv
->iobase
+ APCI1564_COUNTER1
+ APCI1564_TCW_PROG
);
1101 outl(0x0, devpriv
->iobase
+ APCI1564_COUNTER2
+ APCI1564_TCW_PROG
);
1102 outl(0x0, devpriv
->iobase
+ APCI1564_COUNTER3
+ APCI1564_TCW_PROG
);
1103 outl(0x0, devpriv
->iobase
+ APCI1564_COUNTER4
+ APCI1564_TCW_PROG
);