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