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 should 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 Access 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"
58 /* Global variables */
59 static unsigned int ui_InterruptStatus_1564 = 0;
60 static unsigned int ui_InterruptData, ui_Type;
63 +----------------------------------------------------------------------------+
64 | Function Name : int i_APCI1564_ConfigDigitalInput |
65 | (struct comedi_device *dev,struct comedi_subdevice *s, |
66 | struct 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 static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev,
90 struct comedi_subdevice *s,
91 struct comedi_insn *insn,
94 struct addi_private *devpriv = dev->private;
96 devpriv->tsk_Current = current;
97 /*******************************/
98 /* Set the digital input logic */
99 /*******************************/
100 if (data[0] == ADDIDATA_ENABLE) {
101 data[2] = data[2] << 4;
102 data[3] = data[3] << 4;
104 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
105 APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
107 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
108 APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
109 if (data[1] == ADDIDATA_OR) {
111 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
112 APCI1564_DIGITAL_IP_IRQ);
113 } /* if (data[1] == ADDIDATA_OR) */
116 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
117 APCI1564_DIGITAL_IP_IRQ);
118 } /* else if (data[1] == ADDIDATA_OR) */
119 } /* if (data[0] == ADDIDATA_ENABLE) */
122 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
123 APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
125 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
126 APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
128 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
129 APCI1564_DIGITAL_IP_IRQ);
130 } /* else if (data[0] == ADDIDATA_ENABLE) */
136 +----------------------------------------------------------------------------+
137 | Function Name : int i_APCI1564_Read1DigitalInput |
138 | (struct comedi_device *dev,struct comedi_subdevice *s, |
139 | struct comedi_insn *insn,unsigned int *data) |
140 +----------------------------------------------------------------------------+
141 | Task : Return the status of the digital input |
142 +----------------------------------------------------------------------------+
143 | Input Parameters : struct comedi_device *dev : Driver handle |
144 | unsigned int ui_Channel : Channel number to read |
145 | unsigned int *data : Data Pointer to read status |
146 +----------------------------------------------------------------------------+
147 | Output Parameters : -- |
148 +----------------------------------------------------------------------------+
149 | Return Value : TRUE : No error occur |
150 | : FALSE : Error occur. Return the error |
152 +----------------------------------------------------------------------------+
154 static int i_APCI1564_Read1DigitalInput(struct comedi_device *dev,
155 struct comedi_subdevice *s,
156 struct comedi_insn *insn,
159 struct addi_private *devpriv = dev->private;
160 unsigned int ui_TmpValue = 0;
161 unsigned int ui_Channel;
163 ui_Channel = CR_CHAN(insn->chanspec);
164 if (ui_Channel <= 31) {
166 (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
168 * since only 1 channel reqd to bring it to last bit it is rotated 8
169 * +(chan - 1) times then ANDed with 1 for last bit.
171 *data = (ui_TmpValue >> ui_Channel) & 0x1;
172 } /* if (ui_Channel >= 0 && ui_Channel <=31) */
174 comedi_error(dev, "Not a valid channel number !!! \n");
175 return -EINVAL; /* "sorry channel spec wrong " */
176 } /* else if (ui_Channel >= 0 && ui_Channel <=31) */
181 +----------------------------------------------------------------------------+
182 | Function Name : int i_APCI1564_ReadMoreDigitalInput |
183 | (struct comedi_device *dev,struct comedi_subdevice *s, |
184 | struct comedi_insn *insn,unsigned int *data) |
185 +----------------------------------------------------------------------------+
186 | Task : Return the status of the Requested digital inputs |
187 +----------------------------------------------------------------------------+
188 | Input Parameters : struct comedi_device *dev : Driver handle |
189 | unsigned int ui_NoOfChannels : No Of Channels To be Read |
190 | unsigned int *data : Data Pointer to read status |
191 +----------------------------------------------------------------------------+
192 | Output Parameters : -- |
193 +----------------------------------------------------------------------------+
194 | Return Value : TRUE : No error occur |
195 | : FALSE : Error occur. Return the error |
197 +----------------------------------------------------------------------------+
199 static int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev,
200 struct comedi_subdevice *s,
201 struct comedi_insn *insn,
204 struct addi_private *devpriv = dev->private;
205 unsigned int ui_PortValue = data[0];
206 unsigned int ui_Mask = 0;
207 unsigned int ui_NoOfChannels;
209 ui_NoOfChannels = CR_CHAN(insn->chanspec);
211 *data = (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
212 switch (ui_NoOfChannels) {
215 *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
219 *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
223 *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
227 *data = (*data >> (16 * ui_PortValue)) & ui_Mask;
232 comedi_error(dev, "Not a valid Channel number !!!\n");
233 return -EINVAL; /* "sorry channel spec wrong " */
235 } /* switch (ui_NoOfChannels) */
236 } /* if (data[1]==0) */
239 *data = ui_InterruptStatus_1564;
240 } /* if (data[1]==1) */
241 } /* else if (data[1]==0) */
246 +----------------------------------------------------------------------------+
247 | Function Name : int i_APCI1564_ConfigDigitalOutput |
248 | (struct comedi_device *dev,struct comedi_subdevice *s, |
249 | struct comedi_insn *insn,unsigned int *data) |
250 +----------------------------------------------------------------------------+
251 | Task : Configures The Digital Output Subdevice. |
252 +----------------------------------------------------------------------------+
253 | Input Parameters : struct comedi_device *dev : Driver handle |
254 | unsigned int *data : Data Pointer contains |
255 | configuration parameters as below |
257 | data[1] : 1 Enable VCC Interrupt |
258 | 0 Disable VCC Interrupt |
259 | data[2] : 1 Enable CC Interrupt |
260 | 0 Disable CC Interrupt |
262 +----------------------------------------------------------------------------+
263 | Output Parameters : -- |
264 +----------------------------------------------------------------------------+
265 | Return Value : TRUE : No error occur |
266 | : FALSE : Error occur. Return the error |
268 +----------------------------------------------------------------------------+
270 static int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev,
271 struct comedi_subdevice *s,
272 struct comedi_insn *insn,
275 struct addi_private *devpriv = dev->private;
276 unsigned int ul_Command = 0;
278 if ((data[0] != 0) && (data[0] != 1)) {
280 "Not a valid Data !!! ,Data should be 1 or 0\n");
282 } /* if ((data[0]!=0) && (data[0]!=1)) */
284 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
287 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
288 } /* else if (data[0]) */
289 if (data[1] == ADDIDATA_ENABLE) {
290 ul_Command = ul_Command | 0x1;
291 } /* if (data[1] == ADDIDATA_ENABLE) */
293 ul_Command = ul_Command & 0xFFFFFFFE;
294 } /* else if (data[1] == ADDIDATA_ENABLE) */
295 if (data[2] == ADDIDATA_ENABLE) {
296 ul_Command = ul_Command | 0x2;
297 } /* if (data[2] == ADDIDATA_ENABLE) */
299 ul_Command = ul_Command & 0xFFFFFFFD;
300 } /* else if (data[2] == ADDIDATA_ENABLE) */
302 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
303 APCI1564_DIGITAL_OP_INTERRUPT);
305 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
306 APCI1564_DIGITAL_OP_INTERRUPT);
307 devpriv->tsk_Current = current;
312 +----------------------------------------------------------------------------+
313 | Function Name : int i_APCI1564_WriteDigitalOutput |
314 | (struct comedi_device *dev,struct comedi_subdevice *s, |
315 | struct comedi_insn *insn,unsigned int *data) |
316 +----------------------------------------------------------------------------+
317 | Task : Writes port value To the selected port |
318 +----------------------------------------------------------------------------+
319 | Input Parameters : struct comedi_device *dev : Driver handle |
320 | unsigned int ui_NoOfChannels : No Of Channels To Write |
321 | unsigned int *data : Data Pointer to read status |
322 +----------------------------------------------------------------------------+
323 | Output Parameters : -- |
324 +----------------------------------------------------------------------------+
325 | Return Value : TRUE : No error occur |
326 | : FALSE : Error occur. Return the error |
328 +----------------------------------------------------------------------------+
330 static int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev,
331 struct comedi_subdevice *s,
332 struct comedi_insn *insn,
335 struct addi_private *devpriv = dev->private;
336 unsigned int ui_Temp, ui_Temp1;
337 unsigned int ui_NoOfChannel;
339 ui_NoOfChannel = CR_CHAN(insn->chanspec);
340 if (devpriv->b_OutputMemoryStatus) {
342 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
343 APCI1564_DIGITAL_OP_RW);
344 } /* if (devpriv->b_OutputMemoryStatus ) */
347 } /* else if (devpriv->b_OutputMemoryStatus ) */
350 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
352 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
353 APCI1564_DIGITAL_OP_RW);
354 } /* if (data[1]==0) */
357 switch (ui_NoOfChannel) {
379 data[0] = data[0] | ui_Temp;
382 comedi_error(dev, " chan spec wrong");
383 return -EINVAL; /* "sorry channel spec wrong " */
384 } /* switch (ui_NoOfChannels) */
386 devpriv->i_IobaseAmcc +
387 APCI1564_DIGITAL_OP +
388 APCI1564_DIGITAL_OP_RW);
389 } /* if (data[1]==1) */
391 printk("\nSpecified channel not supported\n");
392 } /* else if (data[1]==1) */
393 } /* else if (data[1]==0) */
394 } /* if(data[3]==0) */
398 data[0] = ~data[0] & 0x1;
400 ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
401 ui_Temp = ui_Temp | ui_Temp1;
403 (data[0] << ui_NoOfChannel) ^
405 data[0] = data[0] & ui_Temp;
407 devpriv->i_IobaseAmcc +
408 APCI1564_DIGITAL_OP +
409 APCI1564_DIGITAL_OP_RW);
410 } /* if (data[1]==0) */
413 switch (ui_NoOfChannel) {
415 data[0] = ~data[0] & 0x3;
418 ui_Temp1 << 2 * data[2];
419 ui_Temp = ui_Temp | ui_Temp1;
424 0xffffffff) & ui_Temp;
427 data[0] = ~data[0] & 0xf;
430 ui_Temp1 << 4 * data[2];
431 ui_Temp = ui_Temp | ui_Temp1;
436 0xffffffff) & ui_Temp;
439 data[0] = ~data[0] & 0xff;
442 ui_Temp1 << 8 * data[2];
443 ui_Temp = ui_Temp | ui_Temp1;
448 0xffffffff) & ui_Temp;
451 data[0] = ~data[0] & 0xffff;
456 ui_Temp = ui_Temp | ui_Temp1;
461 0xffffffff) & ui_Temp;
468 return -EINVAL; /* "sorry channel spec wrong " */
469 } /* switch(ui_NoOfChannels) */
471 devpriv->i_IobaseAmcc +
472 APCI1564_DIGITAL_OP +
473 APCI1564_DIGITAL_OP_RW);
474 } /* if (data[1]==1) */
476 printk("\nSpecified channel not supported\n");
477 } /* else if (data[1]==1) */
478 } /* else if (data[1]==0) */
479 } /* if (data[3]==1); */
481 printk("\nSpecified functionality does not exist\n");
483 } /* else if (data[3]==1) */
484 } /* else if (data[3]==0) */
489 +----------------------------------------------------------------------------+
490 | Function Name : int i_APCI1564_ReadDigitalOutput |
491 | (struct comedi_device *dev,struct comedi_subdevice *s, |
492 | struct comedi_insn *insn,unsigned int *data) |
493 +----------------------------------------------------------------------------+
494 | Task : Read value of the selected channel or port |
495 +----------------------------------------------------------------------------+
496 | Input Parameters : struct comedi_device *dev : Driver handle |
497 | unsigned int ui_NoOfChannels : No Of Channels To read |
498 | unsigned int *data : Data Pointer to read status |
499 +----------------------------------------------------------------------------+
500 | Output Parameters : -- |
501 +----------------------------------------------------------------------------+
502 | Return Value : TRUE : No error occur |
503 | : FALSE : Error occur. Return the error |
505 +----------------------------------------------------------------------------+
507 static int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev,
508 struct comedi_subdevice *s,
509 struct comedi_insn *insn,
512 struct addi_private *devpriv = dev->private;
513 unsigned int ui_Temp;
514 unsigned int ui_NoOfChannel;
516 ui_NoOfChannel = CR_CHAN(insn->chanspec);
518 *data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
519 APCI1564_DIGITAL_OP_RW);
521 *data = (*data >> ui_NoOfChannel) & 0x1;
522 } /* if (ui_Temp==0) */
525 switch (ui_NoOfChannel) {
527 *data = (*data >> (2 * data[1])) & 3;
531 *data = (*data >> (4 * data[1])) & 15;
535 *data = (*data >> (8 * data[1])) & 255;
539 *data = (*data >> (16 * data[1])) & 65535;
546 comedi_error(dev, " chan spec wrong");
547 return -EINVAL; /* "sorry channel spec wrong " */
549 } /* switch(ui_NoOfChannels) */
550 } /* if (ui_Temp==1) */
552 printk("\nSpecified channel not supported \n");
553 } /* else if (ui_Temp==1) */
554 } /* else if (ui_Temp==0) */
559 +----------------------------------------------------------------------------+
560 | Function Name : int i_APCI1564_ConfigTimerCounterWatchdog |
561 | (struct comedi_device *dev,struct comedi_subdevice *s, |
562 | struct comedi_insn *insn,unsigned int *data) |
563 +----------------------------------------------------------------------------+
564 | Task : Configures The Timer , Counter or Watchdog |
565 +----------------------------------------------------------------------------+
566 | Input Parameters : struct comedi_device *dev : Driver handle |
567 | unsigned int *data : Data Pointer contains |
568 | configuration parameters as below |
570 | data[0] : 0 Configure As Timer |
571 | 1 Configure As Counter |
572 | 2 Configure As Watchdog |
573 | data[1] : 1 Enable Interrupt |
574 | 0 Disable Interrupt |
575 | data[2] : Time Unit |
576 | data[3] : Reload Value |
577 | data[4] : Timer Mode |
578 | data[5] : Timer Counter Watchdog Number|
579 data[6] : Counter Direction
580 +----------------------------------------------------------------------------+
581 | Output Parameters : -- |
582 +----------------------------------------------------------------------------+
583 | Return Value : TRUE : No error occur |
584 | : FALSE : Error occur. Return the error |
586 +----------------------------------------------------------------------------+
588 static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
589 struct comedi_subdevice *s,
590 struct comedi_insn *insn,
593 struct addi_private *devpriv = dev->private;
594 unsigned int ul_Command1 = 0;
596 devpriv->tsk_Current = current;
597 if (data[0] == ADDIDATA_WATCHDOG) {
598 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
600 /* Disable the watchdog */
602 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
604 /* Loading the Reload value */
606 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
607 APCI1564_TCW_RELOAD_VALUE);
608 } /* if (data[0]==ADDIDATA_WATCHDOG) */
609 else if (data[0] == ADDIDATA_TIMER) {
610 /* First Stop The Timer */
612 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
614 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
615 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Stop The Timer */
617 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
619 outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
621 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
622 APCI1564_DIGITAL_IP_IRQ);
624 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
625 APCI1564_DIGITAL_OP_IRQ);
627 devpriv->i_IobaseAmcc +
628 APCI1564_DIGITAL_OP_WATCHDOG +
631 devpriv->iobase + APCI1564_COUNTER1 +
634 devpriv->iobase + APCI1564_COUNTER2 +
637 devpriv->iobase + APCI1564_COUNTER3 +
640 devpriv->iobase + APCI1564_COUNTER4 +
642 } /* if (data[1]==1) */
644 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* disable Timer interrupt */
645 } /* else if (data[1]==1) */
647 /* Loading Timebase */
650 devpriv->i_IobaseAmcc + APCI1564_TIMER +
651 APCI1564_TCW_TIMEBASE);
653 /* Loading the Reload value */
655 devpriv->i_IobaseAmcc + APCI1564_TIMER +
656 APCI1564_TCW_RELOAD_VALUE);
659 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
662 (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
663 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* mode 2 */
664 } /* else if (data[0]==ADDIDATA_TIMER) */
665 else if (data[0] == ADDIDATA_COUNTER) {
666 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
667 devpriv->b_ModeSelectRegister = data[5];
669 /* First Stop The Counter */
671 inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
673 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
674 outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); /* Stop The Timer */
676 /************************/
677 /* Set the reload value */
678 /************************/
680 devpriv->iobase + ((data[5] - 1) * 0x20) +
681 APCI1564_TCW_RELOAD_VALUE);
683 /******************************/
685 /* - Disable the hardware */
686 /* - Disable the counter mode */
687 /* - Disable the warning */
688 /* - Disable the reset */
689 /* - Disable the timer mode */
690 /* - Enable the counter mode */
691 /******************************/
693 (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
694 (unsigned int) ((unsigned int) data[4] << 16UL);
696 devpriv->iobase + ((data[5] - 1) * 0x20) +
699 /* Enable or Disable Interrupt */
700 ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
702 devpriv->iobase + ((data[5] - 1) * 0x20) +
705 /*****************************/
706 /* Set the Up/Down selection */
707 /*****************************/
708 ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
710 devpriv->iobase + ((data[5] - 1) * 0x20) +
712 } /* else if (data[0]==ADDIDATA_COUNTER) */
714 printk(" Invalid subdevice.");
715 } /* else if (data[0]==ADDIDATA_WATCHDOG) */
721 +----------------------------------------------------------------------------+
722 | Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog |
723 | (struct comedi_device *dev,struct comedi_subdevice *s, |
724 | struct comedi_insn *insn,unsigned int *data) |
725 +----------------------------------------------------------------------------+
726 | Task : Start / Stop The Selected Timer , Counter or Watchdog |
727 +----------------------------------------------------------------------------+
728 | Input Parameters : struct comedi_device *dev : Driver handle |
729 | unsigned int *data : Data Pointer contains |
730 | configuration parameters as below |
732 | data[0] : 0 Timer |
734 | 2 Watchdog | | data[1] : 1 Start |
737 | Clear (Only Counter) |
738 +----------------------------------------------------------------------------+
739 | Output Parameters : -- |
740 +----------------------------------------------------------------------------+
741 | Return Value : TRUE : No error occur |
742 | : FALSE : Error occur. Return the error |
744 +----------------------------------------------------------------------------+
746 static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
747 struct comedi_subdevice *s,
748 struct comedi_insn *insn,
751 struct addi_private *devpriv = dev->private;
752 unsigned int ul_Command1 = 0;
754 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
756 case 0: /* stop the watchdog */
757 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG); /* disable the watchdog */
759 case 1: /* start the watchdog */
761 devpriv->i_IobaseAmcc +
762 APCI1564_DIGITAL_OP_WATCHDOG +
765 case 2: /* Software trigger */
767 devpriv->i_IobaseAmcc +
768 APCI1564_DIGITAL_OP_WATCHDOG +
772 printk("\nSpecified functionality does not exist\n");
774 } /* switch (data[1]) */
775 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
776 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
779 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
781 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
783 /* Enable the Timer */
785 devpriv->i_IobaseAmcc + APCI1564_TIMER +
787 } /* if (data[1]==1) */
788 else if (data[1] == 0) {
792 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
794 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
796 devpriv->i_IobaseAmcc + APCI1564_TIMER +
798 } /* else if(data[1]==0) */
799 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
800 if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
802 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
803 1) * 0x20) + APCI1564_TCW_PROG);
805 /* Start the Counter subdevice */
806 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
807 } /* if (data[1] == 1) */
808 else if (data[1] == 0) {
809 /* Stops the Counter subdevice */
812 } /* else if (data[1] == 0) */
813 else if (data[1] == 2) {
814 /* Clears the Counter subdevice */
815 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
816 } /* else if (data[1] == 3) */
818 devpriv->iobase + ((devpriv->b_ModeSelectRegister -
819 1) * 0x20) + APCI1564_TCW_PROG);
820 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
825 +----------------------------------------------------------------------------+
826 | Function Name : int i_APCI1564_ReadTimerCounterWatchdog |
827 | (struct comedi_device *dev,struct comedi_subdevice *s, |
828 | struct comedi_insn *insn,unsigned int *data) |
829 +----------------------------------------------------------------------------+
830 | Task : Read The Selected Timer , Counter or Watchdog |
831 +----------------------------------------------------------------------------+
832 | Input Parameters : struct comedi_device *dev : Driver handle |
833 | unsigned int *data : Data Pointer contains |
834 | configuration parameters as below |
837 +----------------------------------------------------------------------------+
838 | Output Parameters : -- |
839 +----------------------------------------------------------------------------+
840 | Return Value : TRUE : No error occur |
841 | : FALSE : Error occur. Return the error |
843 +----------------------------------------------------------------------------+
845 static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
846 struct comedi_subdevice *s,
847 struct comedi_insn *insn,
850 struct addi_private *devpriv = dev->private;
851 unsigned int ul_Command1 = 0;
853 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
854 /* Stores the status of the Watchdog */
856 inl(devpriv->i_IobaseAmcc +
857 APCI1564_DIGITAL_OP_WATCHDOG +
858 APCI1564_TCW_TRIG_STATUS) & 0x1;
860 inl(devpriv->i_IobaseAmcc +
861 APCI1564_DIGITAL_OP_WATCHDOG);
862 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
863 else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
864 /* Stores the status of the Timer */
866 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
867 APCI1564_TCW_TRIG_STATUS) & 0x1;
869 /* Stores the Actual value of the Timer */
870 data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
871 } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
872 else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
873 /* Read the Counter Actual Value. */
875 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
877 APCI1564_TCW_SYNC_ENABLEDISABLE);
879 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
880 1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
882 /***********************************/
883 /* Get the software trigger status */
884 /***********************************/
885 data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
887 /***********************************/
888 /* Get the hardware trigger status */
889 /***********************************/
890 data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
892 /*********************************/
893 /* Get the software clear status */
894 /*********************************/
895 data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
897 /***************************/
898 /* Get the overflow status */
899 /***************************/
900 data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
901 } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
902 else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
903 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
904 && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
905 printk("\n Invalid Subdevice !!!\n");
906 } /* else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) */
911 +----------------------------------------------------------------------------+
912 | Function Name : int i_APCI1564_ReadInterruptStatus |
913 | (struct comedi_device *dev,struct comedi_subdevice *s, |
914 | struct comedi_insn *insn,unsigned int *data) |
915 +----------------------------------------------------------------------------+
916 | Task :Reads the interrupt status register |
917 +----------------------------------------------------------------------------+
918 | Input Parameters : |
919 +----------------------------------------------------------------------------+
920 | Output Parameters : -- |
921 +----------------------------------------------------------------------------+
924 +----------------------------------------------------------------------------+
927 static int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev,
928 struct comedi_subdevice *s,
929 struct comedi_insn *insn,
937 +----------------------------------------------------------------------------+
938 | Function Name : static void v_APCI1564_Interrupt |
939 | (int irq , void *d) |
940 +----------------------------------------------------------------------------+
941 | Task : Interrupt handler for the interruptible digital inputs |
942 +----------------------------------------------------------------------------+
943 | Input Parameters : int irq : irq number |
944 | void *d : void pointer |
945 +----------------------------------------------------------------------------+
946 | Output Parameters : -- |
947 +----------------------------------------------------------------------------+
948 | Return Value : TRUE : No error occur |
949 | : FALSE : Error occur. Return the error |
951 +----------------------------------------------------------------------------+
953 static void v_APCI1564_Interrupt(int irq, void *d)
955 struct comedi_device *dev = d;
956 struct addi_private *devpriv = dev->private;
957 unsigned int ui_DO, ui_DI;
958 unsigned int ui_Timer;
959 unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
960 unsigned int ul_Command2 = 0;
962 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
963 APCI1564_DIGITAL_IP_IRQ) & 0x01;
964 ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
965 APCI1564_DIGITAL_OP_IRQ) & 0x01;
967 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
968 APCI1564_TCW_IRQ) & 0x01;
969 ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 +
970 APCI1564_TCW_IRQ) & 0x1;
971 ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 +
972 APCI1564_TCW_IRQ) & 0x1;
973 ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 +
974 APCI1564_TCW_IRQ) & 0x1;
975 ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 +
976 APCI1564_TCW_IRQ) & 0x1;
977 if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
978 && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
979 printk("\nInterrupt from unknown source\n");
980 } /* if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) */
983 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
984 APCI1564_DIGITAL_IP_IRQ);
986 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
987 APCI1564_DIGITAL_IP_IRQ);
988 ui_InterruptStatus_1564 =
989 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
990 APCI1564_DIGITAL_IP_INTERRUPT_STATUS);
991 ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
992 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
993 outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); /* enable the interrupt */
998 /* Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
1000 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
1001 APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
1002 /* Disable the Interrupt */
1004 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
1005 APCI1564_DIGITAL_OP_INTERRUPT);
1007 /* Sends signal to user space */
1008 send_sig(SIGIO, devpriv->tsk_Current, 0);
1012 if (ui_Timer == 1) {
1013 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
1014 if (devpriv->b_TimerSelectMode) {
1016 /* Disable Timer Interrupt */
1018 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
1021 devpriv->i_IobaseAmcc + APCI1564_TIMER +
1024 /* Send a signal to from kernel to user space */
1025 send_sig(SIGIO, devpriv->tsk_Current, 0);
1027 /* Enable Timer Interrupt */
1030 devpriv->i_IobaseAmcc + APCI1564_TIMER +
1033 }/* if (ui_Timer == 1) */
1037 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1038 if (devpriv->b_TimerSelectMode) {
1040 /* Disable Counter Interrupt */
1042 inl(devpriv->iobase + APCI1564_COUNTER1 +
1045 devpriv->iobase + APCI1564_COUNTER1 +
1048 /* Send a signal to from kernel to user space */
1049 send_sig(SIGIO, devpriv->tsk_Current, 0);
1051 /* Enable Counter Interrupt */
1053 devpriv->iobase + APCI1564_COUNTER1 +
1056 } /* if (ui_C1 == 1) */
1059 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1060 if (devpriv->b_TimerSelectMode) {
1062 /* Disable Counter Interrupt */
1064 inl(devpriv->iobase + APCI1564_COUNTER2 +
1067 devpriv->iobase + APCI1564_COUNTER2 +
1070 /* Send a signal to from kernel to user space */
1071 send_sig(SIGIO, devpriv->tsk_Current, 0);
1073 /* Enable Counter Interrupt */
1075 devpriv->iobase + APCI1564_COUNTER2 +
1078 } /* if ((ui_C2 == 1) */
1081 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1082 if (devpriv->b_TimerSelectMode) {
1084 /* Disable Counter Interrupt */
1086 inl(devpriv->iobase + APCI1564_COUNTER3 +
1089 devpriv->iobase + APCI1564_COUNTER3 +
1092 /* Send a signal to from kernel to user space */
1093 send_sig(SIGIO, devpriv->tsk_Current, 0);
1095 /* Enable Counter Interrupt */
1097 devpriv->iobase + APCI1564_COUNTER3 +
1100 } /* if ((ui_C3 == 1) */
1103 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1104 if (devpriv->b_TimerSelectMode) {
1106 /* Disable Counter Interrupt */
1108 inl(devpriv->iobase + APCI1564_COUNTER4 +
1111 devpriv->iobase + APCI1564_COUNTER4 +
1114 /* Send a signal to from kernel to user space */
1115 send_sig(SIGIO, devpriv->tsk_Current, 0);
1117 /* Enable Counter Interrupt */
1119 devpriv->iobase + APCI1564_COUNTER4 +
1122 } /* if (ui_C4 == 1) */
1127 +----------------------------------------------------------------------------+
1128 | Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | |
1129 +----------------------------------------------------------------------------+
1130 | Task :resets all the registers |
1131 +----------------------------------------------------------------------------+
1132 | Input Parameters : struct comedi_device *dev
1133 +----------------------------------------------------------------------------+
1134 | Output Parameters : -- |
1135 +----------------------------------------------------------------------------+
1138 +----------------------------------------------------------------------------+
1141 static int i_APCI1564_Reset(struct comedi_device *dev)
1143 struct addi_private *devpriv = dev->private;
1145 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ); /* disable the interrupts */
1146 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); /* Reset the interrupt status register */
1147 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); /* Disable the and/or interrupt */
1148 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
1149 devpriv->b_DigitalOutputRegister = 0;
1151 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); /* Resets the output channels */
1152 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT); /* Disables the interrupt. */
1154 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
1155 APCI1564_TCW_RELOAD_VALUE);
1156 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER);
1157 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);
1159 outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG);
1160 outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG);
1161 outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG);
1162 outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG);