packaging: release out (3.8.3)
[profile/ivi/kernel-adaptation-intel-automotive.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci3xxx.c
1 /**
2 @verbatim
3
4 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5
6         ADDI-DATA GmbH
7         Dieselstrasse 3
8         D-77833 Ottersweier
9         Tel: +19(0)7223/9493-0
10         Fax: +49(0)7223/9493-92
11         http://www.addi-data.com
12         info@addi-data.com
13
14 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 You should also find the complete GPL in the COPYING file accompanying this source code.
21
22 @endverbatim
23 */
24 /*
25   +-----------------------------------------------------------------------+
26   | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
27   +-----------------------------------------------------------------------+
28   | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
29   | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
30   +-----------------------------------------------------------------------+
31   | Project     : APCI-3XXX       | Compiler   : GCC                      |
32   | Module name : hwdrv_apci3xxx.c| Version    : 2.96                     |
33   +-------------------------------+---------------------------------------+
34   | Project manager: S. Weber     | Date       :  15/09/2005              |
35   +-----------------------------------------------------------------------+
36   | Description :APCI3XXX Module.  Hardware abstraction Layer for APCI3XXX|
37   +-----------------------------------------------------------------------+
38   |                             UPDATE'S                                  |
39   +-----------------------------------------------------------------------+
40   |   Date   |   Author  |          Description of updates                |
41   +----------+-----------+------------------------------------------------+
42   |          |           |                                                |
43   |          |           |                                                |
44   +----------+-----------+------------------------------------------------+
45 */
46
47 #ifndef COMEDI_SUBD_TTLIO
48 #define COMEDI_SUBD_TTLIO       11      /* Digital Input Output But TTL */
49 #endif
50
51 #define APCI3XXX_SINGLE                         0
52 #define APCI3XXX_DIFF                           1
53 #define APCI3XXX_CONFIGURATION                  0
54
55 #define APCI3XXX_TTL_INIT_DIRECTION_PORT2       0
56
57 static const struct comedi_lrange range_apci3XXX_ai = {
58         8, {
59                 BIP_RANGE(10),
60                 BIP_RANGE(5),
61                 BIP_RANGE(2),
62                 BIP_RANGE(1),
63                 UNI_RANGE(10),
64                 UNI_RANGE(5),
65                 UNI_RANGE(2),
66                 UNI_RANGE(1)
67         }
68 };
69
70 static const struct comedi_lrange range_apci3XXX_ao = {
71         2, {
72                 BIP_RANGE(10),
73                 UNI_RANGE(10)
74         }
75 };
76
77 /*
78 +----------------------------------------------------------------------------+
79 |                         ANALOG INPUT FUNCTIONS                             |
80 +----------------------------------------------------------------------------+
81 */
82
83 /*
84 +----------------------------------------------------------------------------+
85 | Function Name     : int   i_APCI3XXX_TestConversionStarted                 |
86 |                          (struct comedi_device    *dev)                           |
87 +----------------------------------------------------------------------------+
88 | Task                Test if any conversion started                         |
89 +----------------------------------------------------------------------------+
90 | Input Parameters  : -                                                      |
91 +----------------------------------------------------------------------------+
92 | Output Parameters : -                                                      |
93 +----------------------------------------------------------------------------+
94 | Return Value      : 0 : Conversion not started                             |
95 |                     1 : Conversion started                                 |
96 +----------------------------------------------------------------------------+
97 */
98 static int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
99 {
100         struct addi_private *devpriv = dev->private;
101
102         if ((readl(devpriv->dw_AiBase + 8) & 0x80000UL) == 0x80000UL)
103                 return 1;
104         else
105                 return 0;
106
107 }
108
109 /*
110 +----------------------------------------------------------------------------+
111 | Function Name     : int   i_APCI3XXX_AnalogInputConfigOperatingMode        |
112 |                          (struct comedi_device    *dev,                           |
113 |                           struct comedi_subdevice *s,                             |
114 |                           struct comedi_insn      *insn,                          |
115 |                           unsigned int         *data)                          |
116 +----------------------------------------------------------------------------+
117 | Task           Converting mode and convert time selection                  |
118 +----------------------------------------------------------------------------+
119 | Input Parameters  : b_SingleDiff  = (unsigned char)  data[1];                       |
120 |                     b_TimeBase    = (unsigned char)  data[2]; (0: ns, 1:micros 2:ms)|
121 |                    dw_ReloadValue = (unsigned int) data[3];                       |
122 |                     ........                                               |
123 +----------------------------------------------------------------------------+
124 | Output Parameters : -                                                      |
125 +----------------------------------------------------------------------------+
126 | Return Value      :>0 : No error                                           |
127 |                    -1 : Single/Diff selection error                        |
128 |                    -2 : Convert time base unity selection error            |
129 |                    -3 : Convert time value selection error                 |
130 |                    -10: Any conversion started                             |
131 |                    ....                                                    |
132 |                    -100 : Config command error                             |
133 |                    -101 : Data size error                                  |
134 +----------------------------------------------------------------------------+
135 */
136 static int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
137                                                      struct comedi_subdevice *s,
138                                                      struct comedi_insn *insn,
139                                                      unsigned int *data)
140 {
141         const struct addi_board *this_board = comedi_board(dev);
142         struct addi_private *devpriv = dev->private;
143         int i_ReturnValue = insn->n;
144         unsigned char b_TimeBase = 0;
145         unsigned char b_SingleDiff = 0;
146         unsigned int dw_ReloadValue = 0;
147         unsigned int dw_TestReloadValue = 0;
148
149         /************************/
150         /* Test the buffer size */
151         /************************/
152
153         if (insn->n == 4) {
154            /****************************/
155                 /* Get the Singel/Diff flag */
156            /****************************/
157
158                 b_SingleDiff = (unsigned char) data[1];
159
160            /****************************/
161                 /* Get the time base unitiy */
162            /****************************/
163
164                 b_TimeBase = (unsigned char) data[2];
165
166            /*************************************/
167                 /* Get the convert time reload value */
168            /*************************************/
169
170                 dw_ReloadValue = (unsigned int) data[3];
171
172            /**********************/
173                 /* Test the time base */
174            /**********************/
175
176                 if ((this_board->b_AvailableConvertUnit & (1 << b_TimeBase)) !=
177                         0) {
178               /*******************************/
179                         /* Test the convert time value */
180               /*******************************/
181
182                         if (dw_ReloadValue <= 65535) {
183                                 dw_TestReloadValue = dw_ReloadValue;
184
185                                 if (b_TimeBase == 1) {
186                                         dw_TestReloadValue =
187                                                 dw_TestReloadValue * 1000UL;
188                                 }
189                                 if (b_TimeBase == 2) {
190                                         dw_TestReloadValue =
191                                                 dw_TestReloadValue * 1000000UL;
192                                 }
193
194                  /*******************************/
195                                 /* Test the convert time value */
196                  /*******************************/
197
198                                 if (dw_TestReloadValue >=
199                                         devpriv->s_EeParameters.
200                                         ui_MinAcquisitiontimeNs) {
201                                         if ((b_SingleDiff == APCI3XXX_SINGLE)
202                                                 || (b_SingleDiff ==
203                                                         APCI3XXX_DIFF)) {
204                                                 if (((b_SingleDiff == APCI3XXX_SINGLE)
205                                                         && (devpriv->s_EeParameters.i_NbrAiChannel == 0))
206                                                     || ((b_SingleDiff == APCI3XXX_DIFF)
207                                                         && (this_board->i_NbrAiChannelDiff == 0))
208                                                     ) {
209                            /*******************************/
210                                                         /* Single/Diff selection error */
211                            /*******************************/
212
213                                                         printk("Single/Diff selection error\n");
214                                                         i_ReturnValue = -1;
215                                                 } else {
216                            /**********************************/
217                                                         /* Test if conversion not started */
218                            /**********************************/
219
220                                                         if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
221                                                                 devpriv->
222                                                                         ui_EocEosConversionTime
223                                                                         =
224                                                                         (unsigned int)
225                                                                         dw_ReloadValue;
226                                                                 devpriv->
227                                                                         b_EocEosConversionTimeBase
228                                                                         =
229                                                                         b_TimeBase;
230                                                                 devpriv->
231                                                                         b_SingelDiff
232                                                                         =
233                                                                         b_SingleDiff;
234                                                                 devpriv->
235                                                                         b_AiInitialisation
236                                                                         = 1;
237
238                               /*******************************/
239                                                                 /* Set the convert timing unit */
240                               /*******************************/
241
242                                                                 writel((unsigned int)b_TimeBase,
243                                                                         devpriv->dw_AiBase + 36);
244
245                               /**************************/
246                                                                 /* Set the convert timing */
247                               /*************************/
248
249                                                                 writel(dw_ReloadValue, devpriv->dw_AiBase + 32);
250                                                         } else {
251                               /**************************/
252                                                                 /* Any conversion started */
253                               /**************************/
254
255                                                                 printk("Any conversion started\n");
256                                                                 i_ReturnValue =
257                                                                         -10;
258                                                         }
259                                                 }
260                                         } else {
261                        /*******************************/
262                                                 /* Single/Diff selection error */
263                        /*******************************/
264
265                                                 printk("Single/Diff selection error\n");
266                                                 i_ReturnValue = -1;
267                                         }
268                                 } else {
269                     /************************/
270                                         /* Time selection error */
271                     /************************/
272
273                                         printk("Convert time value selection error\n");
274                                         i_ReturnValue = -3;
275                                 }
276                         } else {
277                  /************************/
278                                 /* Time selection error */
279                  /************************/
280
281                                 printk("Convert time value selection error\n");
282                                 i_ReturnValue = -3;
283                         }
284                 } else {
285               /*****************************/
286                         /* Time base selection error */
287               /*****************************/
288
289                         printk("Convert time base unity selection error\n");
290                         i_ReturnValue = -2;
291                 }
292         } else {
293            /*******************/
294                 /* Data size error */
295            /*******************/
296
297                 printk("Buffer size error\n");
298                 i_ReturnValue = -101;
299         }
300
301         return i_ReturnValue;
302 }
303
304 /*
305 +----------------------------------------------------------------------------+
306 | Function Name     : int   i_APCI3XXX_InsnConfigAnalogInput                 |
307 |                          (struct comedi_device    *dev,                           |
308 |                           struct comedi_subdevice *s,                             |
309 |                           struct comedi_insn      *insn,                          |
310 |                           unsigned int         *data)                          |
311 +----------------------------------------------------------------------------+
312 | Task           Converting mode and convert time selection                  |
313 +----------------------------------------------------------------------------+
314 | Input Parameters  : b_ConvertMode = (unsigned char)  data[0];                       |
315 |                     b_TimeBase    = (unsigned char)  data[1]; (0: ns, 1:micros 2:ms)|
316 |                    dw_ReloadValue = (unsigned int) data[2];                       |
317 |                     ........                                               |
318 +----------------------------------------------------------------------------+
319 | Output Parameters : -                                                      |
320 +----------------------------------------------------------------------------+
321 | Return Value      :>0: No error                                            |
322 |                    ....                                                    |
323 |                    -100 : Config command error                             |
324 |                    -101 : Data size error                                  |
325 +----------------------------------------------------------------------------+
326 */
327 static int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
328                                             struct comedi_subdevice *s,
329                                             struct comedi_insn *insn,
330                                             unsigned int *data)
331 {
332         int i_ReturnValue = insn->n;
333
334         /************************/
335         /* Test the buffer size */
336         /************************/
337
338         if (insn->n >= 1) {
339                 switch ((unsigned char) data[0]) {
340                 case APCI3XXX_CONFIGURATION:
341                         i_ReturnValue =
342                                 i_APCI3XXX_AnalogInputConfigOperatingMode(dev,
343                                 s, insn, data);
344                         break;
345
346                 default:
347                         i_ReturnValue = -100;
348                         printk("Config command error %d\n", data[0]);
349                         break;
350                 }
351         } else {
352            /*******************/
353                 /* Data size error */
354            /*******************/
355
356                 printk("Buffer size error\n");
357                 i_ReturnValue = -101;
358         }
359
360         return i_ReturnValue;
361 }
362
363 /*
364 +----------------------------------------------------------------------------+
365 | Function Name     : int   i_APCI3XXX_InsnReadAnalogInput                   |
366 |                          (struct comedi_device    *dev,                           |
367 |                           struct comedi_subdevice *s,                             |
368 |                           struct comedi_insn      *insn,                          |
369 |                           unsigned int         *data)                          |
370 +----------------------------------------------------------------------------+
371 | Task                Read 1 analog input                                    |
372 +----------------------------------------------------------------------------+
373 | Input Parameters  : b_Range             = CR_RANGE(insn->chanspec);        |
374 |                     b_Channel           = CR_CHAN(insn->chanspec);         |
375 |                     dw_NbrOfAcquisition = insn->n;                         |
376 +----------------------------------------------------------------------------+
377 | Output Parameters : -                                                      |
378 +----------------------------------------------------------------------------+
379 | Return Value      :>0: No error                                            |
380 |                    -3 : Channel selection error                            |
381 |                    -4 : Configuration selelection error                    |
382 |                    -10: Any conversion started                             |
383 |                    ....                                                    |
384 |                    -100 : Config command error                             |
385 |                    -101 : Data size error                                  |
386 +----------------------------------------------------------------------------+
387 */
388 static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
389                                           struct comedi_subdevice *s,
390                                           struct comedi_insn *insn,
391                                           unsigned int *data)
392 {
393         const struct addi_board *this_board = comedi_board(dev);
394         struct addi_private *devpriv = dev->private;
395         int i_ReturnValue = insn->n;
396         unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
397         unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
398         unsigned int dw_Temp = 0;
399         unsigned int dw_Configuration = 0;
400         unsigned int dw_AcquisitionCpt = 0;
401         unsigned char b_Interrupt = 0;
402
403         /*************************************/
404         /* Test if operating mode configured */
405         /*************************************/
406
407         if (devpriv->b_AiInitialisation) {
408            /***************************/
409                 /* Test the channel number */
410            /***************************/
411
412                 if (((b_Channel < devpriv->s_EeParameters.i_NbrAiChannel)
413                                 && (devpriv->b_SingelDiff == APCI3XXX_SINGLE))
414                         || ((b_Channel < this_board->i_NbrAiChannelDiff)
415                                 && (devpriv->b_SingelDiff == APCI3XXX_DIFF))) {
416               /**********************************/
417                         /* Test the channel configuration */
418               /**********************************/
419
420                         if (b_Configuration > 7) {
421                  /***************************/
422                                 /* Channel not initialised */
423                  /***************************/
424
425                                 i_ReturnValue = -4;
426                                 printk("Channel %d range %d selection error\n",
427                                         b_Channel, b_Configuration);
428                         }
429                 } else {
430               /***************************/
431                         /* Channel selection error */
432               /***************************/
433
434                         i_ReturnValue = -3;
435                         printk("Channel %d selection error\n", b_Channel);
436                 }
437
438            /**************************/
439                 /* Test if no error occur */
440            /**************************/
441
442                 if (i_ReturnValue >= 0) {
443               /************************/
444                         /* Test the buffer size */
445               /************************/
446
447                         if ((b_Interrupt != 0) || ((b_Interrupt == 0)
448                                         && (insn->n >= 1))) {
449                  /**********************************/
450                                 /* Test if conversion not started */
451                  /**********************************/
452
453                                 if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
454                     /******************/
455                                         /* Clear the FIFO */
456                     /******************/
457
458                                         writel(0x10000UL, devpriv->dw_AiBase + 12);
459
460                     /*******************************/
461                                         /* Get and save the delay mode */
462                     /*******************************/
463
464                                         dw_Temp = readl(devpriv->dw_AiBase + 4);
465                                         dw_Temp = dw_Temp & 0xFFFFFEF0UL;
466
467                     /***********************************/
468                                         /* Channel configuration selection */
469                     /***********************************/
470
471                                         writel(dw_Temp, devpriv->dw_AiBase + 4);
472
473                     /**************************/
474                                         /* Make the configuration */
475                     /**************************/
476
477                                         dw_Configuration =
478                                                 (b_Configuration & 3) |
479                                                 ((unsigned int) (b_Configuration >> 2)
480                                                 << 6) | ((unsigned int) devpriv->
481                                                 b_SingelDiff << 7);
482
483                     /***************************/
484                                         /* Write the configuration */
485                     /***************************/
486
487                                         writel(dw_Configuration,
488                                                devpriv->dw_AiBase + 0);
489
490                     /*********************/
491                                         /* Channel selection */
492                     /*********************/
493
494                                         writel(dw_Temp | 0x100UL,
495                                                devpriv->dw_AiBase + 4);
496                                         writel((unsigned int) b_Channel,
497                                                devpriv->dw_AiBase + 0);
498
499                     /***********************/
500                                         /* Restaure delay mode */
501                     /***********************/
502
503                                         writel(dw_Temp, devpriv->dw_AiBase + 4);
504
505                     /***********************************/
506                                         /* Set the number of sequence to 1 */
507                     /***********************************/
508
509                                         writel(1, devpriv->dw_AiBase + 48);
510
511                     /***************************/
512                                         /* Save the interrupt flag */
513                     /***************************/
514
515                                         devpriv->b_EocEosInterrupt =
516                                                 b_Interrupt;
517
518                     /*******************************/
519                                         /* Save the number of channels */
520                     /*******************************/
521
522                                         devpriv->ui_AiNbrofChannels = 1;
523
524                     /******************************/
525                                         /* Test if interrupt not used */
526                     /******************************/
527
528                                         if (b_Interrupt == 0) {
529                                                 for (dw_AcquisitionCpt = 0;
530                                                         dw_AcquisitionCpt <
531                                                         insn->n;
532                                                         dw_AcquisitionCpt++) {
533                           /************************/
534                                                         /* Start the conversion */
535                           /************************/
536
537                                                         writel(0x80000UL, devpriv->dw_AiBase + 8);
538
539                           /****************/
540                                                         /* Wait the EOS */
541                           /****************/
542
543                                                         do {
544                                                                 dw_Temp = readl(devpriv->dw_AiBase + 20);
545                                                                 dw_Temp = dw_Temp & 1;
546                                                         } while (dw_Temp != 1);
547
548                           /*************************/
549                                                         /* Read the analog value */
550                           /*************************/
551
552                                                         data[dw_AcquisitionCpt] = (unsigned int)readl(devpriv->dw_AiBase + 28);
553                                                 }
554                                         } else {
555                        /************************/
556                                                 /* Start the conversion */
557                        /************************/
558
559                                                 writel(0x180000UL, devpriv->dw_AiBase + 8);
560                                         }
561                                 } else {
562                     /**************************/
563                                         /* Any conversion started */
564                     /**************************/
565
566                                         printk("Any conversion started\n");
567                                         i_ReturnValue = -10;
568                                 }
569                         } else {
570                  /*******************/
571                                 /* Data size error */
572                  /*******************/
573
574                                 printk("Buffer size error\n");
575                                 i_ReturnValue = -101;
576                         }
577                 }
578         } else {
579            /***************************/
580                 /* Channel selection error */
581            /***************************/
582
583                 printk("Operating mode not configured\n");
584                 i_ReturnValue = -1;
585         }
586         return i_ReturnValue;
587 }
588
589 /*
590 +----------------------------------------------------------------------------+
591 | Function name     : void v_APCI3XXX_Interrupt (int            irq,         |
592 |                                                void           *d)       |
593 +----------------------------------------------------------------------------+
594 | Task              :Interrupt handler for APCI3XXX                          |
595 |                    When interrupt occurs this gets called.                 |
596 |                    First it finds which interrupt has been generated and   |
597 |                    handles  corresponding interrupt                        |
598 +----------------------------------------------------------------------------+
599 | Input Parameters  : -                                                      |
600 +----------------------------------------------------------------------------+
601 | Return Value      : -                                                      |
602 +----------------------------------------------------------------------------+
603 */
604
605 static void v_APCI3XXX_Interrupt(int irq, void *d)
606 {
607         struct comedi_device *dev = d;
608         struct addi_private *devpriv = dev->private;
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(devpriv->dw_AiBase + 16);
617         if ( (dw_Status & 0x2UL) == 0x2UL) {
618            /***********************/
619                 /* Reset the interrupt */
620            /***********************/
621
622                 writel(dw_Status, 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(devpriv->dw_AiBase + 28);
638                         }
639
640               /**************************/
641                         /* Set the interrupt flag */
642               /**************************/
643
644                         devpriv->b_EocEosInterrupt = 2;
645
646               /**********************************************/
647                         /* Send a signal to from kernel to user space */
648               /**********************************************/
649
650                         send_sig(SIGIO, devpriv->tsk_Current, 0);
651                 }
652         }
653 }
654
655 /*
656 +----------------------------------------------------------------------------+
657 |                            ANALOG OUTPUT SUBDEVICE                         |
658 +----------------------------------------------------------------------------+
659 */
660
661 /*
662 +----------------------------------------------------------------------------+
663 | Function Name     : int   i_APCI3XXX_InsnWriteAnalogOutput                 |
664 |                          (struct comedi_device    *dev,                           |
665 |                           struct comedi_subdevice *s,                             |
666 |                           struct comedi_insn      *insn,                          |
667 |                           unsigned int         *data)                          |
668 +----------------------------------------------------------------------------+
669 | Task                Read 1 analog input                                    |
670 +----------------------------------------------------------------------------+
671 | Input Parameters  : b_Range    = CR_RANGE(insn->chanspec);                 |
672 |                     b_Channel  = CR_CHAN(insn->chanspec);                  |
673 |                     data[0]    = analog value;                             |
674 +----------------------------------------------------------------------------+
675 | Output Parameters : -                                                      |
676 +----------------------------------------------------------------------------+
677 | Return Value      :>0: No error                                            |
678 |                    -3 : Channel selection error                            |
679 |                    -4 : Configuration selelection error                    |
680 |                    ....                                                    |
681 |                    -101 : Data size error                                  |
682 +----------------------------------------------------------------------------+
683 */
684 static int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
685                                             struct comedi_subdevice *s,
686                                             struct comedi_insn *insn,
687                                             unsigned int *data)
688 {
689         struct addi_private *devpriv = dev->private;
690         unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
691         unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
692         unsigned int 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->s_EeParameters.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, 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                                         devpriv->dw_AiBase + 100);
722
723                  /****************************/
724                                 /* Wait the end of transfer */
725                  /****************************/
726
727                                 do {
728                                         dw_Status = readl(devpriv->dw_AiBase + 96);
729                                 } while ((dw_Status & 0x100) != 0x100);
730                         } else {
731                  /***************************/
732                                 /* Channel not initialised */
733                  /***************************/
734
735                                 i_ReturnValue = -4;
736                                 printk("Channel %d range %d selection error\n",
737                                         b_Channel, b_Range);
738                         }
739                 } else {
740               /***************************/
741                         /* Channel selection error */
742               /***************************/
743
744                         i_ReturnValue = -3;
745                         printk("Channel %d selection error\n", b_Channel);
746                 }
747         } else {
748            /*******************/
749                 /* Data size error */
750            /*******************/
751
752                 printk("Buffer size error\n");
753                 i_ReturnValue = -101;
754         }
755
756         return i_ReturnValue;
757 }
758
759 /*
760 +----------------------------------------------------------------------------+
761 |                              TTL FUNCTIONS                                 |
762 +----------------------------------------------------------------------------+
763 */
764
765 /*
766 +----------------------------------------------------------------------------+
767 | Function Name     : int   i_APCI3XXX_InsnConfigInitTTLIO                   |
768 |                          (struct comedi_device    *dev,                           |
769 |                           struct comedi_subdevice *s,                             |
770 |                           struct comedi_insn      *insn,                          |
771 |                           unsigned int         *data)                          |
772 +----------------------------------------------------------------------------+
773 | Task           You must calling this function be                           |
774 |                for you call any other function witch access of TTL.        |
775 |                APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
776 +----------------------------------------------------------------------------+
777 | Input Parameters  : b_InitType    = (unsigned char) data[0];                        |
778 |                     b_Port2Mode   = (unsigned char) data[1];                        |
779 +----------------------------------------------------------------------------+
780 | Output Parameters : -                                                      |
781 +----------------------------------------------------------------------------+
782 | Return Value      :>0: No error                                            |
783 |                    -1: Port 2 mode selection is wrong                      |
784 |                    ....                                                    |
785 |                    -100 : Config command error                             |
786 |                    -101 : Data size error                                  |
787 +----------------------------------------------------------------------------+
788 */
789 static int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
790                                           struct comedi_subdevice *s,
791                                           struct comedi_insn *insn,
792                                           unsigned int *data)
793 {
794         struct addi_private *devpriv = dev->private;
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 static int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
920                                     struct comedi_subdevice *s,
921                                     struct comedi_insn *insn,
922                                     unsigned int *data)
923 {
924         struct addi_private *devpriv = dev->private;
925         int i_ReturnValue = insn->n;
926         unsigned char b_ChannelCpt = 0;
927         unsigned int dw_ChannelMask = 0;
928         unsigned int dw_BitMask = 0;
929         unsigned int 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 |                          (struct comedi_device    *dev,                           |
1061 |                           struct comedi_subdevice *s,                             |
1062 |                           struct comedi_insn      *insn,                          |
1063 |                           unsigned int         *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 static int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
1077                                     struct comedi_subdevice *s,
1078                                     struct comedi_insn *insn,
1079                                     unsigned int *data)
1080 {
1081         struct addi_private *devpriv = dev->private;
1082         unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1083         int i_ReturnValue = insn->n;
1084         unsigned int *pls_ReadData = data;
1085
1086         /************************/
1087         /* Test the buffer size */
1088         /************************/
1089
1090         if (insn->n >= 1) {
1091            /***********************/
1092                 /* Test if read port 0 */
1093            /***********************/
1094
1095                 if (b_Channel < 8) {
1096               /*******************************************/
1097                         /* Read port 0 (first digital output port) */
1098               /*******************************************/
1099
1100                         pls_ReadData[0] = inl(devpriv->iobase + 80);
1101                         pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1;
1102                 } else {
1103               /***********************/
1104                         /* Test if read port 1 */
1105               /***********************/
1106
1107                         if ((b_Channel > 7) && (b_Channel < 16)) {
1108                  /******************************************/
1109                                 /* Read port 1 (first digital input port) */
1110                  /******************************************/
1111
1112                                 pls_ReadData[0] = inl(devpriv->iobase + 64);
1113                                 pls_ReadData[0] =
1114                                         (pls_ReadData[0] >> (b_Channel -
1115                                                 8)) & 1;
1116                         } else {
1117                  /***********************/
1118                                 /* Test if read port 2 */
1119                  /***********************/
1120
1121                                 if ((b_Channel > 15) && (b_Channel < 24)) {
1122                     /************************/
1123                                         /* Test if port 2 input */
1124                     /************************/
1125
1126                                         if ((devpriv->ul_TTLPortConfiguration[0]
1127                                                         & 0xFF) == 0) {
1128                                                 pls_ReadData[0] =
1129                                                         inl(devpriv->iobase +
1130                                                         96);
1131                                                 pls_ReadData[0] =
1132                                                         (pls_ReadData[0] >>
1133                                                         (b_Channel - 16)) & 1;
1134                                         } else {
1135                                                 pls_ReadData[0] =
1136                                                         inl(devpriv->iobase +
1137                                                         112);
1138                                                 pls_ReadData[0] =
1139                                                         (pls_ReadData[0] >>
1140                                                         (b_Channel - 16)) & 1;
1141                                         }
1142                                 } else {
1143                     /***************************/
1144                                         /* Channel selection error */
1145                     /***************************/
1146
1147                                         i_ReturnValue = -3;
1148                                         printk("Channel %d selection error\n",
1149                                                 b_Channel);
1150                                 }
1151                         }
1152                 }
1153         } else {
1154            /*******************/
1155                 /* Data size error */
1156            /*******************/
1157
1158                 printk("Buffer size error\n");
1159                 i_ReturnValue = -101;
1160         }
1161
1162         return i_ReturnValue;
1163 }
1164
1165 /*
1166 +----------------------------------------------------------------------------+
1167 |                        TTL OUTPUT FUNCTIONS                                |
1168 +----------------------------------------------------------------------------+
1169 */
1170
1171 /*
1172 +----------------------------------------------------------------------------+
1173 | Function Name     : int     i_APCI3XXX_InsnWriteTTLIO                      |
1174 |                          (struct comedi_device    *dev,                           |
1175 |                           struct comedi_subdevice *s,                             |
1176 |                           struct comedi_insn      *insn,                          |
1177 |                           unsigned int         *data)                          |
1178 +----------------------------------------------------------------------------+
1179 | Task              : Set the state from TTL output channel                  |
1180 +----------------------------------------------------------------------------+
1181 | Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1182 |                     b_State   = data [0]                                   |
1183 +----------------------------------------------------------------------------+
1184 | Output Parameters : -                                                      |
1185 +----------------------------------------------------------------------------+
1186 | Return Value      : 0   : No error                                         |
1187 |                    -3   : Channel selection error                          |
1188 |                    -101 : Data size error                                  |
1189 +----------------------------------------------------------------------------+
1190 */
1191 static int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
1192                                      struct comedi_subdevice *s,
1193                                      struct comedi_insn *insn,
1194                                      unsigned int *data)
1195 {
1196         struct addi_private *devpriv = dev->private;
1197         int i_ReturnValue = insn->n;
1198         unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1199         unsigned char b_State = 0;
1200         unsigned int dw_Status = 0;
1201
1202         /************************/
1203         /* Test the buffer size */
1204         /************************/
1205
1206         if (insn->n >= 1) {
1207                 b_State = (unsigned char) data[0];
1208
1209            /***********************/
1210                 /* Test if read port 0 */
1211            /***********************/
1212
1213                 if (b_Channel < 8) {
1214               /*****************************************************************************/
1215                         /* Read port 0 (first digital output port) and set/reset the selected channel */
1216               /*****************************************************************************/
1217
1218                         dw_Status = inl(devpriv->iobase + 80);
1219                         dw_Status =
1220                                 (dw_Status & (0xFF -
1221                                         (1 << b_Channel))) | ((b_State & 1) <<
1222                                 b_Channel);
1223                         outl(dw_Status, devpriv->iobase + 80);
1224                 } else {
1225               /***********************/
1226                         /* Test if read port 2 */
1227               /***********************/
1228
1229                         if ((b_Channel > 15) && (b_Channel < 24)) {
1230                  /*************************/
1231                                 /* Test if port 2 output */
1232                  /*************************/
1233
1234                                 if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
1235                                         == 0xFF) {
1236                     /*****************************************************************************/
1237                                         /* Read port 2 (first digital output port) and set/reset the selected channel */
1238                     /*****************************************************************************/
1239
1240                                         dw_Status = inl(devpriv->iobase + 112);
1241                                         dw_Status =
1242                                                 (dw_Status & (0xFF -
1243                                                         (1 << (b_Channel -
1244                                                                         16)))) |
1245                                                 ((b_State & 1) << (b_Channel -
1246                                                         16));
1247                                         outl(dw_Status, devpriv->iobase + 112);
1248                                 } else {
1249                     /***************************/
1250                                         /* Channel selection error */
1251                     /***************************/
1252
1253                                         i_ReturnValue = -3;
1254                                         printk("Channel %d selection error\n",
1255                                                 b_Channel);
1256                                 }
1257                         } else {
1258                  /***************************/
1259                                 /* Channel selection error */
1260                  /***************************/
1261
1262                                 i_ReturnValue = -3;
1263                                 printk("Channel %d selection error\n",
1264                                         b_Channel);
1265                         }
1266                 }
1267         } else {
1268            /*******************/
1269                 /* Data size error */
1270            /*******************/
1271
1272                 printk("Buffer size error\n");
1273                 i_ReturnValue = -101;
1274         }
1275
1276         return i_ReturnValue;
1277 }
1278
1279 static int apci3xxx_di_insn_bits(struct comedi_device *dev,
1280                                  struct comedi_subdevice *s,
1281                                  struct comedi_insn *insn,
1282                                  unsigned int *data)
1283 {
1284         struct addi_private *devpriv = dev->private;
1285
1286         data[1] = inl(devpriv->iobase + 32) & 0xf;
1287
1288         return insn->n;
1289 }
1290
1291 static int apci3xxx_do_insn_bits(struct comedi_device *dev,
1292                                  struct comedi_subdevice *s,
1293                                  struct comedi_insn *insn,
1294                                  unsigned int *data)
1295 {
1296         struct addi_private *devpriv = dev->private;
1297         unsigned int mask = data[0];
1298         unsigned int bits = data[1];
1299
1300         s->state = inl(devpriv->iobase + 48) & 0xf;
1301         if (mask) {
1302                 s->state &= ~mask;
1303                 s->state |= (bits & mask);
1304
1305                 outl(s->state, devpriv->iobase + 48);
1306         }
1307
1308         data[1] = s->state;
1309
1310         return insn->n;
1311 }
1312
1313 /*
1314 +----------------------------------------------------------------------------+
1315 | Function   Name   : int i_APCI3XXX_Reset(struct comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
1316 | Task              :resets all the registers                                |
1317 +----------------------------------------------------------------------------+
1318 | Input Parameters  : struct comedi_device *dev                                     |
1319 +----------------------------------------------------------------------------+
1320 | Output Parameters : -                                                      |
1321 +----------------------------------------------------------------------------+
1322 | Return Value      : -                                                      |
1323 +----------------------------------------------------------------------------+
1324 */
1325
1326 static int i_APCI3XXX_Reset(struct comedi_device *dev)
1327 {
1328         struct addi_private *devpriv = dev->private;
1329         unsigned char b_Cpt = 0;
1330
1331         /*************************/
1332         /* Disable the interrupt */
1333         /*************************/
1334
1335         disable_irq(dev->irq);
1336
1337         /****************************/
1338         /* Reset the interrupt flag */
1339         /****************************/
1340
1341         devpriv->b_EocEosInterrupt = 0;
1342
1343         /***************************/
1344         /* Clear the start command */
1345         /***************************/
1346
1347         writel(0, devpriv->dw_AiBase + 8);
1348
1349         /*****************************/
1350         /* Reset the interrupt flags */
1351         /*****************************/
1352
1353         writel(readl(devpriv->dw_AiBase + 16), devpriv->dw_AiBase + 16);
1354
1355         /*****************/
1356         /* clear the EOS */
1357         /*****************/
1358
1359         readl(devpriv->dw_AiBase + 20);
1360
1361         /******************/
1362         /* Clear the FIFO */
1363         /******************/
1364
1365         for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
1366                 readl(devpriv->dw_AiBase + 28);
1367         }
1368
1369         /************************/
1370         /* Enable the interrupt */
1371         /************************/
1372
1373         enable_irq(dev->irq);
1374
1375         return 0;
1376 }