RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / comedi / drivers / addi-data / hwdrv_apci1564.c
blob4299ff5214dd11bcdb57db1fb95a35d7af4dff7d
1 /**
2 @verbatim
4 Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
6 ADDI-DATA GmbH
7 Dieselstrasse 3
8 D-77833 Ottersweier
9 Tel: +19(0)7223/9493-0
10 Fax: +49(0)7223/9493-92
11 http://www.addi-data-com
12 info@addi-data.com
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.
22 @endverbatim
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 +-----------------------------------------------------------------------+
39 | UPDATES |
40 +----------+-----------+------------------------------------------------+
41 | Date | Author | Description of updates |
42 +----------+-----------+------------------------------------------------+
43 | | | |
44 | | | |
45 | | | |
46 +----------+-----------+------------------------------------------------+
50 +----------------------------------------------------------------------------+
51 | Included files |
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 |
73 | |
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 |
80 | |
81 +----------------------------------------------------------------------------+
82 | Output Parameters : -- |
83 +----------------------------------------------------------------------------+
84 | Return Value : TRUE : No error occur |
85 | : FALSE : Error occur. Return the error |
86 | |
87 +----------------------------------------------------------------------------+
89 int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
90 struct 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;
99 outl(data[2],
100 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
101 APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
102 outl(data[3],
103 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
104 APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
105 if (data[1] == ADDIDATA_OR) {
106 outl(0x4,
107 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
108 APCI1564_DIGITAL_IP_IRQ);
109 } /* if (data[1] == ADDIDATA_OR) */
110 else {
111 outl(0x6,
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) */
116 else {
117 outl(0x0,
118 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
119 APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
120 outl(0x0,
121 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
122 APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
123 outl(0x0,
124 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
125 APCI1564_DIGITAL_IP_IRQ);
126 } /* else if (data[0] == ADDIDATA_ENABLE) */
128 return insn->n;
132 +----------------------------------------------------------------------------+
133 | Function Name : int i_APCI1564_Read1DigitalInput |
134 | (struct comedi_device *dev,struct comedi_subdevice *s, |
135 | struct 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 | unsigned int 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 struct comedi_insn *insn, unsigned int *data)
153 unsigned int ui_TmpValue = 0;
154 unsigned int ui_Channel;
156 ui_Channel = CR_CHAN(insn->chanspec);
157 if (ui_Channel <= 31) {
158 ui_TmpValue =
159 (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
161 * since only 1 channel reqd to bring it to last bit it is rotated 8
162 * +(chan - 1) times then ANDed with 1 for last bit.
164 *data = (ui_TmpValue >> ui_Channel) & 0x1;
165 } /* if (ui_Channel >= 0 && ui_Channel <=31) */
166 else {
167 comedi_error(dev, "Not a valid channel number !!! \n");
168 return -EINVAL; /* "sorry channel spec wrong " */
169 } /* else if (ui_Channel >= 0 && ui_Channel <=31) */
170 return insn->n;
174 +----------------------------------------------------------------------------+
175 | Function Name : int i_APCI1564_ReadMoreDigitalInput |
176 | (struct comedi_device *dev,struct comedi_subdevice *s, |
177 | struct comedi_insn *insn,unsigned int *data) |
178 +----------------------------------------------------------------------------+
179 | Task : Return the status of the Requested digital inputs |
180 +----------------------------------------------------------------------------+
181 | Input Parameters : struct comedi_device *dev : Driver handle |
182 | unsigned int ui_NoOfChannels : No Of Channels To be Read |
183 | unsigned int *data : Data Pointer to read status |
184 +----------------------------------------------------------------------------+
185 | Output Parameters : -- |
186 +----------------------------------------------------------------------------+
187 | Return Value : TRUE : No error occur |
188 | : FALSE : Error occur. Return the error |
190 +----------------------------------------------------------------------------+
192 int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
193 struct comedi_insn *insn, unsigned int *data)
195 unsigned int ui_PortValue = data[0];
196 unsigned int ui_Mask = 0;
197 unsigned int ui_NoOfChannels;
199 ui_NoOfChannels = CR_CHAN(insn->chanspec);
200 if (data[1] == 0) {
201 *data = (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
202 switch (ui_NoOfChannels) {
203 case 2:
204 ui_Mask = 3;
205 *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
206 break;
207 case 4:
208 ui_Mask = 15;
209 *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
210 break;
211 case 8:
212 ui_Mask = 255;
213 *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
214 break;
215 case 16:
216 ui_Mask = 65535;
217 *data = (*data >> (16 * ui_PortValue)) & ui_Mask;
218 break;
219 case 31:
220 break;
221 default:
222 comedi_error(dev, "Not a valid Channel number !!!\n");
223 return -EINVAL; /* "sorry channel spec wrong " */
224 break;
225 } /* switch (ui_NoOfChannels) */
226 } /* if (data[1]==0) */
227 else {
228 if (data[1] == 1) {
229 *data = ui_InterruptStatus_1564;
230 } /* if (data[1]==1) */
231 } /* else if (data[1]==0) */
232 return insn->n;
236 +----------------------------------------------------------------------------+
237 | Function Name : int i_APCI1564_ConfigDigitalOutput |
238 | (struct comedi_device *dev,struct comedi_subdevice *s, |
239 | struct comedi_insn *insn,unsigned int *data) |
240 +----------------------------------------------------------------------------+
241 | Task : Configures The Digital Output Subdevice. |
242 +----------------------------------------------------------------------------+
243 | Input Parameters : struct comedi_device *dev : Driver handle |
244 | unsigned int *data : Data Pointer contains |
245 | configuration parameters as below |
247 | data[1] : 1 Enable VCC Interrupt |
248 | 0 Disable VCC Interrupt |
249 | data[2] : 1 Enable CC Interrupt |
250 | 0 Disable CC Interrupt |
252 +----------------------------------------------------------------------------+
253 | Output Parameters : -- |
254 +----------------------------------------------------------------------------+
255 | Return Value : TRUE : No error occur |
256 | : FALSE : Error occur. Return the error |
258 +----------------------------------------------------------------------------+
260 int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
261 struct comedi_insn *insn, unsigned int *data)
263 unsigned int ul_Command = 0;
265 if ((data[0] != 0) && (data[0] != 1)) {
266 comedi_error(dev,
267 "Not a valid Data !!! ,Data should be 1 or 0\n");
268 return -EINVAL;
269 } /* if ((data[0]!=0) && (data[0]!=1)) */
270 if (data[0]) {
271 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
272 } /* if (data[0]) */
273 else {
274 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
275 } /* else if (data[0]) */
276 if (data[1] == ADDIDATA_ENABLE) {
277 ul_Command = ul_Command | 0x1;
278 } /* if (data[1] == ADDIDATA_ENABLE) */
279 else {
280 ul_Command = ul_Command & 0xFFFFFFFE;
281 } /* else if (data[1] == ADDIDATA_ENABLE) */
282 if (data[2] == ADDIDATA_ENABLE) {
283 ul_Command = ul_Command | 0x2;
284 } /* if (data[2] == ADDIDATA_ENABLE) */
285 else {
286 ul_Command = ul_Command & 0xFFFFFFFD;
287 } /* else if (data[2] == ADDIDATA_ENABLE) */
288 outl(ul_Command,
289 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
290 APCI1564_DIGITAL_OP_INTERRUPT);
291 ui_InterruptData =
292 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
293 APCI1564_DIGITAL_OP_INTERRUPT);
294 devpriv->tsk_Current = current;
295 return insn->n;
299 +----------------------------------------------------------------------------+
300 | Function Name : int i_APCI1564_WriteDigitalOutput |
301 | (struct comedi_device *dev,struct comedi_subdevice *s, |
302 | struct comedi_insn *insn,unsigned int *data) |
303 +----------------------------------------------------------------------------+
304 | Task : Writes port value To the selected port |
305 +----------------------------------------------------------------------------+
306 | Input Parameters : struct comedi_device *dev : Driver handle |
307 | unsigned int ui_NoOfChannels : No Of Channels To Write |
308 | unsigned int *data : Data Pointer to read status |
309 +----------------------------------------------------------------------------+
310 | Output Parameters : -- |
311 +----------------------------------------------------------------------------+
312 | Return Value : TRUE : No error occur |
313 | : FALSE : Error occur. Return the error |
315 +----------------------------------------------------------------------------+
317 int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
318 struct comedi_insn *insn, unsigned int *data)
320 unsigned int ui_Temp, ui_Temp1;
321 unsigned int ui_NoOfChannel;
323 ui_NoOfChannel = CR_CHAN(insn->chanspec);
324 if (devpriv->b_OutputMemoryStatus) {
325 ui_Temp =
326 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
327 APCI1564_DIGITAL_OP_RW);
328 } /* if (devpriv->b_OutputMemoryStatus ) */
329 else {
330 ui_Temp = 0;
331 } /* else if (devpriv->b_OutputMemoryStatus ) */
332 if (data[3] == 0) {
333 if (data[1] == 0) {
334 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
335 outl(data[0],
336 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
337 APCI1564_DIGITAL_OP_RW);
338 } /* if (data[1]==0) */
339 else {
340 if (data[1] == 1) {
341 switch (ui_NoOfChannel) {
342 case 2:
343 data[0] =
344 (data[0] << (2 *
345 data[2])) | ui_Temp;
346 break;
347 case 4:
348 data[0] =
349 (data[0] << (4 *
350 data[2])) | ui_Temp;
351 break;
352 case 8:
353 data[0] =
354 (data[0] << (8 *
355 data[2])) | ui_Temp;
356 break;
357 case 16:
358 data[0] =
359 (data[0] << (16 *
360 data[2])) | ui_Temp;
361 break;
362 case 31:
363 data[0] = data[0] | ui_Temp;
364 break;
365 default:
366 comedi_error(dev, " chan spec wrong");
367 return -EINVAL; /* "sorry channel spec wrong " */
368 } /* switch (ui_NoOfChannels) */
369 outl(data[0],
370 devpriv->i_IobaseAmcc +
371 APCI1564_DIGITAL_OP +
372 APCI1564_DIGITAL_OP_RW);
373 } /* if (data[1]==1) */
374 else {
375 printk("\nSpecified channel not supported\n");
376 } /* else if (data[1]==1) */
377 } /* else if (data[1]==0) */
378 } /* if(data[3]==0) */
379 else {
380 if (data[3] == 1) {
381 if (data[1] == 0) {
382 data[0] = ~data[0] & 0x1;
383 ui_Temp1 = 1;
384 ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
385 ui_Temp = ui_Temp | ui_Temp1;
386 data[0] =
387 (data[0] << ui_NoOfChannel) ^
388 0xffffffff;
389 data[0] = data[0] & ui_Temp;
390 outl(data[0],
391 devpriv->i_IobaseAmcc +
392 APCI1564_DIGITAL_OP +
393 APCI1564_DIGITAL_OP_RW);
394 } /* if (data[1]==0) */
395 else {
396 if (data[1] == 1) {
397 switch (ui_NoOfChannel) {
398 case 2:
399 data[0] = ~data[0] & 0x3;
400 ui_Temp1 = 3;
401 ui_Temp1 =
402 ui_Temp1 << 2 * data[2];
403 ui_Temp = ui_Temp | ui_Temp1;
404 data[0] =
405 ((data[0] << (2 *
406 data
407 [2])) ^
408 0xffffffff) & ui_Temp;
409 break;
410 case 4:
411 data[0] = ~data[0] & 0xf;
412 ui_Temp1 = 15;
413 ui_Temp1 =
414 ui_Temp1 << 4 * data[2];
415 ui_Temp = ui_Temp | ui_Temp1;
416 data[0] =
417 ((data[0] << (4 *
418 data
419 [2])) ^
420 0xffffffff) & ui_Temp;
421 break;
422 case 8:
423 data[0] = ~data[0] & 0xff;
424 ui_Temp1 = 255;
425 ui_Temp1 =
426 ui_Temp1 << 8 * data[2];
427 ui_Temp = ui_Temp | ui_Temp1;
428 data[0] =
429 ((data[0] << (8 *
430 data
431 [2])) ^
432 0xffffffff) & ui_Temp;
433 break;
434 case 16:
435 data[0] = ~data[0] & 0xffff;
436 ui_Temp1 = 65535;
437 ui_Temp1 =
438 ui_Temp1 << 16 *
439 data[2];
440 ui_Temp = ui_Temp | ui_Temp1;
441 data[0] =
442 ((data[0] << (16 *
443 data
444 [2])) ^
445 0xffffffff) & ui_Temp;
446 break;
447 case 31:
448 break;
449 default:
450 comedi_error(dev,
451 " chan spec wrong");
452 return -EINVAL; /* "sorry channel spec wrong " */
453 } /* switch(ui_NoOfChannels) */
454 outl(data[0],
455 devpriv->i_IobaseAmcc +
456 APCI1564_DIGITAL_OP +
457 APCI1564_DIGITAL_OP_RW);
458 } /* if (data[1]==1) */
459 else {
460 printk("\nSpecified channel not supported\n");
461 } /* else if (data[1]==1) */
462 } /* else if (data[1]==0) */
463 } /* if (data[3]==1); */
464 else {
465 printk("\nSpecified functionality does not exist\n");
466 return -EINVAL;
467 } /* else if (data[3]==1) */
468 } /* else if (data[3]==0) */
469 return insn->n;
473 +----------------------------------------------------------------------------+
474 | Function Name : int i_APCI1564_ReadDigitalOutput |
475 | (struct comedi_device *dev,struct comedi_subdevice *s, |
476 | struct comedi_insn *insn,unsigned int *data) |
477 +----------------------------------------------------------------------------+
478 | Task : Read value of the selected channel or port |
479 +----------------------------------------------------------------------------+
480 | Input Parameters : struct comedi_device *dev : Driver handle |
481 | unsigned int ui_NoOfChannels : No Of Channels To read |
482 | unsigned int *data : Data Pointer to read status |
483 +----------------------------------------------------------------------------+
484 | Output Parameters : -- |
485 +----------------------------------------------------------------------------+
486 | Return Value : TRUE : No error occur |
487 | : FALSE : Error occur. Return the error |
489 +----------------------------------------------------------------------------+
491 int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
492 struct comedi_insn *insn, unsigned int *data)
494 unsigned int ui_Temp;
495 unsigned int ui_NoOfChannel;
497 ui_NoOfChannel = CR_CHAN(insn->chanspec);
498 ui_Temp = data[0];
499 *data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
500 APCI1564_DIGITAL_OP_RW);
501 if (ui_Temp == 0) {
502 *data = (*data >> ui_NoOfChannel) & 0x1;
503 } /* if (ui_Temp==0) */
504 else {
505 if (ui_Temp == 1) {
506 switch (ui_NoOfChannel) {
507 case 2:
508 *data = (*data >> (2 * data[1])) & 3;
509 break;
511 case 4:
512 *data = (*data >> (4 * data[1])) & 15;
513 break;
515 case 8:
516 *data = (*data >> (8 * data[1])) & 255;
517 break;
519 case 16:
520 *data = (*data >> (16 * data[1])) & 65535;
521 break;
523 case 31:
524 break;
526 default:
527 comedi_error(dev, " chan spec wrong");
528 return -EINVAL; /* "sorry channel spec wrong " */
529 break;
530 } /* switch(ui_NoOfChannels) */
531 } /* if (ui_Temp==1) */
532 else {
533 printk("\nSpecified channel not supported \n");
534 } /* else if (ui_Temp==1) */
535 } /* else if (ui_Temp==0) */
536 return insn->n;
540 +----------------------------------------------------------------------------+
541 | Function Name : int i_APCI1564_ConfigTimerCounterWatchdog |
542 | (struct comedi_device *dev,struct comedi_subdevice *s, |
543 | struct comedi_insn *insn,unsigned int *data) |
544 +----------------------------------------------------------------------------+
545 | Task : Configures The Timer , Counter or Watchdog |
546 +----------------------------------------------------------------------------+
547 | Input Parameters : struct comedi_device *dev : Driver handle |
548 | unsigned int *data : Data Pointer contains |
549 | configuration parameters as below |
551 | data[0] : 0 Configure As Timer |
552 | 1 Configure As Counter |
553 | 2 Configure As Watchdog |
554 | data[1] : 1 Enable Interrupt |
555 | 0 Disable Interrupt |
556 | data[2] : Time Unit |
557 | data[3] : Reload Value |
558 | data[4] : Timer Mode |
559 | data[5] : Timer Counter Watchdog Number|
560 data[6] : Counter Direction
561 +----------------------------------------------------------------------------+
562 | Output Parameters : -- |
563 +----------------------------------------------------------------------------+
564 | Return Value : TRUE : No error occur |
565 | : FALSE : Error occur. Return the error |
567 +----------------------------------------------------------------------------+
569 int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
570 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
572 unsigned int ul_Command1 = 0;
573 devpriv->tsk_Current = current;
574 if (data[0] == ADDIDATA_WATCHDOG) {
575 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
577 /* Disable the watchdog */
578 outl(0x0,
579 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
580 APCI1564_TCW_PROG);
581 /* Loading the Reload value */
582 outl(data[3],
583 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
584 APCI1564_TCW_RELOAD_VALUE);
585 } /* if (data[0]==ADDIDATA_WATCHDOG) */
586 else if (data[0] == ADDIDATA_TIMER) {
587 /* First Stop The Timer */
588 ul_Command1 =
589 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
590 APCI1564_TCW_PROG);
591 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
592 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Stop The Timer */
594 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
595 if (data[1] == 1) {
596 outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
597 outl(0x0,
598 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
599 APCI1564_DIGITAL_IP_IRQ);
600 outl(0x0,
601 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
602 APCI1564_DIGITAL_OP_IRQ);
603 outl(0x0,
604 devpriv->i_IobaseAmcc +
605 APCI1564_DIGITAL_OP_WATCHDOG +
606 APCI1564_TCW_IRQ);
607 outl(0x0,
608 devpriv->iobase + APCI1564_COUNTER1 +
609 APCI1564_TCW_IRQ);
610 outl(0x0,
611 devpriv->iobase + APCI1564_COUNTER2 +
612 APCI1564_TCW_IRQ);
613 outl(0x0,
614 devpriv->iobase + APCI1564_COUNTER3 +
615 APCI1564_TCW_IRQ);
616 outl(0x0,
617 devpriv->iobase + APCI1564_COUNTER4 +
618 APCI1564_TCW_IRQ);
619 } /* if (data[1]==1) */
620 else {
621 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* disable Timer interrupt */
622 } /* else if (data[1]==1) */
624 /* Loading Timebase */
626 outl(data[2],
627 devpriv->i_IobaseAmcc + APCI1564_TIMER +
628 APCI1564_TCW_TIMEBASE);
630 /* Loading the Reload value */
631 outl(data[3],
632 devpriv->i_IobaseAmcc + APCI1564_TIMER +
633 APCI1564_TCW_RELOAD_VALUE);
635 ul_Command1 =
636 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
637 APCI1564_TCW_PROG);
638 ul_Command1 =
639 (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
640 outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* mode 2 */
641 } /* else if (data[0]==ADDIDATA_TIMER) */
642 else if (data[0] == ADDIDATA_COUNTER) {
643 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
644 devpriv->b_ModeSelectRegister = data[5];
646 /* First Stop The Counter */
647 ul_Command1 =
648 inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
649 APCI1564_TCW_PROG);
650 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
651 outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); /* Stop The Timer */
653 /************************/
654 /* Set the reload value */
655 /************************/
656 outl(data[3],
657 devpriv->iobase + ((data[5] - 1) * 0x20) +
658 APCI1564_TCW_RELOAD_VALUE);
660 /******************************/
661 /* Set the mode : */
662 /* - Disable the hardware */
663 /* - Disable the counter mode */
664 /* - Disable the warning */
665 /* - Disable the reset */
666 /* - Disable the timer mode */
667 /* - Enable the counter mode */
668 /******************************/
669 ul_Command1 =
670 (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
671 (unsigned int) ((unsigned int) data[4] << 16UL);
672 outl(ul_Command1,
673 devpriv->iobase + ((data[5] - 1) * 0x20) +
674 APCI1564_TCW_PROG);
676 /* Enable or Disable Interrupt */
677 ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
678 outl(ul_Command1,
679 devpriv->iobase + ((data[5] - 1) * 0x20) +
680 APCI1564_TCW_PROG);
682 /*****************************/
683 /* Set the Up/Down selection */
684 /*****************************/
685 ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
686 outl(ul_Command1,
687 devpriv->iobase + ((data[5] - 1) * 0x20) +
688 APCI1564_TCW_PROG);
689 } /* else if (data[0]==ADDIDATA_COUNTER) */
690 else {
691 printk(" Invalid subdevice.");
692 } /* else if (data[0]==ADDIDATA_WATCHDOG) */
694 return insn->n;
698 +----------------------------------------------------------------------------+
699 | Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog |
700 | (struct comedi_device *dev,struct comedi_subdevice *s, |
701 | struct comedi_insn *insn,unsigned int *data) |
702 +----------------------------------------------------------------------------+
703 | Task : Start / Stop The Selected Timer , Counter or Watchdog |
704 +----------------------------------------------------------------------------+
705 | Input Parameters : struct comedi_device *dev : Driver handle |
706 | unsigned int *data : Data Pointer contains |
707 | configuration parameters as below |
709 | data[0] : 0 Timer |
710 | 1 Counter |
711 | 2 Watchdog | | data[1] : 1 Start |
712 | 0 Stop |
713 | 2 Trigger |
714 | Clear (Only Counter) |
715 +----------------------------------------------------------------------------+
716 | Output Parameters : -- |
717 +----------------------------------------------------------------------------+
718 | Return Value : TRUE : No error occur |
719 | : FALSE : Error occur. Return the error |
721 +----------------------------------------------------------------------------+
723 int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
724 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
726 unsigned int ul_Command1 = 0;
727 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
728 switch (data[1]) {
729 case 0: /* stop the watchdog */
730 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG); /* disable the watchdog */
731 break;
732 case 1: /* start the watchdog */
733 outl(0x0001,
734 devpriv->i_IobaseAmcc +
735 APCI1564_DIGITAL_OP_WATCHDOG +
736 APCI1564_TCW_PROG);
737 break;
738 case 2: /* Software trigger */
739 outl(0x0201,
740 devpriv->i_IobaseAmcc +
741 APCI1564_DIGITAL_OP_WATCHDOG +
742 APCI1564_TCW_PROG);
743 break;
744 default:
745 printk("\nSpecified functionality does not exist\n");
746 return -EINVAL;
747 } /* switch (data[1]) */
748 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
749 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
750 if (data[1] == 1) {
751 ul_Command1 =
752 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
753 APCI1564_TCW_PROG);
754 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
756 /* Enable the Timer */
757 outl(ul_Command1,
758 devpriv->i_IobaseAmcc + APCI1564_TIMER +
759 APCI1564_TCW_PROG);
760 } /* if (data[1]==1) */
761 else if (data[1] == 0) {
762 /* Stop The Timer */
764 ul_Command1 =
765 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
766 APCI1564_TCW_PROG);
767 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
768 outl(ul_Command1,
769 devpriv->i_IobaseAmcc + APCI1564_TIMER +
770 APCI1564_TCW_PROG);
771 } /* else if(data[1]==0) */
772 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
773 if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
774 ul_Command1 =
775 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
776 1) * 0x20) + APCI1564_TCW_PROG);
777 if (data[1] == 1) {
778 /* Start the Counter subdevice */
779 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
780 } /* if (data[1] == 1) */
781 else if (data[1] == 0) {
782 /* Stops the Counter subdevice */
783 ul_Command1 = 0;
785 } /* else if (data[1] == 0) */
786 else if (data[1] == 2) {
787 /* Clears the Counter subdevice */
788 ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
789 } /* else if (data[1] == 3) */
790 outl(ul_Command1,
791 devpriv->iobase + ((devpriv->b_ModeSelectRegister -
792 1) * 0x20) + APCI1564_TCW_PROG);
793 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
794 return insn->n;
798 +----------------------------------------------------------------------------+
799 | Function Name : int i_APCI1564_ReadTimerCounterWatchdog |
800 | (struct comedi_device *dev,struct comedi_subdevice *s, |
801 | struct comedi_insn *insn,unsigned int *data) |
802 +----------------------------------------------------------------------------+
803 | Task : Read The Selected Timer , Counter or Watchdog |
804 +----------------------------------------------------------------------------+
805 | Input Parameters : struct comedi_device *dev : Driver handle |
806 | unsigned int *data : Data Pointer contains |
807 | configuration parameters as below |
810 +----------------------------------------------------------------------------+
811 | Output Parameters : -- |
812 +----------------------------------------------------------------------------+
813 | Return Value : TRUE : No error occur |
814 | : FALSE : Error occur. Return the error |
816 +----------------------------------------------------------------------------+
818 int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
819 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
821 unsigned int ul_Command1 = 0;
823 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
824 /* Stores the status of the Watchdog */
825 data[0] =
826 inl(devpriv->i_IobaseAmcc +
827 APCI1564_DIGITAL_OP_WATCHDOG +
828 APCI1564_TCW_TRIG_STATUS) & 0x1;
829 data[1] =
830 inl(devpriv->i_IobaseAmcc +
831 APCI1564_DIGITAL_OP_WATCHDOG);
832 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) */
833 else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
834 /* Stores the status of the Timer */
835 data[0] =
836 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
837 APCI1564_TCW_TRIG_STATUS) & 0x1;
839 /* Stores the Actual value of the Timer */
840 data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
841 } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
842 else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
843 /* Read the Counter Actual Value. */
844 data[0] =
845 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
846 1) * 0x20) +
847 APCI1564_TCW_SYNC_ENABLEDISABLE);
848 ul_Command1 =
849 inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
850 1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
852 /***********************************/
853 /* Get the software trigger status */
854 /***********************************/
855 data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
857 /***********************************/
858 /* Get the hardware trigger status */
859 /***********************************/
860 data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
862 /*********************************/
863 /* Get the software clear status */
864 /*********************************/
865 data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
867 /***************************/
868 /* Get the overflow status */
869 /***************************/
870 data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
871 } /* else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) */
872 else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
873 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
874 && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
875 printk("\n Invalid Subdevice !!!\n");
876 } /* else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) */
877 return insn->n;
881 +----------------------------------------------------------------------------+
882 | Function Name : int i_APCI1564_ReadInterruptStatus |
883 | (struct comedi_device *dev,struct comedi_subdevice *s, |
884 | struct comedi_insn *insn,unsigned int *data) |
885 +----------------------------------------------------------------------------+
886 | Task :Reads the interrupt status register |
887 +----------------------------------------------------------------------------+
888 | Input Parameters : |
889 +----------------------------------------------------------------------------+
890 | Output Parameters : -- |
891 +----------------------------------------------------------------------------+
892 | Return Value : |
894 +----------------------------------------------------------------------------+
897 int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
898 struct comedi_insn *insn, unsigned int *data)
900 *data = ui_Type;
901 return insn->n;
905 +----------------------------------------------------------------------------+
906 | Function Name : static void v_APCI1564_Interrupt |
907 | (int irq , void *d) |
908 +----------------------------------------------------------------------------+
909 | Task : Interrupt handler for the interruptible digital inputs |
910 +----------------------------------------------------------------------------+
911 | Input Parameters : int irq : irq number |
912 | void *d : void pointer |
913 +----------------------------------------------------------------------------+
914 | Output Parameters : -- |
915 +----------------------------------------------------------------------------+
916 | Return Value : TRUE : No error occur |
917 | : FALSE : Error occur. Return the error |
919 +----------------------------------------------------------------------------+
921 static void v_APCI1564_Interrupt(int irq, void *d)
923 struct comedi_device *dev = d;
924 unsigned int ui_DO, ui_DI;
925 unsigned int ui_Timer;
926 unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
927 unsigned int ul_Command2 = 0;
928 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
929 APCI1564_DIGITAL_IP_IRQ) & 0x01;
930 ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
931 APCI1564_DIGITAL_OP_IRQ) & 0x01;
932 ui_Timer =
933 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
934 APCI1564_TCW_IRQ) & 0x01;
935 ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 +
936 APCI1564_TCW_IRQ) & 0x1;
937 ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 +
938 APCI1564_TCW_IRQ) & 0x1;
939 ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 +
940 APCI1564_TCW_IRQ) & 0x1;
941 ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 +
942 APCI1564_TCW_IRQ) & 0x1;
943 if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
944 && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
945 printk("\nInterrupt from unknown source\n");
946 } /* if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) */
948 if (ui_DI == 1) {
949 ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
950 APCI1564_DIGITAL_IP_IRQ);
951 outl(0x0,
952 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
953 APCI1564_DIGITAL_IP_IRQ);
954 ui_InterruptStatus_1564 =
955 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
956 APCI1564_DIGITAL_IP_INTERRUPT_STATUS);
957 ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
958 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
959 outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); /* enable the interrupt */
960 return;
963 if (ui_DO == 1) {
964 /* Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
965 ui_Type =
966 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
967 APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
968 /* Disable the Interrupt */
969 outl(0x0,
970 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
971 APCI1564_DIGITAL_OP_INTERRUPT);
973 /* Sends signal to user space */
974 send_sig(SIGIO, devpriv->tsk_Current, 0);
976 } /* if (ui_DO) */
978 if (ui_Timer == 1) {
979 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
980 if (devpriv->b_TimerSelectMode) {
982 /* Disable Timer Interrupt */
983 ul_Command2 =
984 inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
985 APCI1564_TCW_PROG);
986 outl(0x0,
987 devpriv->i_IobaseAmcc + APCI1564_TIMER +
988 APCI1564_TCW_PROG);
990 /* Send a signal to from kernel to user space */
991 send_sig(SIGIO, devpriv->tsk_Current, 0);
993 /* Enable Timer Interrupt */
995 outl(ul_Command2,
996 devpriv->i_IobaseAmcc + APCI1564_TIMER +
997 APCI1564_TCW_PROG);
999 }/* if (ui_Timer == 1) */
1002 if (ui_C1 == 1) {
1003 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1004 if (devpriv->b_TimerSelectMode) {
1006 /* Disable Counter Interrupt */
1007 ul_Command2 =
1008 inl(devpriv->iobase + APCI1564_COUNTER1 +
1009 APCI1564_TCW_PROG);
1010 outl(0x0,
1011 devpriv->iobase + APCI1564_COUNTER1 +
1012 APCI1564_TCW_PROG);
1014 /* Send a signal to from kernel to user space */
1015 send_sig(SIGIO, devpriv->tsk_Current, 0);
1017 /* Enable Counter Interrupt */
1018 outl(ul_Command2,
1019 devpriv->iobase + APCI1564_COUNTER1 +
1020 APCI1564_TCW_PROG);
1022 } /* if (ui_C1 == 1) */
1024 if (ui_C2 == 1) {
1025 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1026 if (devpriv->b_TimerSelectMode) {
1028 /* Disable Counter Interrupt */
1029 ul_Command2 =
1030 inl(devpriv->iobase + APCI1564_COUNTER2 +
1031 APCI1564_TCW_PROG);
1032 outl(0x0,
1033 devpriv->iobase + APCI1564_COUNTER2 +
1034 APCI1564_TCW_PROG);
1036 /* Send a signal to from kernel to user space */
1037 send_sig(SIGIO, devpriv->tsk_Current, 0);
1039 /* Enable Counter Interrupt */
1040 outl(ul_Command2,
1041 devpriv->iobase + APCI1564_COUNTER2 +
1042 APCI1564_TCW_PROG);
1044 } /* if ((ui_C2 == 1) */
1046 if (ui_C3 == 1) {
1047 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1048 if (devpriv->b_TimerSelectMode) {
1050 /* Disable Counter Interrupt */
1051 ul_Command2 =
1052 inl(devpriv->iobase + APCI1564_COUNTER3 +
1053 APCI1564_TCW_PROG);
1054 outl(0x0,
1055 devpriv->iobase + APCI1564_COUNTER3 +
1056 APCI1564_TCW_PROG);
1058 /* Send a signal to from kernel to user space */
1059 send_sig(SIGIO, devpriv->tsk_Current, 0);
1061 /* Enable Counter Interrupt */
1062 outl(ul_Command2,
1063 devpriv->iobase + APCI1564_COUNTER3 +
1064 APCI1564_TCW_PROG);
1066 } /* if ((ui_C3 == 1) */
1068 if (ui_C4 == 1) {
1069 devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1070 if (devpriv->b_TimerSelectMode) {
1072 /* Disable Counter Interrupt */
1073 ul_Command2 =
1074 inl(devpriv->iobase + APCI1564_COUNTER4 +
1075 APCI1564_TCW_PROG);
1076 outl(0x0,
1077 devpriv->iobase + APCI1564_COUNTER4 +
1078 APCI1564_TCW_PROG);
1080 /* Send a signal to from kernel to user space */
1081 send_sig(SIGIO, devpriv->tsk_Current, 0);
1083 /* Enable Counter Interrupt */
1084 outl(ul_Command2,
1085 devpriv->iobase + APCI1564_COUNTER4 +
1086 APCI1564_TCW_PROG);
1088 } /* if (ui_C4 == 1) */
1089 return;
1093 +----------------------------------------------------------------------------+
1094 | Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | |
1095 +----------------------------------------------------------------------------+
1096 | Task :resets all the registers |
1097 +----------------------------------------------------------------------------+
1098 | Input Parameters : struct comedi_device *dev
1099 +----------------------------------------------------------------------------+
1100 | Output Parameters : -- |
1101 +----------------------------------------------------------------------------+
1102 | Return Value : |
1104 +----------------------------------------------------------------------------+
1107 int i_APCI1564_Reset(struct comedi_device *dev)
1109 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ); /* disable the interrupts */
1110 inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); /* Reset the interrupt status register */
1111 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); /* Disable the and/or interrupt */
1112 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
1113 devpriv->b_DigitalOutputRegister = 0;
1114 ui_Type = 0;
1115 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); /* Resets the output channels */
1116 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT); /* Disables the interrupt. */
1117 outl(0x0,
1118 devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
1119 APCI1564_TCW_RELOAD_VALUE);
1120 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER);
1121 outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);
1123 outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG);
1124 outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG);
1125 outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG);
1126 outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG);
1127 return 0;