staging: comedi: addi-data: Get rid of redundant ps_BoardInfo
[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 ((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]) {
308                 case APCI3XXX_CONFIGURATION:
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 }