Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwdrv_apci3xxx.c
Go to the documentation of this file.
1 
24 /*
25  +-----------------------------------------------------------------------+
26  | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
27  +-----------------------------------------------------------------------+
28  | Tel : +49 (0) 7223/9493-0 | email : [email protected] |
29  | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
30  +-----------------------------------------------------------------------+
31  | Project : APCI-3XXX | Compiler : GCC |
32  | Module name : hwdrv_apci3xxx.c| Version : 2.96 |
33  +-------------------------------+---------------------------------------+
34  | Project manager: S. Weber | Date : 15/09/2005 |
35  +-----------------------------------------------------------------------+
36  | Description :APCI3XXX Module. Hardware abstraction Layer for APCI3XXX|
37  +-----------------------------------------------------------------------+
38  | UPDATE'S |
39  +-----------------------------------------------------------------------+
40  | Date | Author | Description of updates |
41  +----------+-----------+------------------------------------------------+
42  | | | |
43  | | | |
44  +----------+-----------+------------------------------------------------+
45 */
46 
47 #include "hwdrv_apci3xxx.h"
48 
49 /*
50 +----------------------------------------------------------------------------+
51 | ANALOG INPUT FUNCTIONS |
52 +----------------------------------------------------------------------------+
53 */
54 
55 /*
56 +----------------------------------------------------------------------------+
57 | Function Name : int i_APCI3XXX_TestConversionStarted |
58 | (struct comedi_device *dev) |
59 +----------------------------------------------------------------------------+
60 | Task Test if any conversion started |
61 +----------------------------------------------------------------------------+
62 | Input Parameters : - |
63 +----------------------------------------------------------------------------+
64 | Output Parameters : - |
65 +----------------------------------------------------------------------------+
66 | Return Value : 0 : Conversion not started |
67 | 1 : Conversion started |
68 +----------------------------------------------------------------------------+
69 */
70 static int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
71 {
72  if ((readl(devpriv->dw_AiBase + 8) & 0x80000UL) == 0x80000UL)
73  return 1;
74  else
75  return 0;
76 
77 }
78 
79 /*
80 +----------------------------------------------------------------------------+
81 | Function Name : int i_APCI3XXX_AnalogInputConfigOperatingMode |
82 | (struct comedi_device *dev, |
83 | struct comedi_subdevice *s, |
84 | struct comedi_insn *insn, |
85 | unsigned int *data) |
86 +----------------------------------------------------------------------------+
87 | Task Converting mode and convert time selection |
88 +----------------------------------------------------------------------------+
89 | Input Parameters : b_SingleDiff = (unsigned char) data[1]; |
90 | b_TimeBase = (unsigned char) data[2]; (0: ns, 1:micros 2:ms)|
91 | dw_ReloadValue = (unsigned int) data[3]; |
92 | ........ |
93 +----------------------------------------------------------------------------+
94 | Output Parameters : - |
95 +----------------------------------------------------------------------------+
96 | Return Value :>0 : No error |
97 | -1 : Single/Diff selection error |
98 | -2 : Convert time base unity selection error |
99 | -3 : Convert time value selection error |
100 | -10: Any conversion started |
101 | .... |
102 | -100 : Config command error |
103 | -101 : Data size error |
104 +----------------------------------------------------------------------------+
105 */
106 static int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
107  struct comedi_subdevice *s,
108  struct comedi_insn *insn,
109  unsigned int *data)
110 {
111  int i_ReturnValue = insn->n;
112  unsigned char b_TimeBase = 0;
113  unsigned char b_SingleDiff = 0;
114  unsigned int dw_ReloadValue = 0;
115  unsigned int dw_TestReloadValue = 0;
116 
117  /************************/
118  /* Test the buffer size */
119  /************************/
120 
121  if (insn->n == 4) {
122  /****************************/
123  /* Get the Singel/Diff flag */
124  /****************************/
125 
126  b_SingleDiff = (unsigned char) data[1];
127 
128  /****************************/
129  /* Get the time base unitiy */
130  /****************************/
131 
132  b_TimeBase = (unsigned char) data[2];
133 
134  /*************************************/
135  /* Get the convert time reload value */
136  /*************************************/
137 
138  dw_ReloadValue = (unsigned int) data[3];
139 
140  /**********************/
141  /* Test the time base */
142  /**********************/
143 
144  if ((this_board->b_AvailableConvertUnit & (1 << b_TimeBase)) !=
145  0) {
146  /*******************************/
147  /* Test the convert time value */
148  /*******************************/
149 
150  if (dw_ReloadValue <= 65535) {
151  dw_TestReloadValue = dw_ReloadValue;
152 
153  if (b_TimeBase == 1) {
154  dw_TestReloadValue =
155  dw_TestReloadValue * 1000UL;
156  }
157  if (b_TimeBase == 2) {
158  dw_TestReloadValue =
159  dw_TestReloadValue * 1000000UL;
160  }
161 
162  /*******************************/
163  /* Test the convert time value */
164  /*******************************/
165 
166  if (dw_TestReloadValue >=
167  devpriv->s_EeParameters.
168  ui_MinAcquisitiontimeNs) {
169  if ((b_SingleDiff == APCI3XXX_SINGLE)
170  || (b_SingleDiff ==
171  APCI3XXX_DIFF)) {
172  if (((b_SingleDiff == APCI3XXX_SINGLE)
173  && (devpriv->s_EeParameters.i_NbrAiChannel == 0))
174  || ((b_SingleDiff == APCI3XXX_DIFF)
175  && (this_board->i_NbrAiChannelDiff == 0))
176  ) {
177  /*******************************/
178  /* Single/Diff selection error */
179  /*******************************/
180 
181  printk("Single/Diff selection error\n");
182  i_ReturnValue = -1;
183  } else {
184  /**********************************/
185  /* Test if conversion not started */
186  /**********************************/
187 
188  if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
189  devpriv->
190  ui_EocEosConversionTime
191  =
192  (unsigned int)
193  dw_ReloadValue;
194  devpriv->
195  b_EocEosConversionTimeBase
196  =
197  b_TimeBase;
198  devpriv->
199  b_SingelDiff
200  =
201  b_SingleDiff;
202  devpriv->
203  b_AiInitialisation
204  = 1;
205 
206  /*******************************/
207  /* Set the convert timing unit */
208  /*******************************/
209 
210  writel((unsigned int)b_TimeBase,
211  devpriv->dw_AiBase + 36);
212 
213  /**************************/
214  /* Set the convert timing */
215  /*************************/
216 
217  writel(dw_ReloadValue, devpriv->dw_AiBase + 32);
218  } else {
219  /**************************/
220  /* Any conversion started */
221  /**************************/
222 
223  printk("Any conversion started\n");
224  i_ReturnValue =
225  -10;
226  }
227  }
228  } else {
229  /*******************************/
230  /* Single/Diff selection error */
231  /*******************************/
232 
233  printk("Single/Diff selection error\n");
234  i_ReturnValue = -1;
235  }
236  } else {
237  /************************/
238  /* Time selection error */
239  /************************/
240 
241  printk("Convert time value selection error\n");
242  i_ReturnValue = -3;
243  }
244  } else {
245  /************************/
246  /* Time selection error */
247  /************************/
248 
249  printk("Convert time value selection error\n");
250  i_ReturnValue = -3;
251  }
252  } else {
253  /*****************************/
254  /* Time base selection error */
255  /*****************************/
256 
257  printk("Convert time base unity selection error\n");
258  i_ReturnValue = -2;
259  }
260  } else {
261  /*******************/
262  /* Data size error */
263  /*******************/
264 
265  printk("Buffer size error\n");
266  i_ReturnValue = -101;
267  }
268 
269  return i_ReturnValue;
270 }
271 
272 /*
273 +----------------------------------------------------------------------------+
274 | Function Name : int i_APCI3XXX_InsnConfigAnalogInput |
275 | (struct comedi_device *dev, |
276 | struct comedi_subdevice *s, |
277 | struct comedi_insn *insn, |
278 | unsigned int *data) |
279 +----------------------------------------------------------------------------+
280 | Task Converting mode and convert time selection |
281 +----------------------------------------------------------------------------+
282 | Input Parameters : b_ConvertMode = (unsigned char) data[0]; |
283 | b_TimeBase = (unsigned char) data[1]; (0: ns, 1:micros 2:ms)|
284 | dw_ReloadValue = (unsigned int) data[2]; |
285 | ........ |
286 +----------------------------------------------------------------------------+
287 | Output Parameters : - |
288 +----------------------------------------------------------------------------+
289 | Return Value :>0: No error |
290 | .... |
291 | -100 : Config command error |
292 | -101 : Data size error |
293 +----------------------------------------------------------------------------+
294 */
295 static int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
296  struct comedi_subdevice *s,
297  struct comedi_insn *insn,
298  unsigned int *data)
299 {
300  int i_ReturnValue = insn->n;
301 
302  /************************/
303  /* Test the buffer size */
304  /************************/
305 
306  if (insn->n >= 1) {
307  switch ((unsigned char) data[0]) {
309  i_ReturnValue =
310  i_APCI3XXX_AnalogInputConfigOperatingMode(dev,
311  s, insn, data);
312  break;
313 
314  default:
315  i_ReturnValue = -100;
316  printk("Config command error %d\n", data[0]);
317  break;
318  }
319  } else {
320  /*******************/
321  /* Data size error */
322  /*******************/
323 
324  printk("Buffer size error\n");
325  i_ReturnValue = -101;
326  }
327 
328  return i_ReturnValue;
329 }
330 
331 /*
332 +----------------------------------------------------------------------------+
333 | Function Name : int i_APCI3XXX_InsnReadAnalogInput |
334 | (struct comedi_device *dev, |
335 | struct comedi_subdevice *s, |
336 | struct comedi_insn *insn, |
337 | unsigned int *data) |
338 +----------------------------------------------------------------------------+
339 | Task Read 1 analog input |
340 +----------------------------------------------------------------------------+
341 | Input Parameters : b_Range = CR_RANGE(insn->chanspec); |
342 | b_Channel = CR_CHAN(insn->chanspec); |
343 | dw_NbrOfAcquisition = insn->n; |
344 +----------------------------------------------------------------------------+
345 | Output Parameters : - |
346 +----------------------------------------------------------------------------+
347 | Return Value :>0: No error |
348 | -3 : Channel selection error |
349 | -4 : Configuration selelection error |
350 | -10: Any conversion started |
351 | .... |
352 | -100 : Config command error |
353 | -101 : Data size error |
354 +----------------------------------------------------------------------------+
355 */
356 static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
357  struct comedi_subdevice *s,
358  struct comedi_insn *insn,
359  unsigned int *data)
360 {
361  int i_ReturnValue = insn->n;
362  unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
363  unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
364  unsigned int dw_Temp = 0;
365  unsigned int dw_Configuration = 0;
366  unsigned int dw_AcquisitionCpt = 0;
367  unsigned char b_Interrupt = 0;
368 
369  /*************************************/
370  /* Test if operating mode configured */
371  /*************************************/
372 
373  if (devpriv->b_AiInitialisation) {
374  /***************************/
375  /* Test the channel number */
376  /***************************/
377 
378  if (((b_Channel < devpriv->s_EeParameters.i_NbrAiChannel)
379  && (devpriv->b_SingelDiff == APCI3XXX_SINGLE))
380  || ((b_Channel < this_board->i_NbrAiChannelDiff)
381  && (devpriv->b_SingelDiff == APCI3XXX_DIFF))) {
382  /**********************************/
383  /* Test the channel configuration */
384  /**********************************/
385 
386  if (b_Configuration > 7) {
387  /***************************/
388  /* Channel not initialised */
389  /***************************/
390 
391  i_ReturnValue = -4;
392  printk("Channel %d range %d selection error\n",
393  b_Channel, b_Configuration);
394  }
395  } else {
396  /***************************/
397  /* Channel selection error */
398  /***************************/
399 
400  i_ReturnValue = -3;
401  printk("Channel %d selection error\n", b_Channel);
402  }
403 
404  /**************************/
405  /* Test if no error occur */
406  /**************************/
407 
408  if (i_ReturnValue >= 0) {
409  /************************/
410  /* Test the buffer size */
411  /************************/
412 
413  if ((b_Interrupt != 0) || ((b_Interrupt == 0)
414  && (insn->n >= 1))) {
415  /**********************************/
416  /* Test if conversion not started */
417  /**********************************/
418 
419  if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
420  /******************/
421  /* Clear the FIFO */
422  /******************/
423 
424  writel(0x10000UL, devpriv->dw_AiBase + 12);
425 
426  /*******************************/
427  /* Get and save the delay mode */
428  /*******************************/
429 
430  dw_Temp = readl(devpriv->dw_AiBase + 4);
431  dw_Temp = dw_Temp & 0xFFFFFEF0UL;
432 
433  /***********************************/
434  /* Channel configuration selection */
435  /***********************************/
436 
437  writel(dw_Temp, devpriv->dw_AiBase + 4);
438 
439  /**************************/
440  /* Make the configuration */
441  /**************************/
442 
443  dw_Configuration =
444  (b_Configuration & 3) |
445  ((unsigned int) (b_Configuration >> 2)
446  << 6) | ((unsigned int) devpriv->
447  b_SingelDiff << 7);
448 
449  /***************************/
450  /* Write the configuration */
451  /***************************/
452 
453  writel(dw_Configuration,
454  devpriv->dw_AiBase + 0);
455 
456  /*********************/
457  /* Channel selection */
458  /*********************/
459 
460  writel(dw_Temp | 0x100UL,
461  devpriv->dw_AiBase + 4);
462  writel((unsigned int) b_Channel,
463  devpriv->dw_AiBase + 0);
464 
465  /***********************/
466  /* Restaure delay mode */
467  /***********************/
468 
469  writel(dw_Temp, devpriv->dw_AiBase + 4);
470 
471  /***********************************/
472  /* Set the number of sequence to 1 */
473  /***********************************/
474 
475  writel(1, devpriv->dw_AiBase + 48);
476 
477  /***************************/
478  /* Save the interrupt flag */
479  /***************************/
480 
481  devpriv->b_EocEosInterrupt =
482  b_Interrupt;
483 
484  /*******************************/
485  /* Save the number of channels */
486  /*******************************/
487 
488  devpriv->ui_AiNbrofChannels = 1;
489 
490  /******************************/
491  /* Test if interrupt not used */
492  /******************************/
493 
494  if (b_Interrupt == 0) {
495  for (dw_AcquisitionCpt = 0;
496  dw_AcquisitionCpt <
497  insn->n;
498  dw_AcquisitionCpt++) {
499  /************************/
500  /* Start the conversion */
501  /************************/
502 
503  writel(0x80000UL, devpriv->dw_AiBase + 8);
504 
505  /****************/
506  /* Wait the EOS */
507  /****************/
508 
509  do {
510  dw_Temp = readl(devpriv->dw_AiBase + 20);
511  dw_Temp = dw_Temp & 1;
512  } while (dw_Temp != 1);
513 
514  /*************************/
515  /* Read the analog value */
516  /*************************/
517 
518  data[dw_AcquisitionCpt] = (unsigned int)readl(devpriv->dw_AiBase + 28);
519  }
520  } else {
521  /************************/
522  /* Start the conversion */
523  /************************/
524 
525  writel(0x180000UL, devpriv->dw_AiBase + 8);
526  }
527  } else {
528  /**************************/
529  /* Any conversion started */
530  /**************************/
531 
532  printk("Any conversion started\n");
533  i_ReturnValue = -10;
534  }
535  } else {
536  /*******************/
537  /* Data size error */
538  /*******************/
539 
540  printk("Buffer size error\n");
541  i_ReturnValue = -101;
542  }
543  }
544  } else {
545  /***************************/
546  /* Channel selection error */
547  /***************************/
548 
549  printk("Operating mode not configured\n");
550  i_ReturnValue = -1;
551  }
552  return i_ReturnValue;
553 }
554 
555 /*
556 +----------------------------------------------------------------------------+
557 | Function name : void v_APCI3XXX_Interrupt (int irq, |
558 | void *d) |
559 +----------------------------------------------------------------------------+
560 | Task :Interrupt handler for APCI3XXX |
561 | When interrupt occurs this gets called. |
562 | First it finds which interrupt has been generated and |
563 | handles corresponding interrupt |
564 +----------------------------------------------------------------------------+
565 | Input Parameters : - |
566 +----------------------------------------------------------------------------+
567 | Return Value : - |
568 +----------------------------------------------------------------------------+
569 */
570 
571 static void v_APCI3XXX_Interrupt(int irq, void *d)
572 {
573  struct comedi_device *dev = d;
574  unsigned char b_CopyCpt = 0;
575  unsigned int dw_Status = 0;
576 
577  /***************************/
578  /* Test if interrupt occur */
579  /***************************/
580 
581  dw_Status = readl(devpriv->dw_AiBase + 16);
582  if ( (dw_Status & 0x2UL) == 0x2UL) {
583  /***********************/
584  /* Reset the interrupt */
585  /***********************/
586 
587  writel(dw_Status, devpriv->dw_AiBase + 16);
588 
589  /*****************************/
590  /* Test if interrupt enabled */
591  /*****************************/
592 
593  if (devpriv->b_EocEosInterrupt == 1) {
594  /********************************/
595  /* Read all analog inputs value */
596  /********************************/
597 
598  for (b_CopyCpt = 0;
599  b_CopyCpt < devpriv->ui_AiNbrofChannels;
600  b_CopyCpt++) {
601  devpriv->ui_AiReadData[b_CopyCpt] =
602  (unsigned int)readl(devpriv->dw_AiBase + 28);
603  }
604 
605  /**************************/
606  /* Set the interrupt flag */
607  /**************************/
608 
609  devpriv->b_EocEosInterrupt = 2;
610 
611  /**********************************************/
612  /* Send a signal to from kernel to user space */
613  /**********************************************/
614 
615  send_sig(SIGIO, devpriv->tsk_Current, 0);
616  }
617  }
618 }
619 
620 /*
621 +----------------------------------------------------------------------------+
622 | ANALOG OUTPUT SUBDEVICE |
623 +----------------------------------------------------------------------------+
624 */
625 
626 /*
627 +----------------------------------------------------------------------------+
628 | Function Name : int i_APCI3XXX_InsnWriteAnalogOutput |
629 | (struct comedi_device *dev, |
630 | struct comedi_subdevice *s, |
631 | struct comedi_insn *insn, |
632 | unsigned int *data) |
633 +----------------------------------------------------------------------------+
634 | Task Read 1 analog input |
635 +----------------------------------------------------------------------------+
636 | Input Parameters : b_Range = CR_RANGE(insn->chanspec); |
637 | b_Channel = CR_CHAN(insn->chanspec); |
638 | data[0] = analog value; |
639 +----------------------------------------------------------------------------+
640 | Output Parameters : - |
641 +----------------------------------------------------------------------------+
642 | Return Value :>0: No error |
643 | -3 : Channel selection error |
644 | -4 : Configuration selelection error |
645 | .... |
646 | -101 : Data size error |
647 +----------------------------------------------------------------------------+
648 */
649 static int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
650  struct comedi_subdevice *s,
651  struct comedi_insn *insn,
652  unsigned int *data)
653 {
654  unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
655  unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
656  unsigned int dw_Status = 0;
657  int i_ReturnValue = insn->n;
658 
659  /************************/
660  /* Test the buffer size */
661  /************************/
662 
663  if (insn->n >= 1) {
664  /***************************/
665  /* Test the channel number */
666  /***************************/
667 
668  if (b_Channel < devpriv->s_EeParameters.i_NbrAoChannel) {
669  /**********************************/
670  /* Test the channel configuration */
671  /**********************************/
672 
673  if (b_Range < 2) {
674  /***************************/
675  /* Set the range selection */
676  /***************************/
677 
678  writel(b_Range, devpriv->dw_AiBase + 96);
679 
680  /**************************************************/
681  /* Write the analog value to the selected channel */
682  /**************************************************/
683 
684  writel((data[0] << 8) | b_Channel,
685  devpriv->dw_AiBase + 100);
686 
687  /****************************/
688  /* Wait the end of transfer */
689  /****************************/
690 
691  do {
692  dw_Status = readl(devpriv->dw_AiBase + 96);
693  } while ((dw_Status & 0x100) != 0x100);
694  } else {
695  /***************************/
696  /* Channel not initialised */
697  /***************************/
698 
699  i_ReturnValue = -4;
700  printk("Channel %d range %d selection error\n",
701  b_Channel, b_Range);
702  }
703  } else {
704  /***************************/
705  /* Channel selection error */
706  /***************************/
707 
708  i_ReturnValue = -3;
709  printk("Channel %d selection error\n", b_Channel);
710  }
711  } else {
712  /*******************/
713  /* Data size error */
714  /*******************/
715 
716  printk("Buffer size error\n");
717  i_ReturnValue = -101;
718  }
719 
720  return i_ReturnValue;
721 }
722 
723 /*
724 +----------------------------------------------------------------------------+
725 | TTL FUNCTIONS |
726 +----------------------------------------------------------------------------+
727 */
728 
729 /*
730 +----------------------------------------------------------------------------+
731 | Function Name : int i_APCI3XXX_InsnConfigInitTTLIO |
732 | (struct comedi_device *dev, |
733 | struct comedi_subdevice *s, |
734 | struct comedi_insn *insn, |
735 | unsigned int *data) |
736 +----------------------------------------------------------------------------+
737 | Task You must calling this function be |
738 | for you call any other function witch access of TTL. |
739 | APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
740 +----------------------------------------------------------------------------+
741 | Input Parameters : b_InitType = (unsigned char) data[0]; |
742 | b_Port2Mode = (unsigned char) data[1]; |
743 +----------------------------------------------------------------------------+
744 | Output Parameters : - |
745 +----------------------------------------------------------------------------+
746 | Return Value :>0: No error |
747 | -1: Port 2 mode selection is wrong |
748 | .... |
749 | -100 : Config command error |
750 | -101 : Data size error |
751 +----------------------------------------------------------------------------+
752 */
753 static int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
754  struct comedi_subdevice *s,
755  struct comedi_insn *insn,
756  unsigned int *data)
757 {
758  int i_ReturnValue = insn->n;
759  unsigned char b_Command = 0;
760 
761  /************************/
762  /* Test the buffer size */
763  /************************/
764 
765  if (insn->n >= 1) {
766  /*******************/
767  /* Get the command */
768  /* **************** */
769 
770  b_Command = (unsigned char) data[0];
771 
772  /********************/
773  /* Test the command */
774  /********************/
775 
776  if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
777  /***************************************/
778  /* Test the initialisation buffer size */
779  /***************************************/
780 
781  if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)
782  && (insn->n != 2)) {
783  /*******************/
784  /* Data size error */
785  /*******************/
786 
787  printk("Buffer size error\n");
788  i_ReturnValue = -101;
789  }
790  } else {
791  /************************/
792  /* Config command error */
793  /************************/
794 
795  printk("Command selection error\n");
796  i_ReturnValue = -100;
797  }
798  } else {
799  /*******************/
800  /* Data size error */
801  /*******************/
802 
803  printk("Buffer size error\n");
804  i_ReturnValue = -101;
805  }
806 
807  /*********************************************************************************/
808  /* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */
809  /*********************************************************************************/
810 
811  if ((i_ReturnValue >= 0)
812  && (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) {
813  /**********************/
814  /* Test the direction */
815  /**********************/
816 
817  if ((data[1] == 0) || (data[1] == 0xFF)) {
818  /**************************/
819  /* Save the configuration */
820  /**************************/
821 
822  devpriv->ul_TTLPortConfiguration[0] =
823  devpriv->ul_TTLPortConfiguration[0] | data[1];
824  } else {
825  /************************/
826  /* Port direction error */
827  /************************/
828 
829  printk("Port 2 direction selection error\n");
830  i_ReturnValue = -1;
831  }
832  }
833 
834  /**************************/
835  /* Test if no error occur */
836  /**************************/
837 
838  if (i_ReturnValue >= 0) {
839  /***********************************/
840  /* Test if TTL port initilaisation */
841  /***********************************/
842 
843  if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
844  /*************************/
845  /* Set the configuration */
846  /*************************/
847 
848  outl(data[1], devpriv->iobase + 224);
849  }
850  }
851 
852  return i_ReturnValue;
853 }
854 
855 /*
856 +----------------------------------------------------------------------------+
857 | TTL INPUT FUNCTIONS |
858 +----------------------------------------------------------------------------+
859 */
860 
861 /*
862 +----------------------------------------------------------------------------+
863 | Function Name : int i_APCI3XXX_InsnBitsTTLIO |
864 | (struct comedi_device *dev, |
865 | struct comedi_subdevice *s, |
866 | struct comedi_insn *insn, |
867 | unsigned int *data) |
868 +----------------------------------------------------------------------------+
869 | Task : Write the selected output mask and read the status from|
870 | all TTL channles |
871 +----------------------------------------------------------------------------+
872 | Input Parameters : dw_ChannelMask = data [0]; |
873 | dw_BitMask = data [1]; |
874 +----------------------------------------------------------------------------+
875 | Output Parameters : data[1] : All TTL channles states |
876 +----------------------------------------------------------------------------+
877 | Return Value : >0 : No error |
878 | -4 : Channel mask error |
879 | -101 : Data size error |
880 +----------------------------------------------------------------------------+
881 */
882 static int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
883  struct comedi_subdevice *s,
884  struct comedi_insn *insn,
885  unsigned int *data)
886 {
887  int i_ReturnValue = insn->n;
888  unsigned char b_ChannelCpt = 0;
889  unsigned int dw_ChannelMask = 0;
890  unsigned int dw_BitMask = 0;
891  unsigned int dw_Status = 0;
892 
893  /************************/
894  /* Test the buffer size */
895  /************************/
896 
897  if (insn->n >= 2) {
898  /*******************************/
899  /* Get the channe and bit mask */
900  /*******************************/
901 
902  dw_ChannelMask = data[0];
903  dw_BitMask = data[1];
904 
905  /*************************/
906  /* Test the channel mask */
907  /*************************/
908 
909  if (((dw_ChannelMask & 0XFF00FF00) == 0) &&
910  (((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF)
911  || (((devpriv->ul_TTLPortConfiguration[0] &
912  0xFF) == 0)
913  && ((dw_ChannelMask & 0XFF0000) ==
914  0)))) {
915  /*********************************/
916  /* Test if set/reset any channel */
917  /*********************************/
918 
919  if (dw_ChannelMask) {
920  /****************************************/
921  /* Test if set/rest any port 0 channels */
922  /****************************************/
923 
924  if (dw_ChannelMask & 0xFF) {
925  /*******************************************/
926  /* Read port 0 (first digital output port) */
927  /*******************************************/
928 
929  dw_Status = inl(devpriv->iobase + 80);
930 
931  for (b_ChannelCpt = 0; b_ChannelCpt < 8;
932  b_ChannelCpt++) {
933  if ((dw_ChannelMask >>
934  b_ChannelCpt) &
935  1) {
936  dw_Status =
937  (dw_Status &
938  (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
939  }
940  }
941 
942  outl(dw_Status, devpriv->iobase + 80);
943  }
944 
945  /****************************************/
946  /* Test if set/rest any port 2 channels */
947  /****************************************/
948 
949  if (dw_ChannelMask & 0xFF0000) {
950  dw_BitMask = dw_BitMask >> 16;
951  dw_ChannelMask = dw_ChannelMask >> 16;
952 
953  /********************************************/
954  /* Read port 2 (second digital output port) */
955  /********************************************/
956 
957  dw_Status = inl(devpriv->iobase + 112);
958 
959  for (b_ChannelCpt = 0; b_ChannelCpt < 8;
960  b_ChannelCpt++) {
961  if ((dw_ChannelMask >>
962  b_ChannelCpt) &
963  1) {
964  dw_Status =
965  (dw_Status &
966  (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
967  }
968  }
969 
970  outl(dw_Status, devpriv->iobase + 112);
971  }
972  }
973 
974  /*******************************************/
975  /* Read port 0 (first digital output port) */
976  /*******************************************/
977 
978  data[1] = inl(devpriv->iobase + 80);
979 
980  /******************************************/
981  /* Read port 1 (first digital input port) */
982  /******************************************/
983 
984  data[1] = data[1] | (inl(devpriv->iobase + 64) << 8);
985 
986  /************************/
987  /* Test if port 2 input */
988  /************************/
989 
990  if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) {
991  data[1] =
992  data[1] | (inl(devpriv->iobase +
993  96) << 16);
994  } else {
995  data[1] =
996  data[1] | (inl(devpriv->iobase +
997  112) << 16);
998  }
999  } else {
1000  /************************/
1001  /* Config command error */
1002  /************************/
1003 
1004  printk("Channel mask error\n");
1005  i_ReturnValue = -4;
1006  }
1007  } else {
1008  /*******************/
1009  /* Data size error */
1010  /*******************/
1011 
1012  printk("Buffer size error\n");
1013  i_ReturnValue = -101;
1014  }
1015 
1016  return i_ReturnValue;
1017 }
1018 
1019 /*
1020 +----------------------------------------------------------------------------+
1021 | Function Name : int i_APCI3XXX_InsnReadTTLIO |
1022 | (struct comedi_device *dev, |
1023 | struct comedi_subdevice *s, |
1024 | struct comedi_insn *insn, |
1025 | unsigned int *data) |
1026 +----------------------------------------------------------------------------+
1027 | Task : Read the status from selected channel |
1028 +----------------------------------------------------------------------------+
1029 | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
1030 +----------------------------------------------------------------------------+
1031 | Output Parameters : data[0] : Selected TTL channel state |
1032 +----------------------------------------------------------------------------+
1033 | Return Value : 0 : No error |
1034 | -3 : Channel selection error |
1035 | -101 : Data size error |
1036 +----------------------------------------------------------------------------+
1037 */
1038 static int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
1039  struct comedi_subdevice *s,
1040  struct comedi_insn *insn,
1041  unsigned int *data)
1042 {
1043  unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1044  int i_ReturnValue = insn->n;
1045  unsigned int *pls_ReadData = data;
1046 
1047  /************************/
1048  /* Test the buffer size */
1049  /************************/
1050 
1051  if (insn->n >= 1) {
1052  /***********************/
1053  /* Test if read port 0 */
1054  /***********************/
1055 
1056  if (b_Channel < 8) {
1057  /*******************************************/
1058  /* Read port 0 (first digital output port) */
1059  /*******************************************/
1060 
1061  pls_ReadData[0] = inl(devpriv->iobase + 80);
1062  pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1;
1063  } else {
1064  /***********************/
1065  /* Test if read port 1 */
1066  /***********************/
1067 
1068  if ((b_Channel > 7) && (b_Channel < 16)) {
1069  /******************************************/
1070  /* Read port 1 (first digital input port) */
1071  /******************************************/
1072 
1073  pls_ReadData[0] = inl(devpriv->iobase + 64);
1074  pls_ReadData[0] =
1075  (pls_ReadData[0] >> (b_Channel -
1076  8)) & 1;
1077  } else {
1078  /***********************/
1079  /* Test if read port 2 */
1080  /***********************/
1081 
1082  if ((b_Channel > 15) && (b_Channel < 24)) {
1083  /************************/
1084  /* Test if port 2 input */
1085  /************************/
1086 
1087  if ((devpriv->ul_TTLPortConfiguration[0]
1088  & 0xFF) == 0) {
1089  pls_ReadData[0] =
1090  inl(devpriv->iobase +
1091  96);
1092  pls_ReadData[0] =
1093  (pls_ReadData[0] >>
1094  (b_Channel - 16)) & 1;
1095  } else {
1096  pls_ReadData[0] =
1097  inl(devpriv->iobase +
1098  112);
1099  pls_ReadData[0] =
1100  (pls_ReadData[0] >>
1101  (b_Channel - 16)) & 1;
1102  }
1103  } else {
1104  /***************************/
1105  /* Channel selection error */
1106  /***************************/
1107 
1108  i_ReturnValue = -3;
1109  printk("Channel %d selection error\n",
1110  b_Channel);
1111  }
1112  }
1113  }
1114  } else {
1115  /*******************/
1116  /* Data size error */
1117  /*******************/
1118 
1119  printk("Buffer size error\n");
1120  i_ReturnValue = -101;
1121  }
1122 
1123  return i_ReturnValue;
1124 }
1125 
1126 /*
1127 +----------------------------------------------------------------------------+
1128 | TTL OUTPUT FUNCTIONS |
1129 +----------------------------------------------------------------------------+
1130 */
1131 
1132 /*
1133 +----------------------------------------------------------------------------+
1134 | Function Name : int i_APCI3XXX_InsnWriteTTLIO |
1135 | (struct comedi_device *dev, |
1136 | struct comedi_subdevice *s, |
1137 | struct comedi_insn *insn, |
1138 | unsigned int *data) |
1139 +----------------------------------------------------------------------------+
1140 | Task : Set the state from TTL output channel |
1141 +----------------------------------------------------------------------------+
1142 | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
1143 | b_State = data [0] |
1144 +----------------------------------------------------------------------------+
1145 | Output Parameters : - |
1146 +----------------------------------------------------------------------------+
1147 | Return Value : 0 : No error |
1148 | -3 : Channel selection error |
1149 | -101 : Data size error |
1150 +----------------------------------------------------------------------------+
1151 */
1152 static int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
1153  struct comedi_subdevice *s,
1154  struct comedi_insn *insn,
1155  unsigned int *data)
1156 {
1157  int i_ReturnValue = insn->n;
1158  unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1159  unsigned char b_State = 0;
1160  unsigned int dw_Status = 0;
1161 
1162  /************************/
1163  /* Test the buffer size */
1164  /************************/
1165 
1166  if (insn->n >= 1) {
1167  b_State = (unsigned char) data[0];
1168 
1169  /***********************/
1170  /* Test if read port 0 */
1171  /***********************/
1172 
1173  if (b_Channel < 8) {
1174  /*****************************************************************************/
1175  /* Read port 0 (first digital output port) and set/reset the selected channel */
1176  /*****************************************************************************/
1177 
1178  dw_Status = inl(devpriv->iobase + 80);
1179  dw_Status =
1180  (dw_Status & (0xFF -
1181  (1 << b_Channel))) | ((b_State & 1) <<
1182  b_Channel);
1183  outl(dw_Status, devpriv->iobase + 80);
1184  } else {
1185  /***********************/
1186  /* Test if read port 2 */
1187  /***********************/
1188 
1189  if ((b_Channel > 15) && (b_Channel < 24)) {
1190  /*************************/
1191  /* Test if port 2 output */
1192  /*************************/
1193 
1194  if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
1195  == 0xFF) {
1196  /*****************************************************************************/
1197  /* Read port 2 (first digital output port) and set/reset the selected channel */
1198  /*****************************************************************************/
1199 
1200  dw_Status = inl(devpriv->iobase + 112);
1201  dw_Status =
1202  (dw_Status & (0xFF -
1203  (1 << (b_Channel -
1204  16)))) |
1205  ((b_State & 1) << (b_Channel -
1206  16));
1207  outl(dw_Status, devpriv->iobase + 112);
1208  } else {
1209  /***************************/
1210  /* Channel selection error */
1211  /***************************/
1212 
1213  i_ReturnValue = -3;
1214  printk("Channel %d selection error\n",
1215  b_Channel);
1216  }
1217  } else {
1218  /***************************/
1219  /* Channel selection error */
1220  /***************************/
1221 
1222  i_ReturnValue = -3;
1223  printk("Channel %d selection error\n",
1224  b_Channel);
1225  }
1226  }
1227  } else {
1228  /*******************/
1229  /* Data size error */
1230  /*******************/
1231 
1232  printk("Buffer size error\n");
1233  i_ReturnValue = -101;
1234  }
1235 
1236  return i_ReturnValue;
1237 }
1238 
1239 /*
1240 +----------------------------------------------------------------------------+
1241 | DIGITAL INPUT SUBDEVICE |
1242 +----------------------------------------------------------------------------+
1243 */
1244 
1245 /*
1246 +----------------------------------------------------------------------------+
1247 | Function name :int i_APCI3XXX_InsnReadDigitalInput |
1248 | (struct comedi_device *dev, |
1249 | struct comedi_subdevice *s, |
1250 | struct comedi_insn *insn, |
1251 | unsigned int *data) |
1252 +----------------------------------------------------------------------------+
1253 | Task : Reads the value of the specified Digital input channel |
1254 +----------------------------------------------------------------------------+
1255 | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) (0 to 3) |
1256 +----------------------------------------------------------------------------+
1257 | Output Parameters : data[0] : Channel value |
1258 +----------------------------------------------------------------------------+
1259 | Return Value : 0 : No error |
1260 | -3 : Channel selection error |
1261 | -101 : Data size error |
1262 +----------------------------------------------------------------------------+
1263 */
1264 
1265 static int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
1266  struct comedi_subdevice *s,
1267  struct comedi_insn *insn,
1268  unsigned int *data)
1269 {
1270  int i_ReturnValue = insn->n;
1271  unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1272  unsigned int dw_Temp = 0;
1273 
1274  /***************************/
1275  /* Test the channel number */
1276  /***************************/
1277 
1278  if (b_Channel <= devpriv->s_EeParameters.i_NbrDiChannel) {
1279  /************************/
1280  /* Test the buffer size */
1281  /************************/
1282 
1283  if (insn->n >= 1) {
1284  dw_Temp = inl(devpriv->iobase + 32);
1285  *data = (dw_Temp >> b_Channel) & 1;
1286  } else {
1287  /*******************/
1288  /* Data size error */
1289  /*******************/
1290 
1291  printk("Buffer size error\n");
1292  i_ReturnValue = -101;
1293  }
1294  } else {
1295  /***************************/
1296  /* Channel selection error */
1297  /***************************/
1298 
1299  printk("Channel selection error\n");
1300  i_ReturnValue = -3;
1301  }
1302 
1303  return i_ReturnValue;
1304 }
1305 
1306 /*
1307 +----------------------------------------------------------------------------+
1308 | Function name :int i_APCI3XXX_InsnBitsDigitalInput |
1309 | (struct comedi_device *dev, |
1310 | struct comedi_subdevice *s, |
1311 | struct comedi_insn *insn, |
1312 | unsigned int *data) |
1313 +----------------------------------------------------------------------------+
1314 | Task : Reads the value of the Digital input Port i.e.4channels|
1315 +----------------------------------------------------------------------------+
1316 | Input Parameters : - |
1317 +----------------------------------------------------------------------------+
1318 | Output Parameters : data[0] : Port value |
1319 +----------------------------------------------------------------------------+
1320 | Return Value :>0: No error |
1321 | .... |
1322 | -101 : Data size error |
1323 +----------------------------------------------------------------------------+
1324 */
1325 static int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
1326  struct comedi_subdevice *s,
1327  struct comedi_insn *insn,
1328  unsigned int *data)
1329 {
1330  int i_ReturnValue = insn->n;
1331  unsigned int dw_Temp = 0;
1332 
1333  /************************/
1334  /* Test the buffer size */
1335  /************************/
1336 
1337  if (insn->n >= 1) {
1338  dw_Temp = inl(devpriv->iobase + 32);
1339  *data = dw_Temp & 0xf;
1340  } else {
1341  /*******************/
1342  /* Data size error */
1343  /*******************/
1344 
1345  printk("Buffer size error\n");
1346  i_ReturnValue = -101;
1347  }
1348 
1349  return i_ReturnValue;
1350 }
1351 
1352 /*
1353 +----------------------------------------------------------------------------+
1354 | DIGITAL OUTPUT SUBDEVICE |
1355 +----------------------------------------------------------------------------+
1356 
1357 */
1358 
1359 /*
1360 +----------------------------------------------------------------------------+
1361 | Function name :int i_APCI3XXX_InsnBitsDigitalOutput |
1362 | (struct comedi_device *dev, |
1363 | struct comedi_subdevice *s, |
1364 | struct comedi_insn *insn, |
1365 | unsigned int *data) |
1366 +----------------------------------------------------------------------------+
1367 | Task : Write the selected output mask and read the status from|
1368 | all digital output channles |
1369 +----------------------------------------------------------------------------+
1370 | Input Parameters : dw_ChannelMask = data [0]; |
1371 | dw_BitMask = data [1]; |
1372 +----------------------------------------------------------------------------+
1373 | Output Parameters : data[1] : All digital output channles states |
1374 +----------------------------------------------------------------------------+
1375 | Return Value : >0 : No error |
1376 | -4 : Channel mask error |
1377 | -101 : Data size error |
1378 +----------------------------------------------------------------------------+
1379 */
1380 static int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
1381  struct comedi_subdevice *s,
1382  struct comedi_insn *insn,
1383  unsigned int *data)
1384 {
1385  int i_ReturnValue = insn->n;
1386  unsigned char b_ChannelCpt = 0;
1387  unsigned int dw_ChannelMask = 0;
1388  unsigned int dw_BitMask = 0;
1389  unsigned int dw_Status = 0;
1390 
1391  /************************/
1392  /* Test the buffer size */
1393  /************************/
1394 
1395  if (insn->n >= 2) {
1396  /*******************************/
1397  /* Get the channe and bit mask */
1398  /*******************************/
1399 
1400  dw_ChannelMask = data[0];
1401  dw_BitMask = data[1];
1402 
1403  /*************************/
1404  /* Test the channel mask */
1405  /*************************/
1406 
1407  if ((dw_ChannelMask & 0XFFFFFFF0) == 0) {
1408  /*********************************/
1409  /* Test if set/reset any channel */
1410  /*********************************/
1411 
1412  if (dw_ChannelMask & 0xF) {
1413  /********************************/
1414  /* Read the digital output port */
1415  /********************************/
1416 
1417  dw_Status = inl(devpriv->iobase + 48);
1418 
1419  for (b_ChannelCpt = 0; b_ChannelCpt < 4;
1420  b_ChannelCpt++) {
1421  if ((dw_ChannelMask >> b_ChannelCpt) &
1422  1) {
1423  dw_Status =
1424  (dw_Status & (0xF -
1425  (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
1426  }
1427  }
1428 
1429  outl(dw_Status, devpriv->iobase + 48);
1430  }
1431 
1432  /********************************/
1433  /* Read the digital output port */
1434  /********************************/
1435 
1436  data[1] = inl(devpriv->iobase + 48);
1437  } else {
1438  /************************/
1439  /* Config command error */
1440  /************************/
1441 
1442  printk("Channel mask error\n");
1443  i_ReturnValue = -4;
1444  }
1445  } else {
1446  /*******************/
1447  /* Data size error */
1448  /*******************/
1449 
1450  printk("Buffer size error\n");
1451  i_ReturnValue = -101;
1452  }
1453 
1454  return i_ReturnValue;
1455 }
1456 
1457 /*
1458 +----------------------------------------------------------------------------+
1459 | Function name :int i_APCI3XXX_InsnWriteDigitalOutput |
1460 | (struct comedi_device *dev, |
1461 | struct comedi_subdevice *s, |
1462 | struct comedi_insn *insn, |
1463 | unsigned int *data) |
1464 +----------------------------------------------------------------------------+
1465 | Task : Set the state from digital output channel |
1466 +----------------------------------------------------------------------------+
1467 | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
1468 | b_State = data [0] |
1469 +----------------------------------------------------------------------------+
1470 | Output Parameters : - |
1471 +----------------------------------------------------------------------------+
1472 | Return Value : >0 : No error |
1473 | -3 : Channel selection error |
1474 | -101 : Data size error |
1475 +----------------------------------------------------------------------------+
1476 */
1477 
1478 static int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
1479  struct comedi_subdevice *s,
1480  struct comedi_insn *insn,
1481  unsigned int *data)
1482 {
1483  int i_ReturnValue = insn->n;
1484  unsigned char b_Channel = CR_CHAN(insn->chanspec);
1485  unsigned char b_State = 0;
1486  unsigned int dw_Status = 0;
1487 
1488  /************************/
1489  /* Test the buffer size */
1490  /************************/
1491 
1492  if (insn->n >= 1) {
1493  /***************************/
1494  /* Test the channel number */
1495  /***************************/
1496 
1497  if (b_Channel < devpriv->s_EeParameters.i_NbrDoChannel) {
1498  /*******************/
1499  /* Get the command */
1500  /*******************/
1501 
1502  b_State = (unsigned char) data[0];
1503 
1504  /********************************/
1505  /* Read the digital output port */
1506  /********************************/
1507 
1508  dw_Status = inl(devpriv->iobase + 48);
1509 
1510  dw_Status =
1511  (dw_Status & (0xF -
1512  (1 << b_Channel))) | ((b_State & 1) <<
1513  b_Channel);
1514  outl(dw_Status, devpriv->iobase + 48);
1515  } else {
1516  /***************************/
1517  /* Channel selection error */
1518  /***************************/
1519 
1520  printk("Channel selection error\n");
1521  i_ReturnValue = -3;
1522  }
1523  } else {
1524  /*******************/
1525  /* Data size error */
1526  /*******************/
1527 
1528  printk("Buffer size error\n");
1529  i_ReturnValue = -101;
1530  }
1531 
1532  return i_ReturnValue;
1533 }
1534 
1535 /*
1536 +----------------------------------------------------------------------------+
1537 | Function name :int i_APCI3XXX_InsnReadDigitalOutput |
1538 | (struct comedi_device *dev, |
1539 | struct comedi_subdevice *s, |
1540 | struct comedi_insn *insn, |
1541 | unsigned int *data) |
1542 +----------------------------------------------------------------------------+
1543 | Task : Read the state from digital output channel |
1544 +----------------------------------------------------------------------------+
1545 | Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
1546 +----------------------------------------------------------------------------+
1547 | Output Parameters : b_State = data [0] |
1548 +----------------------------------------------------------------------------+
1549 | Return Value : >0 : No error |
1550 | -3 : Channel selection error |
1551 | -101 : Data size error |
1552 +----------------------------------------------------------------------------+
1553 */
1554 
1555 static int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
1556  struct comedi_subdevice *s,
1557  struct comedi_insn *insn,
1558  unsigned int *data)
1559 {
1560  int i_ReturnValue = insn->n;
1561  unsigned char b_Channel = CR_CHAN(insn->chanspec);
1562  unsigned int dw_Status = 0;
1563 
1564  /************************/
1565  /* Test the buffer size */
1566  /************************/
1567 
1568  if (insn->n >= 1) {
1569  /***************************/
1570  /* Test the channel number */
1571  /***************************/
1572 
1573  if (b_Channel < devpriv->s_EeParameters.i_NbrDoChannel) {
1574  /********************************/
1575  /* Read the digital output port */
1576  /********************************/
1577 
1578  dw_Status = inl(devpriv->iobase + 48);
1579 
1580  dw_Status = (dw_Status >> b_Channel) & 1;
1581  *data = dw_Status;
1582  } else {
1583  /***************************/
1584  /* Channel selection error */
1585  /***************************/
1586 
1587  printk("Channel selection error\n");
1588  i_ReturnValue = -3;
1589  }
1590  } else {
1591  /*******************/
1592  /* Data size error */
1593  /*******************/
1594 
1595  printk("Buffer size error\n");
1596  i_ReturnValue = -101;
1597  }
1598 
1599  return i_ReturnValue;
1600 }
1601 
1602 /*
1603 +----------------------------------------------------------------------------+
1604 | Function Name : int i_APCI3XXX_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+
1605 | Task :resets all the registers |
1606 +----------------------------------------------------------------------------+
1607 | Input Parameters : struct comedi_device *dev |
1608 +----------------------------------------------------------------------------+
1609 | Output Parameters : - |
1610 +----------------------------------------------------------------------------+
1611 | Return Value : - |
1612 +----------------------------------------------------------------------------+
1613 */
1614 
1615 static int i_APCI3XXX_Reset(struct comedi_device *dev)
1616 {
1617  unsigned char b_Cpt = 0;
1618 
1619  /*************************/
1620  /* Disable the interrupt */
1621  /*************************/
1622 
1623  disable_irq(dev->irq);
1624 
1625  /****************************/
1626  /* Reset the interrupt flag */
1627  /****************************/
1628 
1629  devpriv->b_EocEosInterrupt = 0;
1630 
1631  /***************************/
1632  /* Clear the start command */
1633  /***************************/
1634 
1635  writel(0, devpriv->dw_AiBase + 8);
1636 
1637  /*****************************/
1638  /* Reset the interrupt flags */
1639  /*****************************/
1640 
1641  writel(readl(devpriv->dw_AiBase + 16), devpriv->dw_AiBase + 16);
1642 
1643  /*****************/
1644  /* clear the EOS */
1645  /*****************/
1646 
1647  readl(devpriv->dw_AiBase + 20);
1648 
1649  /******************/
1650  /* Clear the FIFO */
1651  /******************/
1652 
1653  for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
1654  readl(devpriv->dw_AiBase + 28);
1655  }
1656 
1657  /************************/
1658  /* Enable the interrupt */
1659  /************************/
1660 
1661  enable_irq(dev->irq);
1662 
1663  return 0;
1664 }