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