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