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