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 +----------+-----------+------------------------------------------------+
49 /********* Definitions for APCI-1564 card *****/
51 #define APCI1564_ADDRESS_RANGE 128
53 /* DIGITAL INPUT-OUTPUT DEFINE */
55 #define APCI1564_DIGITAL_IP 0x04
56 #define APCI1564_DIGITAL_IP_INTERRUPT_MODE1 4
57 #define APCI1564_DIGITAL_IP_INTERRUPT_MODE2 8
58 #define APCI1564_DIGITAL_IP_IRQ 16
61 #define APCI1564_DIGITAL_OP 0x18
62 #define APCI1564_DIGITAL_OP_RW 0
63 #define APCI1564_DIGITAL_OP_INTERRUPT 4
64 #define APCI1564_DIGITAL_OP_IRQ 12
66 /* Digital Input IRQ Function Selection */
68 #define ADDIDATA_AND 1
70 /* Digital Input Interrupt Status */
71 #define APCI1564_DIGITAL_IP_INTERRUPT_STATUS 12
73 /* Digital Output Interrupt Status */
74 #define APCI1564_DIGITAL_OP_INTERRUPT_STATUS 8
76 /* Digital Input Interrupt Enable Disable. */
77 #define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE 0x4
78 #define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE 0xfffffffb
80 /* Digital Output Interrupt Enable Disable. */
81 #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1
82 #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xfffffffe
83 #define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2
84 #define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xfffffffd
86 /* ADDIDATA Enable Disable */
88 #define ADDIDATA_ENABLE 1
89 #define ADDIDATA_DISABLE 0
91 /* TIMER COUNTER WATCHDOG DEFINES */
93 #define ADDIDATA_TIMER 0
94 #define ADDIDATA_COUNTER 1
95 #define ADDIDATA_WATCHDOG 2
96 #define APCI1564_DIGITAL_OP_WATCHDOG 0x28
97 #define APCI1564_TIMER 0x48
98 #define APCI1564_COUNTER1 0x0
99 #define APCI1564_COUNTER2 0x20
100 #define APCI1564_COUNTER3 0x40
101 #define APCI1564_COUNTER4 0x60
102 #define APCI1564_TCW_SYNC_ENABLEDISABLE 0
103 #define APCI1564_TCW_RELOAD_VALUE 4
104 #define APCI1564_TCW_TIMEBASE 8
105 #define APCI1564_TCW_PROG 12
106 #define APCI1564_TCW_TRIG_STATUS 16
107 #define APCI1564_TCW_IRQ 20
108 #define APCI1564_TCW_WARN_TIMEVAL 24
109 #define APCI1564_TCW_WARN_TIMEBASE 28
111 /* Global variables */
112 static unsigned int ui_InterruptStatus_1564 = 0;
113 static unsigned int ui_InterruptData, ui_Type;
116 +----------------------------------------------------------------------------+
117 | Function Name : int i_APCI1564_ConfigDigitalInput |
118 | (struct comedi_device *dev,struct comedi_subdevice *s, |
119 | struct comedi_insn *insn,unsigned int *data) |
120 +----------------------------------------------------------------------------+
121 | Task : Configures the digital input Subdevice |
122 +----------------------------------------------------------------------------+
123 | Input Parameters : struct comedi_device *dev : Driver handle |
124 | unsigned int *data : Data Pointer contains |
125 | configuration parameters as below |
127 | data[0] : 1 Enable Digital Input Interrupt |
128 | 0 Disable Digital Input Interrupt |
129 | data[1] : 0 ADDIDATA Interrupt OR LOGIC |
130 | : 1 ADDIDATA Interrupt AND LOGIC |
131 | data[2] : Interrupt mask for the mode 1 |
132 | data[3] : Interrupt mask for the mode 2 |
134 +----------------------------------------------------------------------------+
135 | Output Parameters : -- |
136 +----------------------------------------------------------------------------+
137 | Return Value : TRUE : No error occur |
138 | : FALSE : Error occur. Return the error |
140 +----------------------------------------------------------------------------+
142 static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev,
143 struct comedi_subdevice *s,
144 struct comedi_insn *insn,
147 struct addi_private *devpriv = dev->private;
149 devpriv->tsk_Current = current;
150 /*******************************/
151 /* Set the digital input logic */
152 /*******************************/
153 if (data[0] == ADDIDATA_ENABLE) {
154 data[2] = data[2] << 4;
155 data[3] = data[3] << 4;
157 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
158 APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
160 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
161 APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
162 if (data[1] == ADDIDATA_OR) {
164 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
165 APCI1564_DIGITAL_IP_IRQ);
166 } /* if (data[1] == ADDIDATA_OR) */
169 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
170 APCI1564_DIGITAL_IP_IRQ);
171 } /* else if (data[1] == ADDIDATA_OR) */
172 } /* if (data[0] == ADDIDATA_ENABLE) */
175 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
176 APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
178 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
179 APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
181 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
182 APCI1564_DIGITAL_IP_IRQ);
183 } /* else if (data[0] == ADDIDATA_ENABLE) */
189 +----------------------------------------------------------------------------+
190 | Function Name : int i_APCI1564_Read1DigitalInput |
191 | (struct comedi_device *dev,struct comedi_subdevice *s, |
192 | struct comedi_insn *insn,unsigned int *data) |
193 +----------------------------------------------------------------------------+
194 | Task : Return the status of the digital input |
195 +----------------------------------------------------------------------------+
196 | Input Parameters : struct comedi_device *dev : Driver handle |
197 | unsigned int ui_Channel : Channel number to read |
198 | unsigned int *data : Data Pointer to read status |
199 +----------------------------------------------------------------------------+
200 | Output Parameters : -- |
201 +----------------------------------------------------------------------------+
202 | Return Value : TRUE : No error occur |
203 | : FALSE : Error occur. Return the error |
205 +----------------------------------------------------------------------------+
207 static int i_APCI1564_Read1DigitalInput(struct comedi_device *dev,
208 struct comedi_subdevice *s,
209 struct comedi_insn *insn,
212 struct addi_private *devpriv = dev->private;
213 unsigned int ui_TmpValue = 0;
214 unsigned int ui_Channel;
216 ui_Channel = CR_CHAN(insn->chanspec);
217 if (ui_Channel <= 31) {
219 (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
221 * since only 1 channel reqd to bring it to last bit it is rotated 8
222 * +(chan - 1) times then ANDed with 1 for last bit.
224 *data = (ui_TmpValue >> ui_Channel) & 0x1;
225 } /* if (ui_Channel >= 0 && ui_Channel <=31) */
227 comedi_error(dev, "Not a valid channel number !!! \n");
228 return -EINVAL; /* "sorry channel spec wrong " */
229 } /* else if (ui_Channel >= 0 && ui_Channel <=31) */
234 +----------------------------------------------------------------------------+
235 | Function Name : int i_APCI1564_ReadMoreDigitalInput |
236 | (struct comedi_device *dev,struct comedi_subdevice *s, |
237 | struct comedi_insn *insn,unsigned int *data) |
238 +----------------------------------------------------------------------------+
239 | Task : Return the status of the Requested digital inputs |
240 +----------------------------------------------------------------------------+
241 | Input Parameters : struct comedi_device *dev : Driver handle |
242 | unsigned int ui_NoOfChannels : No Of Channels To be Read |
243 | unsigned int *data : Data Pointer to read status |
244 +----------------------------------------------------------------------------+
245 | Output Parameters : -- |
246 +----------------------------------------------------------------------------+
247 | Return Value : TRUE : No error occur |
248 | : FALSE : Error occur. Return the error |
250 +----------------------------------------------------------------------------+
252 static int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev,
253 struct comedi_subdevice *s,
254 struct comedi_insn *insn,
257 struct addi_private *devpriv = dev->private;
258 unsigned int ui_PortValue = data[0];
259 unsigned int ui_Mask = 0;
260 unsigned int ui_NoOfChannels;
262 ui_NoOfChannels = CR_CHAN(insn->chanspec);
264 *data = (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
265 switch (ui_NoOfChannels) {
268 *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
272 *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
276 *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
280 *data = (*data >> (16 * ui_PortValue)) & ui_Mask;
285 comedi_error(dev, "Not a valid Channel number !!!\n");
286 return -EINVAL; /* "sorry channel spec wrong " */
288 } /* switch (ui_NoOfChannels) */
289 } /* if (data[1]==0) */
292 *data = ui_InterruptStatus_1564;
293 } /* if (data[1]==1) */
294 } /* else if (data[1]==0) */
299 +----------------------------------------------------------------------------+
300 | Function Name : int i_APCI1564_ConfigDigitalOutput |
301 | (struct comedi_device *dev,struct comedi_subdevice *s, |
302 | struct comedi_insn *insn,unsigned int *data) |
303 +----------------------------------------------------------------------------+
304 | Task : Configures The Digital Output Subdevice. |
305 +----------------------------------------------------------------------------+
306 | Input Parameters : struct comedi_device *dev : Driver handle |
307 | unsigned int *data : Data Pointer contains |
308 | configuration parameters as below |
310 | data[1] : 1 Enable VCC Interrupt |
311 | 0 Disable VCC Interrupt |
312 | data[2] : 1 Enable CC Interrupt |
313 | 0 Disable CC Interrupt |
315 +----------------------------------------------------------------------------+
316 | Output Parameters : -- |
317 +----------------------------------------------------------------------------+
318 | Return Value : TRUE : No error occur |
319 | : FALSE : Error occur. Return the error |
321 +----------------------------------------------------------------------------+
323 static int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev,
324 struct comedi_subdevice *s,
325 struct comedi_insn *insn,
328 struct addi_private *devpriv = dev->private;
329 unsigned int ul_Command = 0;
331 if ((data[0] != 0) && (data[0] != 1)) {
333 "Not a valid Data !!! ,Data should be 1 or 0\n");
335 } /* if ((data[0]!=0) && (data[0]!=1)) */
337 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
340 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
341 } /* else if (data[0]) */
342 if (data[1] == ADDIDATA_ENABLE) {
343 ul_Command = ul_Command | 0x1;
344 } /* if (data[1] == ADDIDATA_ENABLE) */
346 ul_Command = ul_Command & 0xFFFFFFFE;
347 } /* else if (data[1] == ADDIDATA_ENABLE) */
348 if (data[2] == ADDIDATA_ENABLE) {
349 ul_Command = ul_Command | 0x2;
350 } /* if (data[2] == ADDIDATA_ENABLE) */
352 ul_Command = ul_Command & 0xFFFFFFFD;
353 } /* else if (data[2] == ADDIDATA_ENABLE) */
355 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
356 APCI1564_DIGITAL_OP_INTERRUPT);
358 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
359 APCI1564_DIGITAL_OP_INTERRUPT);
360 devpriv->tsk_Current = current;
365 +----------------------------------------------------------------------------+
366 | Function Name : int i_APCI1564_WriteDigitalOutput |
367 | (struct comedi_device *dev,struct comedi_subdevice *s, |
368 | struct comedi_insn *insn,unsigned int *data) |
369 +----------------------------------------------------------------------------+
370 | Task : Writes port value To the selected port |
371 +----------------------------------------------------------------------------+
372 | Input Parameters : struct comedi_device *dev : Driver handle |
373 | unsigned int ui_NoOfChannels : No Of Channels To Write |
374 | unsigned int *data : Data Pointer to read status |
375 +----------------------------------------------------------------------------+
376 | Output Parameters : -- |
377 +----------------------------------------------------------------------------+
378 | Return Value : TRUE : No error occur |
379 | : FALSE : Error occur. Return the error |
381 +----------------------------------------------------------------------------+
383 static int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev,
384 struct comedi_subdevice *s,
385 struct comedi_insn *insn,
388 struct addi_private *devpriv = dev->private;
389 unsigned int ui_Temp, ui_Temp1;
390 unsigned int ui_NoOfChannel;
392 ui_NoOfChannel = CR_CHAN(insn->chanspec);
393 if (devpriv->b_OutputMemoryStatus) {
395 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
396 APCI1564_DIGITAL_OP_RW);
397 } /* if (devpriv->b_OutputMemoryStatus ) */
400 } /* else if (devpriv->b_OutputMemoryStatus ) */
403 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
405 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
406 APCI1564_DIGITAL_OP_RW);
407 } /* if (data[1]==0) */
410 switch (ui_NoOfChannel) {
432 data[0] = data[0] | ui_Temp;
435 comedi_error(dev, " chan spec wrong");
436 return -EINVAL; /* "sorry channel spec wrong " */
437 } /* switch (ui_NoOfChannels) */
439 devpriv->i_IobaseAmcc +
440 APCI1564_DIGITAL_OP +
441 APCI1564_DIGITAL_OP_RW);
442 } /* if (data[1]==1) */
444 printk("\nSpecified channel not supported\n");
445 } /* else if (data[1]==1) */
446 } /* else if (data[1]==0) */
447 } /* if(data[3]==0) */
451 data[0] = ~data[0] & 0x1;
453 ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
454 ui_Temp = ui_Temp | ui_Temp1;
456 (data[0] << ui_NoOfChannel) ^
458 data[0] = data[0] & ui_Temp;
460 devpriv->i_IobaseAmcc +
461 APCI1564_DIGITAL_OP +
462 APCI1564_DIGITAL_OP_RW);
463 } /* if (data[1]==0) */
466 switch (ui_NoOfChannel) {
468 data[0] = ~data[0] & 0x3;
471 ui_Temp1 << 2 * data[2];
472 ui_Temp = ui_Temp | ui_Temp1;
477 0xffffffff) & ui_Temp;
480 data[0] = ~data[0] & 0xf;
483 ui_Temp1 << 4 * data[2];
484 ui_Temp = ui_Temp | ui_Temp1;
489 0xffffffff) & ui_Temp;
492 data[0] = ~data[0] & 0xff;
495 ui_Temp1 << 8 * data[2];
496 ui_Temp = ui_Temp | ui_Temp1;
501 0xffffffff) & ui_Temp;
504 data[0] = ~data[0] & 0xffff;
509 ui_Temp = ui_Temp | ui_Temp1;
514 0xffffffff) & ui_Temp;
521 return -EINVAL; /* "sorry channel spec wrong " */
522 } /* switch(ui_NoOfChannels) */
524 devpriv->i_IobaseAmcc +
525 APCI1564_DIGITAL_OP +
526 APCI1564_DIGITAL_OP_RW);
527 } /* if (data[1]==1) */
529 printk("\nSpecified channel not supported\n");
530 } /* else if (data[1]==1) */
531 } /* else if (data[1]==0) */
532 } /* if (data[3]==1); */
534 printk("\nSpecified functionality does not exist\n");
536 } /* else if (data[3]==1) */
537 } /* else if (data[3]==0) */
542 +----------------------------------------------------------------------------+
543 | Function Name : int i_APCI1564_ReadDigitalOutput |
544 | (struct comedi_device *dev,struct comedi_subdevice *s, |
545 | struct comedi_insn *insn,unsigned int *data) |
546 +----------------------------------------------------------------------------+
547 | Task : Read value of the selected channel or port |
548 +----------------------------------------------------------------------------+
549 | Input Parameters : struct comedi_device *dev : Driver handle |
550 | unsigned int ui_NoOfChannels : No Of Channels To read |
551 | unsigned int *data : Data Pointer to read status |
552 +----------------------------------------------------------------------------+
553 | Output Parameters : -- |
554 +----------------------------------------------------------------------------+
555 | Return Value : TRUE : No error occur |
556 | : FALSE : Error occur. Return the error |
558 +----------------------------------------------------------------------------+
560 static int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev,
561 struct comedi_subdevice *s,
562 struct comedi_insn *insn,
565 struct addi_private *devpriv = dev->private;
566 unsigned int ui_Temp;
567 unsigned int ui_NoOfChannel;
569 ui_NoOfChannel = CR_CHAN(insn->chanspec);
571 *data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
572 APCI1564_DIGITAL_OP_RW);
574 *data = (*data >> ui_NoOfChannel) & 0x1;
575 } /* if (ui_Temp==0) */
578 switch (ui_NoOfChannel) {
580 *data = (*data >> (2 * data[1])) & 3;
584 *data = (*data >> (4 * data[1])) & 15;
588 *data = (*data >> (8 * data[1])) & 255;
592 *data = (*data >> (16 * data[1])) & 65535;
599 comedi_error(dev, " chan spec wrong");
600 return -EINVAL; /* "sorry channel spec wrong " */
602 } /* switch(ui_NoOfChannels) */
603 } /* if (ui_Temp==1) */
605 printk("\nSpecified channel not supported \n");
606 } /* else if (ui_Temp==1) */
607 } /* else if (ui_Temp==0) */
612 +----------------------------------------------------------------------------+
613 | Function Name : int i_APCI1564_ConfigTimerCounterWatchdog |
614 | (struct comedi_device *dev,struct comedi_subdevice *s, |
615 | struct comedi_insn *insn,unsigned int *data) |
616 +----------------------------------------------------------------------------+
617 | Task : Configures The Timer , Counter or Watchdog |
618 +----------------------------------------------------------------------------+
619 | Input Parameters : struct comedi_device *dev : Driver handle |
620 | unsigned int *data : Data Pointer contains |
621 | configuration parameters as below |
623 | data[0] : 0 Configure As Timer |
624 | 1 Configure As Counter |
625 | 2 Configure As Watchdog |
626 | data[1] : 1 Enable Interrupt |
627 | 0 Disable Interrupt |
628 | data[2] : Time Unit |
629 | data[3] : Reload Value |
630 | data[4] : Timer Mode |
631 | data[5] : Timer Counter Watchdog Number|
632 data[6] : Counter Direction
633 +----------------------------------------------------------------------------+
634 | Output Parameters : -- |
635 +----------------------------------------------------------------------------+
636 | Return Value : TRUE : No error occur |
637 | : FALSE : Error occur. Return the error |
639 +----------------------------------------------------------------------------+
641 static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
642 struct comedi_subdevice *s,
643 struct comedi_insn *insn,
646 struct addi_private *devpriv = dev->private;
647 unsigned int ul_Command1 = 0;
649 devpriv->tsk_Current = current;
650 if (data[0] == ADDIDATA_WATCHDOG) {
651 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
653 /* Disable the watchdog */
655 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
657 /* Loading the Reload value */
659 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
660 APCI1564_TCW_RELOAD_VALUE);
661 } /* if (data[0]==ADDIDATA_WATCHDOG) */
662 else if (data[0] == ADDIDATA_TIMER) {
663 /* First Stop The Timer */
665 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
667 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
668 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Stop The Timer */
670 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
672 outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
674 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
675 APCI1564_DIGITAL_IP_IRQ);
677 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
678 APCI1564_DIGITAL_OP_IRQ);
680 devpriv->i_IobaseAmcc +
681 APCI1564_DIGITAL_OP_WATCHDOG +
684 devpriv->iobase + APCI1564_COUNTER1 +
687 devpriv->iobase + APCI1564_COUNTER2 +
690 devpriv->iobase + APCI1564_COUNTER3 +
693 devpriv->iobase + APCI1564_COUNTER4 +
695 } /* if (data[1]==1) */
697 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* disable Timer interrupt */
698 } /* else if (data[1]==1) */
700 /* Loading Timebase */
703 devpriv->i_IobaseAmcc + APCI1564_TIMER +
704 APCI1564_TCW_TIMEBASE);
706 /* Loading the Reload value */
708 devpriv->i_IobaseAmcc + APCI1564_TIMER +
709 APCI1564_TCW_RELOAD_VALUE);
712 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
715 (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
716 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* mode 2 */
717 } /* else if (data[0]==ADDIDATA_TIMER) */
718 else if (data[0] == ADDIDATA_COUNTER) {
719 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
720 devpriv->b_ModeSelectRegister = data[5];
722 /* First Stop The Counter */
724 inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
726 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
727 outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); /* Stop The Timer */
729 /************************/
730 /* Set the reload value */
731 /************************/
733 devpriv->iobase + ((data[5] - 1) * 0x20) +
734 APCI1564_TCW_RELOAD_VALUE);
736 /******************************/
738 /* - Disable the hardware */
739 /* - Disable the counter mode */
740 /* - Disable the warning */
741 /* - Disable the reset */
742 /* - Disable the timer mode */
743 /* - Enable the counter mode */
744 /******************************/
746 (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
747 (unsigned int) ((unsigned int) data[4] << 16UL);
749 devpriv->iobase + ((data[5] - 1) * 0x20) +
752 /* Enable or Disable Interrupt */
753 ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
755 devpriv->iobase + ((data[5] - 1) * 0x20) +
758 /*****************************/
759 /* Set the Up/Down selection */
760 /*****************************/
761 ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
763 devpriv->iobase + ((data[5] - 1) * 0x20) +
765 } /* else if (data[0]==ADDIDATA_COUNTER) */
767 printk(" Invalid subdevice.");
768 } /* else if (data[0]==ADDIDATA_WATCHDOG) */
774 +----------------------------------------------------------------------------+
775 | Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog |
776 | (struct comedi_device *dev,struct comedi_subdevice *s, |
777 | struct comedi_insn *insn,unsigned int *data) |
778 +----------------------------------------------------------------------------+
779 | Task : Start / Stop The Selected Timer , Counter or Watchdog |
780 +----------------------------------------------------------------------------+
781 | Input Parameters : struct comedi_device *dev : Driver handle |
782 | unsigned int *data : Data Pointer contains |
783 | configuration parameters as below |
785 | data[0] : 0 Timer |
787 | 2 Watchdog | | data[1] : 1 Start |
790 | Clear (Only Counter) |
791 +----------------------------------------------------------------------------+
792 | Output Parameters : -- |
793 +----------------------------------------------------------------------------+
794 | Return Value : TRUE : No error occur |
795 | : FALSE : Error occur. Return the error |
797 +----------------------------------------------------------------------------+
799 static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
800 struct comedi_subdevice *s,
801 struct comedi_insn *insn,
804 struct addi_private *devpriv = dev->private;
805 unsigned int ul_Command1 = 0;
807 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
809 case 0: /* stop the watchdog */
810 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG); /* disable the watchdog */
812 case 1: /* start the watchdog */
814 devpriv->i_IobaseAmcc +
815 APCI1564_DIGITAL_OP_WATCHDOG +
818 case 2: /* Software trigger */
820 devpriv->i_IobaseAmcc +
821 APCI1564_DIGITAL_OP_WATCHDOG +
825 printk("\nSpecified functionality does not exist\n");
827 } /* switch (data[1]) */
828 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
829 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
832 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
834 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
836 /* Enable the Timer */
838 devpriv->i_IobaseAmcc + APCI1564_TIMER +
840 } /* if (data[1]==1) */
841 else if (data[1] == 0) {
845 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
847 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
849 devpriv->i_IobaseAmcc + APCI1564_TIMER +
851 } /* else if(data[1]==0) */
852 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
853 if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
855 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
856 1) * 0x20) + APCI1564_TCW_PROG);
858 /* Start the Counter subdevice */
859 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
860 } /* if (data[1] == 1) */
861 else if (data[1] == 0) {
862 /* Stops the Counter subdevice */
865 } /* else if (data[1] == 0) */
866 else if (data[1] == 2) {
867 /* Clears the Counter subdevice */
868 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
869 } /* else if (data[1] == 3) */
871 devpriv->iobase + ((devpriv->b_ModeSelectRegister -
872 1) * 0x20) + APCI1564_TCW_PROG);
873 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
878 +----------------------------------------------------------------------------+
879 | Function Name : int i_APCI1564_ReadTimerCounterWatchdog |
880 | (struct comedi_device *dev,struct comedi_subdevice *s, |
881 | struct comedi_insn *insn,unsigned int *data) |
882 +----------------------------------------------------------------------------+
883 | Task : Read The Selected Timer , Counter or Watchdog |
884 +----------------------------------------------------------------------------+
885 | Input Parameters : struct comedi_device *dev : Driver handle |
886 | unsigned int *data : Data Pointer contains |
887 | configuration parameters as below |
890 +----------------------------------------------------------------------------+
891 | Output Parameters : -- |
892 +----------------------------------------------------------------------------+
893 | Return Value : TRUE : No error occur |
894 | : FALSE : Error occur. Return the error |
896 +----------------------------------------------------------------------------+
898 static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
899 struct comedi_subdevice *s,
900 struct comedi_insn *insn,
903 struct addi_private *devpriv = dev->private;
904 unsigned int ul_Command1 = 0;
906 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
907 /* Stores the status of the Watchdog */
909 inl(devpriv->i_IobaseAmcc +
910 APCI1564_DIGITAL_OP_WATCHDOG +
911 APCI1564_TCW_TRIG_STATUS) & 0x1;
913 inl(devpriv->i_IobaseAmcc +
914 APCI1564_DIGITAL_OP_WATCHDOG);
915 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
916 else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
917 /* Stores the status of the Timer */
919 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
920 APCI1564_TCW_TRIG_STATUS) & 0x1;
922 /* Stores the Actual value of the Timer */
923 data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
924 } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
925 else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
926 /* Read the Counter Actual Value. */
928 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
930 APCI1564_TCW_SYNC_ENABLEDISABLE);
932 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
933 1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
935 /***********************************/
936 /* Get the software trigger status */
937 /***********************************/
938 data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
940 /***********************************/
941 /* Get the hardware trigger status */
942 /***********************************/
943 data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
945 /*********************************/
946 /* Get the software clear status */
947 /*********************************/
948 data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
950 /***************************/
951 /* Get the overflow status */
952 /***************************/
953 data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
954 } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
955 else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
956 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
957 && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
958 printk("\n Invalid Subdevice !!!\n");
959 } /* else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) */
964 +----------------------------------------------------------------------------+
965 | Function Name : int i_APCI1564_ReadInterruptStatus |
966 | (struct comedi_device *dev,struct comedi_subdevice *s, |
967 | struct comedi_insn *insn,unsigned int *data) |
968 +----------------------------------------------------------------------------+
969 | Task :Reads the interrupt status register |
970 +----------------------------------------------------------------------------+
971 | Input Parameters : |
972 +----------------------------------------------------------------------------+
973 | Output Parameters : -- |
974 +----------------------------------------------------------------------------+
977 +----------------------------------------------------------------------------+
980 static int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev,
981 struct comedi_subdevice *s,
982 struct comedi_insn *insn,
990 +----------------------------------------------------------------------------+
991 | Function Name : static void v_APCI1564_Interrupt |
992 | (int irq , void *d) |
993 +----------------------------------------------------------------------------+
994 | Task : Interrupt handler for the interruptible digital inputs |
995 +----------------------------------------------------------------------------+
996 | Input Parameters : int irq : irq number |
997 | void *d : void pointer |
998 +----------------------------------------------------------------------------+
999 | Output Parameters : -- |
1000 +----------------------------------------------------------------------------+
1001 | Return Value : TRUE : No error occur |
1002 | : FALSE : Error occur. Return the error |
1004 +----------------------------------------------------------------------------+
1006 static void v_APCI1564_Interrupt(int irq, void *d)
1008 struct comedi_device *dev = d;
1009 struct addi_private *devpriv = dev->private;
1010 unsigned int ui_DO, ui_DI;
1011 unsigned int ui_Timer;
1012 unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
1013 unsigned int ul_Command2 = 0;
1015 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
1016 APCI1564_DIGITAL_IP_IRQ) & 0x01;
1017 ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
1018 APCI1564_DIGITAL_OP_IRQ) & 0x01;
1020 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
1021 APCI1564_TCW_IRQ) & 0x01;
1022 ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 +
1023 APCI1564_TCW_IRQ) & 0x1;
1024 ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 +
1025 APCI1564_TCW_IRQ) & 0x1;
1026 ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 +
1027 APCI1564_TCW_IRQ) & 0x1;
1028 ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 +
1029 APCI1564_TCW_IRQ) & 0x1;
1030 if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
1031 && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
1032 printk("\nInterrupt from unknown source\n");
1033 } /* if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) */
1036 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
1037 APCI1564_DIGITAL_IP_IRQ);
1039 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
1040 APCI1564_DIGITAL_IP_IRQ);
1041 ui_InterruptStatus_1564 =
1042 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
1043 APCI1564_DIGITAL_IP_INTERRUPT_STATUS);
1044 ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
1045 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
1046 outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); /* enable the interrupt */
1051 /* Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
1053 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
1054 APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
1055 /* Disable the Interrupt */
1057 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
1058 APCI1564_DIGITAL_OP_INTERRUPT);
1060 /* Sends signal to user space */
1061 send_sig(SIGIO, devpriv->tsk_Current, 0);
1065 if (ui_Timer == 1) {
1066 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
1067 if (devpriv->b_TimerSelectMode) {
1069 /* Disable Timer Interrupt */
1071 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
1074 devpriv->i_IobaseAmcc + APCI1564_TIMER +
1077 /* Send a signal to from kernel to user space */
1078 send_sig(SIGIO, devpriv->tsk_Current, 0);
1080 /* Enable Timer Interrupt */
1083 devpriv->i_IobaseAmcc + APCI1564_TIMER +
1086 }/* if (ui_Timer == 1) */
1090 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1091 if (devpriv->b_TimerSelectMode) {
1093 /* Disable Counter Interrupt */
1095 inl(devpriv->iobase + APCI1564_COUNTER1 +
1098 devpriv->iobase + APCI1564_COUNTER1 +
1101 /* Send a signal to from kernel to user space */
1102 send_sig(SIGIO, devpriv->tsk_Current, 0);
1104 /* Enable Counter Interrupt */
1106 devpriv->iobase + APCI1564_COUNTER1 +
1109 } /* if (ui_C1 == 1) */
1112 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1113 if (devpriv->b_TimerSelectMode) {
1115 /* Disable Counter Interrupt */
1117 inl(devpriv->iobase + APCI1564_COUNTER2 +
1120 devpriv->iobase + APCI1564_COUNTER2 +
1123 /* Send a signal to from kernel to user space */
1124 send_sig(SIGIO, devpriv->tsk_Current, 0);
1126 /* Enable Counter Interrupt */
1128 devpriv->iobase + APCI1564_COUNTER2 +
1131 } /* if ((ui_C2 == 1) */
1134 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1135 if (devpriv->b_TimerSelectMode) {
1137 /* Disable Counter Interrupt */
1139 inl(devpriv->iobase + APCI1564_COUNTER3 +
1142 devpriv->iobase + APCI1564_COUNTER3 +
1145 /* Send a signal to from kernel to user space */
1146 send_sig(SIGIO, devpriv->tsk_Current, 0);
1148 /* Enable Counter Interrupt */
1150 devpriv->iobase + APCI1564_COUNTER3 +
1153 } /* if ((ui_C3 == 1) */
1156 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1157 if (devpriv->b_TimerSelectMode) {
1159 /* Disable Counter Interrupt */
1161 inl(devpriv->iobase + APCI1564_COUNTER4 +
1164 devpriv->iobase + APCI1564_COUNTER4 +
1167 /* Send a signal to from kernel to user space */
1168 send_sig(SIGIO, devpriv->tsk_Current, 0);
1170 /* Enable Counter Interrupt */
1172 devpriv->iobase + APCI1564_COUNTER4 +
1175 } /* if (ui_C4 == 1) */
1180 +----------------------------------------------------------------------------+
1181 | Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | |
1182 +----------------------------------------------------------------------------+
1183 | Task :resets all the registers |
1184 +----------------------------------------------------------------------------+
1185 | Input Parameters : struct comedi_device *dev
1186 +----------------------------------------------------------------------------+
1187 | Output Parameters : -- |
1188 +----------------------------------------------------------------------------+
1191 +----------------------------------------------------------------------------+
1194 static int i_APCI1564_Reset(struct comedi_device *dev)
1196 struct addi_private *devpriv = dev->private;
1198 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ); /* disable the interrupts */
1199 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); /* Reset the interrupt status register */
1200 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); /* Disable the and/or interrupt */
1201 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
1202 devpriv->b_DigitalOutputRegister = 0;
1204 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); /* Resets the output channels */
1205 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT); /* Disables the interrupt. */
1207 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
1208 APCI1564_TCW_RELOAD_VALUE);
1209 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER);
1210 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);
1212 outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG);
1213 outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG);
1214 outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG);
1215 outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG);