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