Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwdrv_apci1564.c
Go to the documentation of this file.
1 
24 /*
25 
26  +-----------------------------------------------------------------------+
27  | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
28  +-----------------------------------------------------------------------+
29  | Tel : +49 (0) 7223/9493-0 | email : [email protected] |
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  +-----------------------------------------------------------------------+
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 static unsigned int ui_InterruptStatus_1564 = 0;
60 static unsigned int ui_InterruptData, ui_Type;
61 
62 /*
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 +----------------------------------------------------------------------------+
88 */
90  struct comedi_insn *insn, unsigned int *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 +
102  outl(data[3],
103  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
105  if (data[1] == ADDIDATA_OR) {
106  outl(0x4,
107  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
109  } /* if (data[1] == ADDIDATA_OR) */
110  else {
111  outl(0x6,
112  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
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 +
120  outl(0x0,
121  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
123  outl(0x0,
124  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
126  } /* else if (data[0] == ADDIDATA_ENABLE) */
127 
128  return insn->n;
129 }
130 
131 /*
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 |
147 | |
148 +----------------------------------------------------------------------------+
149 */
151  struct comedi_insn *insn, unsigned int *data)
152 {
153  unsigned int ui_TmpValue = 0;
154  unsigned int ui_Channel;
155 
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);
160 /*
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.
163 */
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;
171 }
172 
173 /*
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 |
189 | |
190 +----------------------------------------------------------------------------+
191 */
193  struct comedi_insn *insn, unsigned int *data)
194 {
195  unsigned int ui_PortValue = data[0];
196  unsigned int ui_Mask = 0;
197  unsigned int ui_NoOfChannels;
198 
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;
233 }
234 
235 /*
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 |
246 | |
247 | data[1] : 1 Enable VCC Interrupt |
248 | 0 Disable VCC Interrupt |
249 | data[2] : 1 Enable CC Interrupt |
250 | 0 Disable CC Interrupt |
251 | |
252 +----------------------------------------------------------------------------+
253 | Output Parameters : -- |
254 +----------------------------------------------------------------------------+
255 | Return Value : TRUE : No error occur |
256 | : FALSE : Error occur. Return the error |
257 | |
258 +----------------------------------------------------------------------------+
259 */
261  struct comedi_insn *insn, unsigned int *data)
262 {
263  unsigned int ul_Command = 0;
264 
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 +
291  ui_InterruptData =
292  inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
294  devpriv->tsk_Current = current;
295  return insn->n;
296 }
297 
298 /*
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 |
314 | |
315 +----------------------------------------------------------------------------+
316 */
318  struct comedi_insn *insn, unsigned int *data)
319 {
320  unsigned int ui_Temp, ui_Temp1;
321  unsigned int ui_NoOfChannel;
322 
323  ui_NoOfChannel = CR_CHAN(insn->chanspec);
324  if (devpriv->b_OutputMemoryStatus) {
325  ui_Temp =
326  inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
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 +
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 +
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 +
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 +
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;
470 }
471 
472 /*
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 |
488 | |
489 +----------------------------------------------------------------------------+
490 */
492  struct comedi_insn *insn, unsigned int *data)
493 {
494  unsigned int ui_Temp;
495  unsigned int ui_NoOfChannel;
496 
497  ui_NoOfChannel = CR_CHAN(insn->chanspec);
498  ui_Temp = data[0];
499  *data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
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;
510 
511  case 4:
512  *data = (*data >> (4 * data[1])) & 15;
513  break;
514 
515  case 8:
516  *data = (*data >> (8 * data[1])) & 255;
517  break;
518 
519  case 16:
520  *data = (*data >> (16 * data[1])) & 65535;
521  break;
522 
523  case 31:
524  break;
525 
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;
537 }
538 
539 /*
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 |
550 | |
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 |
566 | |
567 +----------------------------------------------------------------------------+
568 */
570  struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
571 {
572  unsigned int ul_Command1 = 0;
573  devpriv->tsk_Current = current;
574  if (data[0] == ADDIDATA_WATCHDOG) {
575  devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
576 
577  /* Disable the watchdog */
578  outl(0x0,
579  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
581  /* Loading the Reload value */
582  outl(data[3],
583  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
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 +
591  ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
592  outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); /* Stop The Timer */
593 
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 +
600  outl(0x0,
601  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
603  outl(0x0,
604  devpriv->i_IobaseAmcc +
607  outl(0x0,
608  devpriv->iobase + APCI1564_COUNTER1 +
610  outl(0x0,
611  devpriv->iobase + APCI1564_COUNTER2 +
613  outl(0x0,
614  devpriv->iobase + APCI1564_COUNTER3 +
616  outl(0x0,
617  devpriv->iobase + APCI1564_COUNTER4 +
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) */
623 
624  /* Loading Timebase */
625 
626  outl(data[2],
627  devpriv->i_IobaseAmcc + APCI1564_TIMER +
629 
630  /* Loading the Reload value */
631  outl(data[3],
632  devpriv->i_IobaseAmcc + APCI1564_TIMER +
634 
635  ul_Command1 =
636  inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
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];
645 
646  /* First Stop The Counter */
647  ul_Command1 =
648  inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
650  ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
651  outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); /* Stop The Timer */
652 
653  /************************/
654  /* Set the reload value */
655  /************************/
656  outl(data[3],
657  devpriv->iobase + ((data[5] - 1) * 0x20) +
659 
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) +
675 
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) +
681 
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) +
689  } /* else if (data[0]==ADDIDATA_COUNTER) */
690  else {
691  printk(" Invalid subdevice.");
692  } /* else if (data[0]==ADDIDATA_WATCHDOG) */
693 
694  return insn->n;
695 }
696 
697 /*
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 |
708 | |
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 |
720 | |
721 +----------------------------------------------------------------------------+
722 */
724  struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
725 {
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 +
737  break;
738  case 2: /* Software trigger */
739  outl(0x0201,
740  devpriv->i_IobaseAmcc +
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 +
754  ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
755 
756  /* Enable the Timer */
757  outl(ul_Command1,
758  devpriv->i_IobaseAmcc + APCI1564_TIMER +
760  } /* if (data[1]==1) */
761  else if (data[1] == 0) {
762  /* Stop The Timer */
763 
764  ul_Command1 =
765  inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
767  ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
768  outl(ul_Command1,
769  devpriv->i_IobaseAmcc + APCI1564_TIMER +
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;
784 
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;
795 }
796 
797 /*
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 |
808 | |
809 
810 +----------------------------------------------------------------------------+
811 | Output Parameters : -- |
812 +----------------------------------------------------------------------------+
813 | Return Value : TRUE : No error occur |
814 | : FALSE : Error occur. Return the error |
815 | |
816 +----------------------------------------------------------------------------+
817 */
819  struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
820 {
821  unsigned int ul_Command1 = 0;
822 
823  if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
824  /* Stores the status of the Watchdog */
825  data[0] =
826  inl(devpriv->i_IobaseAmcc +
829  data[1] =
830  inl(devpriv->i_IobaseAmcc +
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 +
838 
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) +
848  ul_Command1 =
849  inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
850  1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
851 
852  /***********************************/
853  /* Get the software trigger status */
854  /***********************************/
855  data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
856 
857  /***********************************/
858  /* Get the hardware trigger status */
859  /***********************************/
860  data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
861 
862  /*********************************/
863  /* Get the software clear status */
864  /*********************************/
865  data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
866 
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;
878 }
879 
880 /*
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 : |
893 | |
894 +----------------------------------------------------------------------------+
895 */
896 
898  struct comedi_insn *insn, unsigned int *data)
899 {
900  *data = ui_Type;
901  return insn->n;
902 }
903 
904 /*
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 |
918 | |
919 +----------------------------------------------------------------------------+
920 */
921 static void v_APCI1564_Interrupt(int irq, void *d)
922 {
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) */
947 
948  if (ui_DI == 1) {
949  ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
951  outl(0x0,
952  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
954  ui_InterruptStatus_1564 =
955  inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
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;
961  }
962 
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 +
968  /* Disable the Interrupt */
969  outl(0x0,
970  devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
972 
973  /* Sends signal to user space */
974  send_sig(SIGIO, devpriv->tsk_Current, 0);
975 
976  } /* if (ui_DO) */
977 
978  if (ui_Timer == 1) {
979  devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
980  if (devpriv->b_TimerSelectMode) {
981 
982  /* Disable Timer Interrupt */
983  ul_Command2 =
984  inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
986  outl(0x0,
987  devpriv->i_IobaseAmcc + APCI1564_TIMER +
989 
990  /* Send a signal to from kernel to user space */
991  send_sig(SIGIO, devpriv->tsk_Current, 0);
992 
993  /* Enable Timer Interrupt */
994 
995  outl(ul_Command2,
996  devpriv->i_IobaseAmcc + APCI1564_TIMER +
998  }
999  }/* if (ui_Timer == 1) */
1000 
1001 
1002  if (ui_C1 == 1) {
1003  devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1004  if (devpriv->b_TimerSelectMode) {
1005 
1006  /* Disable Counter Interrupt */
1007  ul_Command2 =
1008  inl(devpriv->iobase + APCI1564_COUNTER1 +
1010  outl(0x0,
1011  devpriv->iobase + APCI1564_COUNTER1 +
1013 
1014  /* Send a signal to from kernel to user space */
1015  send_sig(SIGIO, devpriv->tsk_Current, 0);
1016 
1017  /* Enable Counter Interrupt */
1018  outl(ul_Command2,
1019  devpriv->iobase + APCI1564_COUNTER1 +
1021  }
1022  } /* if (ui_C1 == 1) */
1023 
1024  if (ui_C2 == 1) {
1025  devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1026  if (devpriv->b_TimerSelectMode) {
1027 
1028  /* Disable Counter Interrupt */
1029  ul_Command2 =
1030  inl(devpriv->iobase + APCI1564_COUNTER2 +
1032  outl(0x0,
1033  devpriv->iobase + APCI1564_COUNTER2 +
1035 
1036  /* Send a signal to from kernel to user space */
1037  send_sig(SIGIO, devpriv->tsk_Current, 0);
1038 
1039  /* Enable Counter Interrupt */
1040  outl(ul_Command2,
1041  devpriv->iobase + APCI1564_COUNTER2 +
1043  }
1044  } /* if ((ui_C2 == 1) */
1045 
1046  if (ui_C3 == 1) {
1047  devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1048  if (devpriv->b_TimerSelectMode) {
1049 
1050  /* Disable Counter Interrupt */
1051  ul_Command2 =
1052  inl(devpriv->iobase + APCI1564_COUNTER3 +
1054  outl(0x0,
1055  devpriv->iobase + APCI1564_COUNTER3 +
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_COUNTER3 +
1065  }
1066  } /* if ((ui_C3 == 1) */
1067 
1068  if (ui_C4 == 1) {
1069  devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
1070  if (devpriv->b_TimerSelectMode) {
1071 
1072  /* Disable Counter Interrupt */
1073  ul_Command2 =
1074  inl(devpriv->iobase + APCI1564_COUNTER4 +
1076  outl(0x0,
1077  devpriv->iobase + APCI1564_COUNTER4 +
1079 
1080  /* Send a signal to from kernel to user space */
1081  send_sig(SIGIO, devpriv->tsk_Current, 0);
1082 
1083  /* Enable Counter Interrupt */
1084  outl(ul_Command2,
1085  devpriv->iobase + APCI1564_COUNTER4 +
1087  }
1088  } /* if (ui_C4 == 1) */
1089  return;
1090 }
1091 
1092 /*
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 : |
1103 | |
1104 +----------------------------------------------------------------------------+
1105 */
1106 
1108 {
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 +
1120  outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER);
1121  outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);
1122 
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;
1128 }