Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.git] / drivers / staging / comedi / drivers / addi-data / APCI1710_Chrono.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   +-----------------------------------------------------------------------+
27   | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
28   +-----------------------------------------------------------------------+
29   | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
30   | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
31   +-----------------------------------------------------------------------+
32   | Project     : API APCI1710    | Compiler : gcc                        |
33   | Module name : CHRONO.C        | Version  : 2.96                       |
34   +-------------------------------+---------------------------------------+
35   | Project manager: Eric Stolz   | Date     :  02/12/2002                |
36   +-----------------------------------------------------------------------+
37   | Description :   APCI-1710 chronometer module                          |
38   |                                                                       |
39   |                                                                       |
40   +-----------------------------------------------------------------------+
41   |                             UPDATES                                   |
42   +-----------------------------------------------------------------------+
43   |   Date   |   Author  |          Description of updates                |
44   +----------+-----------+------------------------------------------------+
45   | 29/06/98 | S. Weber  | Digital input / output implementation          |
46   |----------|-----------|------------------------------------------------|
47   | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
48   |          |           |   available                                    |
49   +-----------------------------------------------------------------------+
50   |          |           |                                                |
51   |          |           |                                                |
52   +-----------------------------------------------------------------------+
53 */
54
55 /*
56 +----------------------------------------------------------------------------+
57 |                               Included files                               |
58 +----------------------------------------------------------------------------+
59 */
60 #include "APCI1710_Chrono.h"
61
62 /*
63 +----------------------------------------------------------------------------+
64 | Function Name     : _INT_     i_APCI1710_InitChrono                        |
65 |                                       (unsigned char_     b_BoardHandle,            |
66 |                                        unsigned char_     b_ModulNbr,               |
67 |                                        unsigned char_     b_ChronoMode,             |
68 |                                        unsigned char_     b_PCIInputClock,          |
69 |                                        unsigned char_     b_TimingUnit,             |
70 |                                        ULONG_   ul_TimingInterval,         |
71 |                                        PULONG_ pul_RealTimingInterval)
72
73 +----------------------------------------------------------------------------+
74 | Task              : Configure the chronometer operating mode (b_ChronoMode)|
75 |                     from selected module (b_ModulNbr).                     |
76 |                     The ul_TimingInterval and ul_TimingUnit determine the  |
77 |                     timing base for the measurement.                       |
78 |                     The pul_RealTimingInterval return the real timing      |
79 |                     value. You must calling this function be for you call  |
80 |                     any other function witch access of the chronometer.    |
81 |                                                                            |
82 |                     Witch this functionality from the APCI-1710 you have   |
83 |                     the possibility to measure the timing witch two event. |
84 |                                                                            |
85 |                     The mode 0 and 1 is appropriate for period measurement.|
86 |                     The mode 2 and 3 is appropriate for frequent           |
87 |                     measurement.                                           |
88 |                     The mode 4 to 7 is appropriate for measuring the timing|
89 |                     between  two event.                                    |
90 +----------------------------------------------------------------------------+
91 | Input Parameters  : unsigned char_   b_BoardHandle    : Handle of board APCI-1710   |
92 | unsigned char_   b_ModulNbr  CR_AREF(insn->chanspec)  : Module number to configure  |
93 |                                                (0 to 3)                    |
94 | unsigned char_   b_ChronoMode                         data[0]    : Chronometer action mode     |
95 |                                                (0 to 7).                   |
96 | unsigned char_   b_PCIInputClock                      data[1] : Selection from PCI bus clock|
97 |                                                - APCI1710_30MHZ :          |
98 |                                                  The PC have a PCI bus     |
99 |                                                  clock from 30 MHz         |
100 |                                                - APCI1710_33MHZ :          |
101 |                                                  The PC have a PCI bus     |
102 |                                                  clock from 33 MHz         |
103 |                                                - APCI1710_40MHZ            |
104 |                                                  The APCI-1710 have a      |
105 |                                                  integrated 40Mhz          |
106 |                                                  quartz.                   |
107 |               unsigned char_   b_TimingUnit   data[2]    : Base timing unity (0 to 4) |
108 |                                                 0 : ns                     |
109 |                                                 1 : µs                     |
110 |                                                 2 : ms                     |
111 |                                                 3 : s                      |
112 |                                                 4 : mn                     |
113 |         ULONG_ ul_TimingInterval : data[3]     Base timing value.          |
114 +----------------------------------------------------------------------------+
115 | Output Parameters : PULONG_  pul_RealTimingInterval : Real  base timing    |
116 |                                                       value.
117 |                     data[0]
118 +----------------------------------------------------------------------------+
119 | Return Value      :  0: No error                                           |
120 |                     -1: The handle parameter of the board is wrong         |
121 |                     -2: Module selection wrong                             |
122 |                     -3: The module is not a Chronometer module             |
123 |                     -4: Chronometer mode selection is wrong                |
124 |                     -5: The selected PCI input clock is wrong              |
125 |                     -6: Timing unity selection is wrong                    |
126 |                     -7: Base timing selection is wrong                     |
127 |                     -8: You can not used the 40MHz clock selection wich    |
128 |                         this board                                         |
129 |                     -9: You can not used the 40MHz clock selection wich    |
130 |                         this CHRONOS version                               |
131 +----------------------------------------------------------------------------+
132 */
133
134 int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
135         struct comedi_insn *insn, unsigned int *data)
136 {
137         int i_ReturnValue = 0;
138         unsigned int ul_TimerValue = 0;
139         unsigned int ul_TimingInterval = 0;
140         unsigned int ul_RealTimingInterval = 0;
141         double d_RealTimingInterval = 0;
142         unsigned int dw_ModeArray[8] =
143                 { 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 };
144         unsigned char b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit;
145
146         b_ModulNbr = CR_AREF(insn->chanspec);
147         b_ChronoMode = (unsigned char) data[0];
148         b_PCIInputClock = (unsigned char) data[1];
149         b_TimingUnit = (unsigned char) data[2];
150         ul_TimingInterval = (unsigned int) data[3];
151         i_ReturnValue = insn->n;
152
153         /**************************/
154         /* Test the module number */
155         /**************************/
156
157         if (b_ModulNbr < 4) {
158            /***********************/
159                 /* Test if chronometer */
160            /***********************/
161
162                 if ((devpriv->s_BoardInfos.
163                                 dw_MolduleConfiguration[b_ModulNbr] &
164                                 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
165               /*****************************/
166                         /* Test the chronometer mode */
167               /*****************************/
168
169                         if (b_ChronoMode <= 7) {
170                  /**************************/
171                                 /* Test the PCI bus clock */
172                  /**************************/
173
174                                 if ((b_PCIInputClock == APCI1710_30MHZ) ||
175                                         (b_PCIInputClock == APCI1710_33MHZ) ||
176                                         (b_PCIInputClock == APCI1710_40MHZ)) {
177                     /*************************/
178                                         /* Test the timing unity */
179                     /*************************/
180
181                                         if (b_TimingUnit <= 4) {
182                        /**********************************/
183                                                 /* Test the base timing selection */
184                        /**********************************/
185
186                                                 if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 66) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165576UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 60) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150240UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 50) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374182UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 1UL))) {
187                           /**************************/
188                                                         /* Test the board version */
189                           /**************************/
190
191                                                         if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) {
192                              /************************/
193                                                                 /* Test the TOR version */
194                              /************************/
195
196                                                                 if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || (b_PCIInputClock != APCI1710_40MHZ)) {
197                                                                         fpu_begin
198                                                                                 ();
199
200                                 /****************************************/
201                                                                         /* Calculate the timer 0 division fator */
202                                 /****************************************/
203
204                                                                         switch (b_TimingUnit) {
205                                    /******/
206                                                                                 /* ns */
207                                    /******/
208
209                                                                         case 0:
210
211                                            /******************/
212                                                                                 /* Timer 0 factor */
213                                            /******************/
214
215                                                                                 ul_TimerValue
216                                                                                         =
217                                                                                         (unsigned int)
218                                                                                         (ul_TimingInterval
219                                                                                         *
220                                                                                         (0.001 * b_PCIInputClock));
221
222                                            /*******************/
223                                                                                 /* Round the value */
224                                            /*******************/
225
226                                                                                 if ((double)((double)ul_TimingInterval * (0.001 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
227                                                                                         ul_TimerValue
228                                                                                                 =
229                                                                                                 ul_TimerValue
230                                                                                                 +
231                                                                                                 1;
232                                                                                 }
233
234                                            /*****************************/
235                                                                                 /* Calculate the real timing */
236                                            /*****************************/
237
238                                                                                 ul_RealTimingInterval
239                                                                                         =
240                                                                                         (unsigned int)
241                                                                                         (ul_TimerValue
242                                                                                         /
243                                                                                         (0.001 * (double)b_PCIInputClock));
244                                                                                 d_RealTimingInterval
245                                                                                         =
246                                                                                         (double)
247                                                                                         ul_TimerValue
248                                                                                         /
249                                                                                         (0.001
250                                                                                         *
251                                                                                         (double)
252                                                                                         b_PCIInputClock);
253
254                                                                                 if ((double)((double)ul_TimerValue / (0.001 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
255                                                                                         ul_RealTimingInterval
256                                                                                                 =
257                                                                                                 ul_RealTimingInterval
258                                                                                                 +
259                                                                                                 1;
260                                                                                 }
261
262                                                                                 ul_TimingInterval
263                                                                                         =
264                                                                                         ul_TimingInterval
265                                                                                         -
266                                                                                         1;
267                                                                                 ul_TimerValue
268                                                                                         =
269                                                                                         ul_TimerValue
270                                                                                         -
271                                                                                         2;
272                                                                                 if (b_PCIInputClock != APCI1710_40MHZ) {
273                                                                                         ul_TimerValue
274                                                                                                 =
275                                                                                                 (unsigned int)
276                                                                                                 (
277                                                                                                 (double)
278                                                                                                 (ul_TimerValue)
279                                                                                                 *
280                                                                                                 0.99392);
281                                                                                 }
282
283                                                                                 break;
284
285                                    /******/
286                                                                                 /* æs */
287                                    /******/
288
289                                                                         case 1:
290
291                                            /******************/
292                                                                                 /* Timer 0 factor */
293                                            /******************/
294
295                                                                                 ul_TimerValue
296                                                                                         =
297                                                                                         (unsigned int)
298                                                                                         (ul_TimingInterval
299                                                                                         *
300                                                                                         (1.0 * b_PCIInputClock));
301
302                                            /*******************/
303                                                                                 /* Round the value */
304                                            /*******************/
305
306                                                                                 if ((double)((double)ul_TimingInterval * (1.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
307                                                                                         ul_TimerValue
308                                                                                                 =
309                                                                                                 ul_TimerValue
310                                                                                                 +
311                                                                                                 1;
312                                                                                 }
313
314                                            /*****************************/
315                                                                                 /* Calculate the real timing */
316                                            /*****************************/
317
318                                                                                 ul_RealTimingInterval
319                                                                                         =
320                                                                                         (unsigned int)
321                                                                                         (ul_TimerValue
322                                                                                         /
323                                                                                         (1.0 * (double)b_PCIInputClock));
324                                                                                 d_RealTimingInterval
325                                                                                         =
326                                                                                         (double)
327                                                                                         ul_TimerValue
328                                                                                         /
329                                                                                         (
330                                                                                         (double)
331                                                                                         1.0
332                                                                                         *
333                                                                                         (double)
334                                                                                         b_PCIInputClock);
335
336                                                                                 if ((double)((double)ul_TimerValue / (1.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
337                                                                                         ul_RealTimingInterval
338                                                                                                 =
339                                                                                                 ul_RealTimingInterval
340                                                                                                 +
341                                                                                                 1;
342                                                                                 }
343
344                                                                                 ul_TimingInterval
345                                                                                         =
346                                                                                         ul_TimingInterval
347                                                                                         -
348                                                                                         1;
349                                                                                 ul_TimerValue
350                                                                                         =
351                                                                                         ul_TimerValue
352                                                                                         -
353                                                                                         2;
354                                                                                 if (b_PCIInputClock != APCI1710_40MHZ) {
355                                                                                         ul_TimerValue
356                                                                                                 =
357                                                                                                 (unsigned int)
358                                                                                                 (
359                                                                                                 (double)
360                                                                                                 (ul_TimerValue)
361                                                                                                 *
362                                                                                                 0.99392);
363                                                                                 }
364
365                                                                                 break;
366
367                                    /******/
368                                                                                 /* ms */
369                                    /******/
370
371                                                                         case 2:
372
373                                            /******************/
374                                                                                 /* Timer 0 factor */
375                                            /******************/
376
377                                                                                 ul_TimerValue
378                                                                                         =
379                                                                                         ul_TimingInterval
380                                                                                         *
381                                                                                         (1000
382                                                                                         *
383                                                                                         b_PCIInputClock);
384
385                                            /*******************/
386                                                                                 /* Round the value */
387                                            /*******************/
388
389                                                                                 if ((double)((double)ul_TimingInterval * (1000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
390                                                                                         ul_TimerValue
391                                                                                                 =
392                                                                                                 ul_TimerValue
393                                                                                                 +
394                                                                                                 1;
395                                                                                 }
396
397                                            /*****************************/
398                                                                                 /* Calculate the real timing */
399                                            /*****************************/
400
401                                                                                 ul_RealTimingInterval
402                                                                                         =
403                                                                                         (unsigned int)
404                                                                                         (ul_TimerValue
405                                                                                         /
406                                                                                         (1000.0 * (double)b_PCIInputClock));
407                                                                                 d_RealTimingInterval
408                                                                                         =
409                                                                                         (double)
410                                                                                         ul_TimerValue
411                                                                                         /
412                                                                                         (1000.0
413                                                                                         *
414                                                                                         (double)
415                                                                                         b_PCIInputClock);
416
417                                                                                 if ((double)((double)ul_TimerValue / (1000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
418                                                                                         ul_RealTimingInterval
419                                                                                                 =
420                                                                                                 ul_RealTimingInterval
421                                                                                                 +
422                                                                                                 1;
423                                                                                 }
424
425                                                                                 ul_TimingInterval
426                                                                                         =
427                                                                                         ul_TimingInterval
428                                                                                         -
429                                                                                         1;
430                                                                                 ul_TimerValue
431                                                                                         =
432                                                                                         ul_TimerValue
433                                                                                         -
434                                                                                         2;
435                                                                                 if (b_PCIInputClock != APCI1710_40MHZ) {
436                                                                                         ul_TimerValue
437                                                                                                 =
438                                                                                                 (unsigned int)
439                                                                                                 (
440                                                                                                 (double)
441                                                                                                 (ul_TimerValue)
442                                                                                                 *
443                                                                                                 0.99392);
444                                                                                 }
445
446                                                                                 break;
447
448                                    /*****/
449                                                                                 /* s */
450                                    /*****/
451
452                                                                         case 3:
453
454                                            /******************/
455                                                                                 /* Timer 0 factor */
456                                            /******************/
457
458                                                                                 ul_TimerValue
459                                                                                         =
460                                                                                         (unsigned int)
461                                                                                         (ul_TimingInterval
462                                                                                         *
463                                                                                         (1000000.0
464                                                                                                 *
465                                                                                                 b_PCIInputClock));
466
467                                            /*******************/
468                                                                                 /* Round the value */
469                                            /*******************/
470
471                                                                                 if ((double)((double)ul_TimingInterval * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
472                                                                                         ul_TimerValue
473                                                                                                 =
474                                                                                                 ul_TimerValue
475                                                                                                 +
476                                                                                                 1;
477                                                                                 }
478
479                                            /*****************************/
480                                                                                 /* Calculate the real timing */
481                                            /*****************************/
482
483                                                                                 ul_RealTimingInterval
484                                                                                         =
485                                                                                         (unsigned int)
486                                                                                         (ul_TimerValue
487                                                                                         /
488                                                                                         (1000000.0
489                                                                                                 *
490                                                                                                 (double)
491                                                                                                 b_PCIInputClock));
492                                                                                 d_RealTimingInterval
493                                                                                         =
494                                                                                         (double)
495                                                                                         ul_TimerValue
496                                                                                         /
497                                                                                         (1000000.0
498                                                                                         *
499                                                                                         (double)
500                                                                                         b_PCIInputClock);
501
502                                                                                 if ((double)((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
503                                                                                         ul_RealTimingInterval
504                                                                                                 =
505                                                                                                 ul_RealTimingInterval
506                                                                                                 +
507                                                                                                 1;
508                                                                                 }
509
510                                                                                 ul_TimingInterval
511                                                                                         =
512                                                                                         ul_TimingInterval
513                                                                                         -
514                                                                                         1;
515                                                                                 ul_TimerValue
516                                                                                         =
517                                                                                         ul_TimerValue
518                                                                                         -
519                                                                                         2;
520                                                                                 if (b_PCIInputClock != APCI1710_40MHZ) {
521                                                                                         ul_TimerValue
522                                                                                                 =
523                                                                                                 (unsigned int)
524                                                                                                 (
525                                                                                                 (double)
526                                                                                                 (ul_TimerValue)
527                                                                                                 *
528                                                                                                 0.99392);
529                                                                                 }
530
531                                                                                 break;
532
533                                    /******/
534                                                                                 /* mn */
535                                    /******/
536
537                                                                         case 4:
538
539                                            /******************/
540                                                                                 /* Timer 0 factor */
541                                            /******************/
542
543                                                                                 ul_TimerValue
544                                                                                         =
545                                                                                         (unsigned int)
546                                                                                         (
547                                                                                         (ul_TimingInterval
548                                                                                                 *
549                                                                                                 60)
550                                                                                         *
551                                                                                         (1000000.0
552                                                                                                 *
553                                                                                                 b_PCIInputClock));
554
555                                            /*******************/
556                                                                                 /* Round the value */
557                                            /*******************/
558
559                                                                                 if ((double)((double)(ul_TimingInterval * 60.0) * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
560                                                                                         ul_TimerValue
561                                                                                                 =
562                                                                                                 ul_TimerValue
563                                                                                                 +
564                                                                                                 1;
565                                                                                 }
566
567                                            /*****************************/
568                                                                                 /* Calculate the real timing */
569                                            /*****************************/
570
571                                                                                 ul_RealTimingInterval
572                                                                                         =
573                                                                                         (unsigned int)
574                                                                                         (ul_TimerValue
575                                                                                         /
576                                                                                         (1000000.0
577                                                                                                 *
578                                                                                                 (double)
579                                                                                                 b_PCIInputClock))
580                                                                                         /
581                                                                                         60;
582                                                                                 d_RealTimingInterval
583                                                                                         =
584                                                                                         (
585                                                                                         (double)
586                                                                                         ul_TimerValue
587                                                                                         /
588                                                                                         (0.001 * (double)b_PCIInputClock)) / 60.0;
589
590                                                                                 if ((double)(((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) {
591                                                                                         ul_RealTimingInterval
592                                                                                                 =
593                                                                                                 ul_RealTimingInterval
594                                                                                                 +
595                                                                                                 1;
596                                                                                 }
597
598                                                                                 ul_TimingInterval
599                                                                                         =
600                                                                                         ul_TimingInterval
601                                                                                         -
602                                                                                         1;
603                                                                                 ul_TimerValue
604                                                                                         =
605                                                                                         ul_TimerValue
606                                                                                         -
607                                                                                         2;
608                                                                                 if (b_PCIInputClock != APCI1710_40MHZ) {
609                                                                                         ul_TimerValue
610                                                                                                 =
611                                                                                                 (unsigned int)
612                                                                                                 (
613                                                                                                 (double)
614                                                                                                 (ul_TimerValue)
615                                                                                                 *
616                                                                                                 0.99392);
617                                                                                 }
618
619                                                                                 break;
620                                                                         }
621
622                                                                         fpu_end();
623
624                                 /****************************/
625                                                                         /* Save the PCI input clock */
626                                 /****************************/
627
628                                                                         devpriv->
629                                                                                 s_ModuleInfo
630                                                                                 [b_ModulNbr].
631                                                                                 s_ChronoModuleInfo.
632                                                                                 b_PCIInputClock
633                                                                                 =
634                                                                                 b_PCIInputClock;
635
636                                 /*************************/
637                                                                         /* Save the timing unity */
638                                 /*************************/
639
640                                                                         devpriv->
641                                                                                 s_ModuleInfo
642                                                                                 [b_ModulNbr].
643                                                                                 s_ChronoModuleInfo.
644                                                                                 b_TimingUnit
645                                                                                 =
646                                                                                 b_TimingUnit;
647
648                                 /************************/
649                                                                         /* Save the base timing */
650                                 /************************/
651
652                                                                         devpriv->
653                                                                                 s_ModuleInfo
654                                                                                 [b_ModulNbr].
655                                                                                 s_ChronoModuleInfo.
656                                                                                 d_TimingInterval
657                                                                                 =
658                                                                                 d_RealTimingInterval;
659
660                                 /****************************/
661                                                                         /* Set the chronometer mode */
662                                 /****************************/
663
664                                                                         devpriv->
665                                                                                 s_ModuleInfo
666                                                                                 [b_ModulNbr].
667                                                                                 s_ChronoModuleInfo.
668                                                                                 dw_ConfigReg
669                                                                                 =
670                                                                                 dw_ModeArray
671                                                                                 [b_ChronoMode];
672
673                                 /***********************/
674                                                                         /* Test if 40 MHz used */
675                                 /***********************/
676
677                                                                         if (b_PCIInputClock == APCI1710_40MHZ) {
678                                                                                 devpriv->
679                                                                                         s_ModuleInfo
680                                                                                         [b_ModulNbr].
681                                                                                         s_ChronoModuleInfo.
682                                                                                         dw_ConfigReg
683                                                                                         =
684                                                                                         devpriv->
685                                                                                         s_ModuleInfo
686                                                                                         [b_ModulNbr].
687                                                                                         s_ChronoModuleInfo.
688                                                                                         dw_ConfigReg
689                                                                                         |
690                                                                                         0x80;
691                                                                         }
692
693                                                                         outl(devpriv->s_ModuleInfo[b_ModulNbr].s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr));
694
695                                 /***********************/
696                                                                         /* Write timer 0 value */
697                                 /***********************/
698
699                                                                         outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
700
701                                 /*********************/
702                                                                         /* Chronometer init. */
703                                 /*********************/
704
705                                                                         devpriv->
706                                                                                 s_ModuleInfo
707                                                                                 [b_ModulNbr].
708                                                                                 s_ChronoModuleInfo.
709                                                                                 b_ChronoInit
710                                                                                 =
711                                                                                 1;
712                                                                 } else {
713                                 /***********************************************/
714                                                                         /* TOR version error for 40MHz clock selection */
715                                 /***********************************************/
716
717                                                                         DPRINTK("TOR version error for 40MHz clock selection\n");
718                                                                         i_ReturnValue
719                                                                                 =
720                                                                                 -9;
721                                                                 }
722                                                         } else {
723                              /**************************************************************/
724                                                                 /* You can not used the 40MHz clock selection wich this board */
725                              /**************************************************************/
726
727                                                                 DPRINTK("You can not used the 40MHz clock selection wich this board\n");
728                                                                 i_ReturnValue =
729                                                                         -8;
730                                                         }
731                                                 } else {
732                           /**********************************/
733                                                         /* Base timing selection is wrong */
734                           /**********************************/
735
736                                                         DPRINTK("Base timing selection is wrong\n");
737                                                         i_ReturnValue = -7;
738                                                 }
739                                         }       /*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
740                                         else {
741                        /***********************************/
742                                                 /* Timing unity selection is wrong */
743                        /***********************************/
744
745                                                 DPRINTK("Timing unity selection is wrong\n");
746                                                 i_ReturnValue = -6;
747                                         }       /*  if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */
748                                 }       /*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
749                                 else {
750                     /*****************************************/
751                                         /* The selected PCI input clock is wrong */
752                     /*****************************************/
753
754                                         DPRINTK("The selected PCI input clock is wrong\n");
755                                         i_ReturnValue = -5;
756                                 }       /*  if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */
757                         }       /*  if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */
758                         else {
759                  /***************************************/
760                                 /* Chronometer mode selection is wrong */
761                  /***************************************/
762
763                                 DPRINTK("Chronometer mode selection is wrong\n");
764                                 i_ReturnValue = -4;
765                         }       /*  if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */
766                 } else {
767               /******************************************/
768                         /* The module is not a Chronometer module */
769               /******************************************/
770
771                         DPRINTK("The module is not a Chronometer module\n");
772                         i_ReturnValue = -3;
773                 }
774         } else {
775            /***********************/
776                 /* Module number error */
777            /***********************/
778
779                 DPRINTK("Module number error\n");
780                 i_ReturnValue = -2;
781         }
782         data[0] = ul_RealTimingInterval;
783         return i_ReturnValue;
784 }
785
786 /*
787 +----------------------------------------------------------------------------+
788 | Function Name     : _INT_ i_APCI1710_EnableChrono                          |
789 |                                               (unsigned char_ b_BoardHandle,        |
790 |                                                unsigned char_ b_ModulNbr,           |
791 |                                                unsigned char_ b_CycleMode,          |
792 |                                                unsigned char_ b_InterruptEnable)
793 int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
794 struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                                          |
795 +----------------------------------------------------------------------------+
796 | Task              : Enable the chronometer from selected module            |
797 |                     (b_ModulNbr). You must calling the                     |
798 |                     "i_APCI1710_InitChrono" function be for you call this  |
799 |                     function.                                              |
800 |                     If you enable the chronometer interrupt, the           |
801 |                     chronometer generate a interrupt after the stop signal.|
802 |                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
803 |                     Interrupt mask description chapter from this manual.   |
804 |                     The b_CycleMode parameter determine if you will        |
805 |                     measured a single or more cycle.
806
807 |                                         Disable the chronometer from selected module           |
808 |                     (b_ModulNbr). If you disable the chronometer after a   |
809 |                     start signal occur and you restart the chronometer     |
810 |                     witch the " i_APCI1710_EnableChrono" function, if no   |
811 |                     stop signal occur this start signal is ignored.
812 +----------------------------------------------------------------------------+
813 | Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
814 |                     unsigned char_ b_ModulNbr   CR_AREF(chanspec)  : Selected module number (0 to 3) |
815                                   data[0]  ENABle/Disable chrono
816 |                     unsigned char_ b_CycleMode    : Selected the chronometer        |
817 |                                  data[1]           acquisition mode                |
818 |                     unsigned char_ b_InterruptEnable : Enable or disable the        |
819 |                                   data[2]            chronometer interrupt.       |
820 |                                               APCI1710_ENABLE:             |
821 |                                               Enable the chronometer       |
822 |                                               interrupt                    |
823 |                                               APCI1710_DISABLE:            |
824 |                                               Disable the chronometer      |
825 |                                               interrupt                    |
826 +----------------------------------------------------------------------------+
827 | Output Parameters : -                                                      |
828 +----------------------------------------------------------------------------+
829 | Return Value      :  0: No error                                           |
830 |                     -1: The handle parameter of the board is wrong         |
831 |                     -2: Module selection wrong                             |
832 |                     -3: The module is not a Chronometer module             |
833 |                     -4: Chronometer not initialised see function           |
834 |                         "i_APCI1710_InitChrono"                            |
835 |                     -5: Chronometer acquisition mode cycle is wrong        |
836 |                     -6: Interrupt parameter is wrong                       |
837 |                     -7: Interrupt function not initialised.                |
838 |                         See function "i_APCI1710_SetBoardIntRoutineX"
839                       -8: data[0] wrong input    |
840 +----------------------------------------------------------------------------+
841 */
842
843 int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
844         struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
845 {
846         int i_ReturnValue = 0;
847         unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
848         b_ModulNbr = CR_AREF(insn->chanspec);
849         b_Action = (unsigned char) data[0];
850         b_CycleMode = (unsigned char) data[1];
851         b_InterruptEnable = (unsigned char) data[2];
852         i_ReturnValue = insn->n;
853
854         /**************************/
855         /* Test the module number */
856         /**************************/
857
858         if (b_ModulNbr < 4) {
859            /***********************/
860                 /* Test if chronometer */
861            /***********************/
862
863                 if ((devpriv->s_BoardInfos.
864                                 dw_MolduleConfiguration[b_ModulNbr] &
865                                 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
866               /***********************************/
867                         /* Test if chronometer initialised */
868               /***********************************/
869
870                         if (devpriv->s_ModuleInfo[b_ModulNbr].
871                                 s_ChronoModuleInfo.b_ChronoInit == 1) {
872
873                                 switch (b_Action) {
874
875                                 case APCI1710_ENABLE:
876
877                  /*********************************/
878                                         /* Test the cycle mode parameter */
879                  /*********************************/
880
881                                         if ((b_CycleMode == APCI1710_SINGLE)
882                                                 || (b_CycleMode ==
883                                                         APCI1710_CONTINUOUS)) {
884                     /***************************/
885                                                 /* Test the interrupt flag */
886                     /***************************/
887
888                                                 if ((b_InterruptEnable ==
889                                                                 APCI1710_ENABLE)
890                                                         || (b_InterruptEnable ==
891                                                                 APCI1710_DISABLE))
892                                                 {
893
894                           /***************************/
895                                                         /* Save the interrupt flag */
896                           /***************************/
897
898                                                         devpriv->
899                                                                 s_ModuleInfo
900                                                                 [b_ModulNbr].
901                                                                 s_ChronoModuleInfo.
902                                                                 b_InterruptMask
903                                                                 =
904                                                                 b_InterruptEnable;
905
906                           /***********************/
907                                                         /* Save the cycle mode */
908                           /***********************/
909
910                                                         devpriv->
911                                                                 s_ModuleInfo
912                                                                 [b_ModulNbr].
913                                                                 s_ChronoModuleInfo.
914                                                                 b_CycleMode =
915                                                                 b_CycleMode;
916
917                                                         devpriv->
918                                                                 s_ModuleInfo
919                                                                 [b_ModulNbr].
920                                                                 s_ChronoModuleInfo.
921                                                                 dw_ConfigReg =
922                                                                 (devpriv->
923                                                                 s_ModuleInfo
924                                                                 [b_ModulNbr].
925                                                                 s_ChronoModuleInfo.
926                                                                 dw_ConfigReg &
927                                                                 0x8F) | ((1 &
928                                                                         b_InterruptEnable)
929                                                                 << 5) | ((1 &
930                                                                         b_CycleMode)
931                                                                 << 6) | 0x10;
932
933                           /*****************************/
934                                                         /* Test if interrupt enabled */
935                           /*****************************/
936
937                                                         if (b_InterruptEnable ==
938                                                                 APCI1710_ENABLE)
939                                                         {
940                              /****************************/
941                                                                 /* Clear the interrupt flag */
942                              /****************************/
943
944                                                                 outl(devpriv->
945                                                                         s_ModuleInfo
946                                                                         [b_ModulNbr].
947                                                                         s_ChronoModuleInfo.
948                                                                         dw_ConfigReg,
949                                                                         devpriv->
950                                                                         s_BoardInfos.
951                                                                         ui_Address
952                                                                         + 32 +
953                                                                         (64 * b_ModulNbr));
954                                                                 devpriv->tsk_Current = current; /*  Save the current process task structure */
955                                                         }
956
957                           /***********************************/
958                                                         /* Enable or disable the interrupt */
959                                                         /* Enable the chronometer          */
960                           /***********************************/
961
962                                                         outl(devpriv->
963                                                                 s_ModuleInfo
964                                                                 [b_ModulNbr].
965                                                                 s_ChronoModuleInfo.
966                                                                 dw_ConfigReg,
967                                                                 devpriv->
968                                                                 s_BoardInfos.
969                                                                 ui_Address +
970                                                                 16 +
971                                                                 (64 * b_ModulNbr));
972
973                           /*************************/
974                                                         /* Clear status register */
975                           /*************************/
976
977                                                         outl(0, devpriv->
978                                                                 s_BoardInfos.
979                                                                 ui_Address +
980                                                                 36 +
981                                                                 (64 * b_ModulNbr));
982
983                                                 }       /*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
984                                                 else {
985                        /********************************/
986                                                         /* Interrupt parameter is wrong */
987                        /********************************/
988
989                                                         DPRINTK("Interrupt parameter is wrong\n");
990                                                         i_ReturnValue = -6;
991                                                 }       /*  if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */
992                                         }       /*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
993                                         else {
994                     /***********************************************/
995                                                 /* Chronometer acquisition mode cycle is wrong */
996                     /***********************************************/
997
998                                                 DPRINTK("Chronometer acquisition mode cycle is wrong\n");
999                                                 i_ReturnValue = -5;
1000                                         }       /*  if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */
1001                                         break;
1002
1003                                 case APCI1710_DISABLE:
1004
1005                                         devpriv->s_ModuleInfo[b_ModulNbr].
1006                                                 s_ChronoModuleInfo.
1007                                                 b_InterruptMask = 0;
1008
1009                                         devpriv->s_ModuleInfo[b_ModulNbr].
1010                                                 s_ChronoModuleInfo.
1011                                                 dw_ConfigReg =
1012                                                 devpriv->
1013                                                 s_ModuleInfo[b_ModulNbr].
1014                                                 s_ChronoModuleInfo.
1015                                                 dw_ConfigReg & 0x2F;
1016
1017                  /***************************/
1018                                         /* Disable the interrupt   */
1019                                         /* Disable the chronometer */
1020                  /***************************/
1021
1022                                         outl(devpriv->s_ModuleInfo[b_ModulNbr].
1023                                                 s_ChronoModuleInfo.dw_ConfigReg,
1024                                                 devpriv->s_BoardInfos.
1025                                                 ui_Address + 16 +
1026                                                 (64 * b_ModulNbr));
1027
1028                  /***************************/
1029                                         /* Test if continuous mode */
1030                  /***************************/
1031
1032                                         if (devpriv->s_ModuleInfo[b_ModulNbr].
1033                                                 s_ChronoModuleInfo.
1034                                                 b_CycleMode ==
1035                                                 APCI1710_CONTINUOUS) {
1036                     /*************************/
1037                                                 /* Clear status register */
1038                     /*************************/
1039
1040                                                 outl(0, devpriv->s_BoardInfos.
1041                                                         ui_Address + 36 +
1042                                                         (64 * b_ModulNbr));
1043                                         }
1044                                         break;
1045
1046                                 default:
1047                                         DPRINTK("Inputs wrong! Enable or Disable chrono\n");
1048                                         i_ReturnValue = -8;
1049                                 }       /*  switch ENABLE/DISABLE */
1050                         } else {
1051                  /*******************************/
1052                                 /* Chronometer not initialised */
1053                  /*******************************/
1054
1055                                 DPRINTK("Chronometer not initialised\n");
1056                                 i_ReturnValue = -4;
1057                         }
1058                 } else {
1059               /******************************************/
1060                         /* The module is not a Chronometer module */
1061               /******************************************/
1062
1063                         DPRINTK("The module is not a Chronometer module\n");
1064                         i_ReturnValue = -3;
1065                 }
1066         } else {
1067            /***********************/
1068                 /* Module number error */
1069            /***********************/
1070
1071                 DPRINTK("Module number error\n");
1072                 i_ReturnValue = -2;
1073         }
1074
1075         return i_ReturnValue;
1076 }
1077
1078 /*
1079 +----------------------------------------------------------------------------+
1080 | Function Name     :INT        i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s,
1081 struct comedi_insn *insn,unsigned int *data)                   |
1082 +----------------------------------------------------------------------------+
1083 | Task              : Read  functions for Timer                                     |
1084 +----------------------------------------------------------------------------+
1085 | Input Parameters  :
1086 +----------------------------------------------------------------------------+
1087 | Output Parameters : -                                                      |
1088 +----------------------------------------------------------------------------+
1089 | Return Value      :
1090 +----------------------------------------------------------------------------+
1091 */
1092
1093 int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
1094         struct comedi_insn *insn, unsigned int *data)
1095 {
1096         unsigned char b_ReadType;
1097         int i_ReturnValue = insn->n;
1098
1099         b_ReadType = CR_CHAN(insn->chanspec);
1100
1101         switch (b_ReadType) {
1102         case APCI1710_CHRONO_PROGRESS_STATUS:
1103                 i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
1104                         (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
1105                 break;
1106
1107         case APCI1710_CHRONO_READVALUE:
1108                 i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
1109                         (unsigned char) CR_AREF(insn->chanspec),
1110                         (unsigned int) insn->unused[0],
1111                         (unsigned char *) &data[0], (unsigned int *) &data[1]);
1112                 break;
1113
1114         case APCI1710_CHRONO_CONVERTVALUE:
1115                 i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
1116                         (unsigned char) CR_AREF(insn->chanspec),
1117                         (unsigned int) insn->unused[0],
1118                         (unsigned int *) &data[0],
1119                         (unsigned char *) &data[1],
1120                         (unsigned char *) &data[2],
1121                         (unsigned int *) &data[3],
1122                         (unsigned int *) &data[4], (unsigned int *) &data[5]);
1123                 break;
1124
1125         case APCI1710_CHRONO_READINTERRUPT:
1126                 printk("In Chrono Read Interrupt\n");
1127
1128                 data[0] = devpriv->s_InterruptParameters.
1129                         s_FIFOInterruptParameters[devpriv->
1130                         s_InterruptParameters.ui_Read].b_OldModuleMask;
1131                 data[1] = devpriv->s_InterruptParameters.
1132                         s_FIFOInterruptParameters[devpriv->
1133                         s_InterruptParameters.ui_Read].ul_OldInterruptMask;
1134                 data[2] = devpriv->s_InterruptParameters.
1135                         s_FIFOInterruptParameters[devpriv->
1136                         s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
1137
1138                              /**************************/
1139                 /* Increment the read FIFO */
1140                              /***************************/
1141
1142                 devpriv->
1143                         s_InterruptParameters.
1144                         ui_Read = (devpriv->
1145                         s_InterruptParameters.
1146                         ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
1147                 break;
1148
1149         default:
1150                 printk("ReadType Parameter wrong\n");
1151         }
1152
1153         if (i_ReturnValue >= 0)
1154                 i_ReturnValue = insn->n;
1155         return i_ReturnValue;
1156
1157 }
1158
1159 /*
1160 +----------------------------------------------------------------------------+
1161 | Function Name     : _INT_ i_APCI1710_GetChronoProgressStatus               |
1162 |                               (unsigned char_    b_BoardHandle,                     |
1163 |                                unsigned char_    b_ModulNbr,                        |
1164 |                                unsigned char *_  pb_ChronoStatus)                    |
1165 +----------------------------------------------------------------------------+
1166 | Task              : Return the chronometer status (pb_ChronoStatus) from   |
1167 |                     selected chronometer module (b_ModulNbr).              |
1168 +----------------------------------------------------------------------------+
1169 | Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
1170 |                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
1171 +----------------------------------------------------------------------------+
1172 | Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
1173 |                                                status.                     |
1174 |                                                0 : Measurement not started.|
1175 |                                                    No start signal occur.  |
1176 |                                                1 : Measurement started.    |
1177 |                                                    A start signal occur.   |
1178 |                                                2 : Measurement stopped.    |
1179 |                                                    A stop signal occur.    |
1180 |                                                    The measurement is      |
1181 |                                                    terminate.              |
1182 |                                                3: A overflow occur. You    |
1183 |                                                   must change the base     |
1184 |                                                   timing witch the         |
1185 |                                                   function                 |
1186 |                                                   "i_APCI1710_InitChrono"  |
1187 +----------------------------------------------------------------------------+
1188 | Return Value      :  0: No error                                           |
1189 |                     -1: The handle parameter of the board is wrong         |
1190 |                     -2: Module selection wrong                             |
1191 |                     -3: The module is not a Chronometer module             |
1192 |                     -4: Chronometer not initialised see function           |
1193 |                         "i_APCI1710_InitChrono"                            |
1194 +----------------------------------------------------------------------------+
1195 */
1196
1197 int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
1198         unsigned char b_ModulNbr, unsigned char *pb_ChronoStatus)
1199 {
1200         int i_ReturnValue = 0;
1201         unsigned int dw_Status;
1202
1203         /**************************/
1204         /* Test the module number */
1205         /**************************/
1206
1207         if (b_ModulNbr < 4) {
1208            /***********************/
1209                 /* Test if chronometer */
1210            /***********************/
1211
1212                 if ((devpriv->s_BoardInfos.
1213                                 dw_MolduleConfiguration[b_ModulNbr] &
1214                                 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
1215               /***********************************/
1216                         /* Test if chronometer initialised */
1217               /***********************************/
1218
1219                         if (devpriv->
1220                                 s_ModuleInfo[b_ModulNbr].
1221                                 s_ChronoModuleInfo.b_ChronoInit == 1) {
1222
1223                                 dw_Status = inl(devpriv->s_BoardInfos.
1224                                         ui_Address + 8 + (64 * b_ModulNbr));
1225
1226                  /********************/
1227                                 /* Test if overflow */
1228                  /********************/
1229
1230                                 if ((dw_Status & 8) == 8) {
1231                     /******************/
1232                                         /* Overflow occur */
1233                     /******************/
1234
1235                                         *pb_ChronoStatus = 3;
1236                                 }       /*  if ((dw_Status & 8) == 8) */
1237                                 else {
1238                     /*******************************/
1239                                         /* Test if measurement stopped */
1240                     /*******************************/
1241
1242                                         if ((dw_Status & 2) == 2) {
1243                        /***********************/
1244                                                 /* A stop signal occur */
1245                        /***********************/
1246
1247                                                 *pb_ChronoStatus = 2;
1248                                         }       /*  if ((dw_Status & 2) == 2) */
1249                                         else {
1250                        /*******************************/
1251                                                 /* Test if measurement started */
1252                        /*******************************/
1253
1254                                                 if ((dw_Status & 1) == 1) {
1255                           /************************/
1256                                                         /* A start signal occur */
1257                           /************************/
1258
1259                                                         *pb_ChronoStatus = 1;
1260                                                 }       /*  if ((dw_Status & 1) == 1) */
1261                                                 else {
1262                           /***************************/
1263                                                         /* Measurement not started */
1264                           /***************************/
1265
1266                                                         *pb_ChronoStatus = 0;
1267                                                 }       /*  if ((dw_Status & 1) == 1) */
1268                                         }       /*  if ((dw_Status & 2) == 2) */
1269                                 }       /*  if ((dw_Status & 8) == 8) */
1270                         } else {
1271                  /*******************************/
1272                                 /* Chronometer not initialised */
1273                  /*******************************/
1274                                 DPRINTK("Chronometer not initialised\n");
1275                                 i_ReturnValue = -4;
1276                         }
1277                 } else {
1278               /******************************************/
1279                         /* The module is not a Chronometer module */
1280               /******************************************/
1281                         DPRINTK("The module is not a Chronometer module\n");
1282                         i_ReturnValue = -3;
1283                 }
1284         } else {
1285            /***********************/
1286                 /* Module number error */
1287            /***********************/
1288                 DPRINTK("Module number error\n");
1289                 i_ReturnValue = -2;
1290         }
1291
1292         return i_ReturnValue;
1293 }
1294
1295 /*
1296 +----------------------------------------------------------------------------+
1297 | Function Name     : _INT_ i_APCI1710_ReadChronoValue                       |
1298 |                               (unsigned char_     b_BoardHandle,                    |
1299 |                                unsigned char_     b_ModulNbr,                       |
1300 |                                unsigned int_    ui_TimeOut,                        |
1301 |                                unsigned char *_   pb_ChronoStatus,                   |
1302 |                                PULONG_ pul_ChronoValue)                    |
1303 +----------------------------------------------------------------------------+
1304 | Task              : Return the chronometer status (pb_ChronoStatus) and the|
1305 |                     timing value (pul_ChronoValue) after a stop signal     |
1306 |                     occur from selected chronometer module (b_ModulNbr).   |
1307 |                     This function are only avaible if you have disabled    |
1308 |                     the interrupt functionality. See function              |
1309 |                     "i_APCI1710_EnableChrono" and the Interrupt mask       |
1310 |                     description chapter.                                   |
1311 |                     You can test the chronometer status witch the          |
1312 |                     "i_APCI1710_GetChronoProgressStatus" function.         |
1313 |                                                                            |
1314 |                     The returned value from pul_ChronoValue parameter is   |
1315 |                     not real measured timing.                              |
1316 |                     You must used the "i_APCI1710_ConvertChronoValue"      |
1317 |                     function or make this operation for calculate the      |
1318 |                     timing:                                                |
1319 |                                                                            |
1320 |                     Timing = pul_ChronoValue * pul_RealTimingInterval.     |
1321 |                                                                            |
1322 |                     pul_RealTimingInterval is the returned parameter from  |
1323 |                     "i_APCI1710_InitChrono" function and the time unity is |
1324 |                     the b_TimingUnit from "i_APCI1710_InitChrono" function|
1325 +----------------------------------------------------------------------------+
1326 | Input Parameters  : unsigned char_ b_BoardHandle  : Handle of board APCI-1710       |
1327 |                     unsigned char_ b_ModulNbr     : Selected module number (0 to 3) |
1328 +----------------------------------------------------------------------------+
1329 | Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
1330 |                                                status.                     |
1331 |                                                0 : Measurement not started.|
1332 |                                                    No start signal occur.  |
1333 |                                                1 : Measurement started.    |
1334 |                                                    A start signal occur.   |
1335 |                                                2 : Measurement stopped.    |
1336 |                                                    A stop signal occur.    |
1337 |                                                    The measurement is      |
1338 |                                                    terminate.              |
1339 |                                                3: A overflow occur. You    |
1340 |                                                   must change the base     |
1341 |                                                   timing witch the         |
1342 |                                                   function                 |
1343 |                                                   "i_APCI1710_InitChrono"  |
1344 |                     unsigned int *  pul_ChronoValue  : Chronometer timing value.   |
1345 +----------------------------------------------------------------------------+
1346 | Return Value      :  0: No error                                           |
1347 |                     -1: The handle parameter of the board is wrong         |
1348 |                     -2: Module selection wrong                             |
1349 |                     -3: The module is not a Chronometer module             |
1350 |                     -4: Chronometer not initialised see function           |
1351 |                         "i_APCI1710_InitChrono"                            |
1352 |                     -5: Timeout parameter is wrong (0 to 65535)            |
1353 |                     -6: Interrupt routine installed. You can not read      |
1354 |                         directly the chronometer measured timing.          |
1355 +----------------------------------------------------------------------------+
1356 */
1357
1358 int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
1359         unsigned char b_ModulNbr,
1360         unsigned int ui_TimeOut, unsigned char *pb_ChronoStatus, unsigned int *pul_ChronoValue)
1361 {
1362         int i_ReturnValue = 0;
1363         unsigned int dw_Status;
1364         unsigned int dw_TimeOut = 0;
1365
1366         /**************************/
1367         /* Test the module number */
1368         /**************************/
1369
1370         if (b_ModulNbr < 4) {
1371            /***********************/
1372                 /* Test if chronometer */
1373            /***********************/
1374
1375                 if ((devpriv->s_BoardInfos.
1376                                 dw_MolduleConfiguration[b_ModulNbr] &
1377                                 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
1378               /***********************************/
1379                         /* Test if chronometer initialised */
1380               /***********************************/
1381
1382                         if (devpriv->
1383                                 s_ModuleInfo[b_ModulNbr].
1384                                 s_ChronoModuleInfo.b_ChronoInit == 1) {
1385                  /*****************************/
1386                                 /* Test the timout parameter */
1387                  /*****************************/
1388
1389                                 if (ui_TimeOut <= 65535UL) {
1390
1391                                         for (;;) {
1392                           /*******************/
1393                                                 /* Read the status */
1394                           /*******************/
1395
1396                                                 dw_Status =
1397                                                         inl(devpriv->
1398                                                         s_BoardInfos.
1399                                                         ui_Address + 8 +
1400                                                         (64 * b_ModulNbr));
1401
1402                           /********************/
1403                                                 /* Test if overflow */
1404                           /********************/
1405
1406                                                 if ((dw_Status & 8) == 8) {
1407                              /******************/
1408                                                         /* Overflow occur */
1409                              /******************/
1410
1411                                                         *pb_ChronoStatus = 3;
1412
1413                              /***************************/
1414                                                         /* Test if continuous mode */
1415                              /***************************/
1416
1417                                                         if (devpriv->
1418                                                                 s_ModuleInfo
1419                                                                 [b_ModulNbr].
1420                                                                 s_ChronoModuleInfo.
1421                                                                 b_CycleMode ==
1422                                                                 APCI1710_CONTINUOUS)
1423                                                         {
1424                                 /*************************/
1425                                                                 /* Clear status register */
1426                                 /*************************/
1427
1428                                                                 outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
1429                                                         }
1430
1431                                                         break;
1432                                                 }       /*  if ((dw_Status & 8) == 8) */
1433                                                 else {
1434                              /*******************************/
1435                                                         /* Test if measurement stopped */
1436                              /*******************************/
1437
1438                                                         if ((dw_Status & 2) ==
1439                                                                 2) {
1440                                 /***********************/
1441                                                                 /* A stop signal occur */
1442                                 /***********************/
1443
1444                                                                 *pb_ChronoStatus
1445                                                                         = 2;
1446
1447                                 /***************************/
1448                                                                 /* Test if continnous mode */
1449                                 /***************************/
1450
1451                                                                 if (devpriv->
1452                                                                         s_ModuleInfo
1453                                                                         [b_ModulNbr].
1454                                                                         s_ChronoModuleInfo.
1455                                                                         b_CycleMode
1456                                                                         ==
1457                                                                         APCI1710_CONTINUOUS)
1458                                                                 {
1459                                    /*************************/
1460                                                                         /* Clear status register */
1461                                    /*************************/
1462
1463                                                                         outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
1464                                                                 }
1465                                                                 break;
1466                                                         }       /*  if ((dw_Status & 2) == 2) */
1467                                                         else {
1468                                 /*******************************/
1469                                                                 /* Test if measurement started */
1470                                 /*******************************/
1471
1472                                                                 if ((dw_Status & 1) == 1) {
1473                                    /************************/
1474                                                                         /* A start signal occur */
1475                                    /************************/
1476
1477                                                                         *pb_ChronoStatus
1478                                                                                 =
1479                                                                                 1;
1480                                                                 }       /*  if ((dw_Status & 1) == 1) */
1481                                                                 else {
1482                                    /***************************/
1483                                                                         /* Measurement not started */
1484                                    /***************************/
1485
1486                                                                         *pb_ChronoStatus
1487                                                                                 =
1488                                                                                 0;
1489                                                                 }       /*  if ((dw_Status & 1) == 1) */
1490                                                         }       /*  if ((dw_Status & 2) == 2) */
1491                                                 }       /*  if ((dw_Status & 8) == 8) */
1492
1493                                                 if (dw_TimeOut == ui_TimeOut) {
1494                              /*****************/
1495                                                         /* Timeout occur */
1496                              /*****************/
1497
1498                                                         break;
1499                                                 } else {
1500                              /*************************/
1501                                                         /* Increment the timeout */
1502                              /*************************/
1503
1504                                                         dw_TimeOut =
1505                                                                 dw_TimeOut + 1;
1506                                                         mdelay(1000);
1507
1508                                                 }
1509                                         }       /*  for (;;) */
1510
1511                        /*****************************/
1512                                         /* Test if stop signal occur */
1513                        /*****************************/
1514
1515                                         if (*pb_ChronoStatus == 2) {
1516                           /**********************************/
1517                                                 /* Read the measured timing value */
1518                           /**********************************/
1519
1520                                                 *pul_ChronoValue =
1521                                                         inl(devpriv->
1522                                                         s_BoardInfos.
1523                                                         ui_Address + 4 +
1524                                                         (64 * b_ModulNbr));
1525
1526                                                 if (*pul_ChronoValue != 0) {
1527                                                         *pul_ChronoValue =
1528                                                                 *pul_ChronoValue
1529                                                                 - 1;
1530                                                 }
1531                                         } else {
1532                           /*************************/
1533                                                 /* Test if timeout occur */
1534                           /*************************/
1535
1536                                                 if ((*pb_ChronoStatus != 3)
1537                                                         && (dw_TimeOut ==
1538                                                                 ui_TimeOut)
1539                                                         && (ui_TimeOut != 0)) {
1540                              /*****************/
1541                                                         /* Timeout occur */
1542                              /*****************/
1543
1544                                                         *pb_ChronoStatus = 4;
1545                                                 }
1546                                         }
1547
1548                                 } else {
1549                     /******************************/
1550                                         /* Timeout parameter is wrong */
1551                     /******************************/
1552                                         DPRINTK("Timeout parameter is wrong\n");
1553                                         i_ReturnValue = -5;
1554                                 }
1555                         } else {
1556                  /*******************************/
1557                                 /* Chronometer not initialised */
1558                  /*******************************/
1559                                 DPRINTK("Chronometer not initialised\n");
1560                                 i_ReturnValue = -4;
1561                         }
1562                 } else {
1563               /******************************************/
1564                         /* The module is not a Chronometer module */
1565               /******************************************/
1566                         DPRINTK("The module is not a Chronometer module\n");
1567                         i_ReturnValue = -3;
1568                 }
1569         } else {
1570            /***********************/
1571                 /* Module number error */
1572            /***********************/
1573                 DPRINTK("Module number error\n");
1574                 i_ReturnValue = -2;
1575         }
1576
1577         return i_ReturnValue;
1578 }
1579
1580 /*
1581 +----------------------------------------------------------------------------+
1582 | Function Name     : _INT_ i_APCI1710_ConvertChronoValue                    |
1583 |                               (unsigned char_     b_BoardHandle,                    |
1584 |                                unsigned char_     b_ModulNbr,                       |
1585 |                                ULONG_   ul_ChronoValue,                    |
1586 |                                PULONG_ pul_Hour,                           |
1587 |                                unsigned char *_   pb_Minute,                         |
1588 |                                unsigned char *_   pb_Second,                         |
1589 |                                unsigned int *_  pui_MilliSecond,                    |
1590 |                                unsigned int *_  pui_MicroSecond,                    |
1591 |                                unsigned int *_  pui_NanoSecond)                     |
1592 +----------------------------------------------------------------------------+
1593 | Task              : Convert the chronometer measured timing                |
1594 |                     (ul_ChronoValue) in to h, mn, s, ms, µs, ns.           |
1595 +----------------------------------------------------------------------------+
1596 | Input Parameters  : unsigned char_   b_BoardHandle : Handle of board APCI-1710      |
1597 |                     unsigned char_   b_ModulNbr    : Selected module number (0 to 3)|
1598 |                     ULONG_ ul_ChronoValue : Measured chronometer timing    |
1599 |                                             value.                         |
1600 |                                             See"i_APCI1710_ReadChronoValue"|
1601 +----------------------------------------------------------------------------+
1602 | Output Parameters : PULONG_   pul_Hour        : Chronometer timing hour    |
1603 |                     unsigned char *_     pb_Minute      : Chronometer timing minute  |
1604 |                     unsigned char *_     pb_Second      : Chronometer timing second  |
1605 |                     unsigned int *_    pui_MilliSecond  : Chronometer timing mini   |
1606 |                                                 second                     |
1607 |                     unsigned int *_    pui_MicroSecond : Chronometer timing micro   |
1608 |                                                 second                     |
1609 |                     unsigned int *_    pui_NanoSecond  : Chronometer timing nano    |
1610 |                                                 second                     |
1611 +----------------------------------------------------------------------------+
1612 | Return Value      :  0: No error                                           |
1613 |                     -1: The handle parameter of the board is wrong         |
1614 |                     -2: Module selection wrong                             |
1615 |                     -3: The module is not a Chronometer module             |
1616 |                     -4: Chronometer not initialised see function           |
1617 |                         "i_APCI1710_InitChrono"                            |
1618 +----------------------------------------------------------------------------+
1619 */
1620
1621 int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
1622         unsigned char b_ModulNbr,
1623         unsigned int ul_ChronoValue,
1624         unsigned int *pul_Hour,
1625         unsigned char *pb_Minute,
1626         unsigned char *pb_Second,
1627         unsigned int *pui_MilliSecond, unsigned int *pui_MicroSecond, unsigned int *pui_NanoSecond)
1628 {
1629         int i_ReturnValue = 0;
1630         double d_Hour;
1631         double d_Minute;
1632         double d_Second;
1633         double d_MilliSecond;
1634         double d_MicroSecond;
1635         double d_NanoSecond;
1636
1637         /**************************/
1638         /* Test the module number */
1639         /**************************/
1640
1641         if (b_ModulNbr < 4) {
1642            /***********************/
1643                 /* Test if chronometer */
1644            /***********************/
1645
1646                 if ((devpriv->s_BoardInfos.
1647                                 dw_MolduleConfiguration[b_ModulNbr] &
1648                                 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
1649               /***********************************/
1650                         /* Test if chronometer initialised */
1651               /***********************************/
1652
1653                         if (devpriv->
1654                                 s_ModuleInfo[b_ModulNbr].
1655                                 s_ChronoModuleInfo.b_ChronoInit == 1) {
1656                                 fpu_begin();
1657
1658                                 d_Hour = (double)ul_ChronoValue *(double)
1659                                         devpriv->s_ModuleInfo[b_ModulNbr].
1660                                         s_ChronoModuleInfo.d_TimingInterval;
1661
1662                                 switch (devpriv->
1663                                         s_ModuleInfo[b_ModulNbr].
1664                                         s_ChronoModuleInfo.b_TimingUnit) {
1665                                 case 0:
1666                                         d_Hour = d_Hour / (double)1000.0;
1667
1668                                 case 1:
1669                                         d_Hour = d_Hour / (double)1000.0;
1670
1671                                 case 2:
1672                                         d_Hour = d_Hour / (double)1000.0;
1673
1674                                 case 3:
1675                                         d_Hour = d_Hour / (double)60.0;
1676
1677                                 case 4:
1678                             /**********************/
1679                                         /* Calculate the hour */
1680                             /**********************/
1681
1682                                         d_Hour = d_Hour / (double)60.0;
1683                                         *pul_Hour = (unsigned int) d_Hour;
1684
1685                             /************************/
1686                                         /* Calculate the minute */
1687                             /************************/
1688
1689                                         d_Minute = d_Hour - *pul_Hour;
1690                                         d_Minute = d_Minute * 60;
1691                                         *pb_Minute = (unsigned char) d_Minute;
1692
1693                             /************************/
1694                                         /* Calculate the second */
1695                             /************************/
1696
1697                                         d_Second = d_Minute - *pb_Minute;
1698                                         d_Second = d_Second * 60;
1699                                         *pb_Second = (unsigned char) d_Second;
1700
1701                             /*****************************/
1702                                         /* Calculate the mini second */
1703                             /*****************************/
1704
1705                                         d_MilliSecond = d_Second - *pb_Second;
1706                                         d_MilliSecond = d_MilliSecond * 1000;
1707                                         *pui_MilliSecond = (unsigned int) d_MilliSecond;
1708
1709                             /******************************/
1710                                         /* Calculate the micro second */
1711                             /******************************/
1712
1713                                         d_MicroSecond =
1714                                                 d_MilliSecond -
1715                                                 *pui_MilliSecond;
1716                                         d_MicroSecond = d_MicroSecond * 1000;
1717                                         *pui_MicroSecond = (unsigned int) d_MicroSecond;
1718
1719                             /******************************/
1720                                         /* Calculate the micro second */
1721                             /******************************/
1722
1723                                         d_NanoSecond =
1724                                                 d_MicroSecond -
1725                                                 *pui_MicroSecond;
1726                                         d_NanoSecond = d_NanoSecond * 1000;
1727                                         *pui_NanoSecond = (unsigned int) d_NanoSecond;
1728                                         break;
1729                                 }
1730
1731                                 fpu_end();
1732                         } else {
1733                  /*******************************/
1734                                 /* Chronometer not initialised */
1735                  /*******************************/
1736                                 DPRINTK("Chronometer not initialised\n");
1737                                 i_ReturnValue = -4;
1738                         }
1739                 } else {
1740               /******************************************/
1741                         /* The module is not a Chronometer module */
1742               /******************************************/
1743                         DPRINTK("The module is not a Chronometer module\n");
1744                         i_ReturnValue = -3;
1745                 }
1746         } else {
1747            /***********************/
1748                 /* Module number error */
1749            /***********************/
1750                 DPRINTK("Module number error\n");
1751                 i_ReturnValue = -2;
1752         }
1753
1754         return i_ReturnValue;
1755 }
1756
1757 /*
1758 +----------------------------------------------------------------------------+
1759 | Function Name     : int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
1760         struct comedi_insn *insn,unsigned int *data)                    |
1761 +----------------------------------------------------------------------------+
1762 | Task              : Sets the output witch has been passed with the         |
1763 |                     parameter b_Channel. Setting an output means setting an|
1764 |                     output high.                                           |
1765 +----------------------------------------------------------------------------+
1766 | Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
1767 |                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
1768 |                     unsigned char_ b_OutputChannel : Selection from digital output  |
1769 |                           CR_CHAN()                  channel (0 to 2)               |
1770 |                                              0 : Channel H                 |
1771 |                                              1 : Channel A                 |
1772 |                                              2 : Channel B                 |
1773 +----------------------------------------------------------------------------+
1774 | Output Parameters : -                                                      |
1775 +----------------------------------------------------------------------------+
1776 | Return Value      :  0: No error                                           |
1777 |                     -1: The handle parameter of the board is wrong         |
1778 |                     -2: Module selection wrong                             |
1779 |                     -3: The module is not a Chronometer module             |
1780 |                     -4: The selected digital output is wrong               |
1781 |                     -5: Chronometer not initialised see function           |
1782 |                         "i_APCI1710_InitChrono"                            |
1783 +----------------------------------------------------------------------------+
1784 */
1785
1786 /*
1787 +----------------------------------------------------------------------------+
1788 | Function Name     : _INT_ i_APCI1710_SetChronoChlOff                       |
1789 |                               (unsigned char_  b_BoardHandle,                       |
1790 |                                unsigned char_  b_ModulNbr,                          |
1791 |                                unsigned char_  b_OutputChannel)                     |
1792 +----------------------------------------------------------------------------+
1793 | Task              : Resets the output witch has been passed with the       |
1794 |                     parameter b_Channel. Resetting an output means setting |
1795 |                     an output low.                                         |
1796 +----------------------------------------------------------------------------+
1797 | Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710
1798                         data[0] : Chl ON, Chl OFF , Chl Read , Port Read
1799
1800 |                     unsigned char_ b_ModulNbr  CR_AREF    : Selected module number (0 to 3)|
1801 |                     unsigned char_ b_OutputChannel CR_CHAN : Selection from digital output  |
1802 |                                             channel (0 to 2)               |
1803 |                                              0 : Channel H                 |
1804 |                                              1 : Channel A                 |
1805 |                                              2 : Channel B                 |
1806 +----------------------------------------------------------------------------+
1807 | Output Parameters : -                                                      |
1808 +----------------------------------------------------------------------------+
1809 | Return Value      :  0: No error                                           |
1810 |                     -1: The handle parameter of the board is wrong         |
1811 |                     -2: Module selection wrong                             |
1812 |                     -3: The module is not a Chronometer module             |
1813 |                     -4: The selected digital output is wrong               |
1814 |                     -5: Chronometer not initialised see function           |
1815 |                         "i_APCI1710_InitChrono"                            |
1816 +----------------------------------------------------------------------------+
1817 */
1818
1819 /*
1820 +----------------------------------------------------------------------------+
1821 | Function Name     : _INT_ i_APCI1710_ReadChronoChlValue                    |
1822 |                               (unsigned char_   b_BoardHandle,                      |
1823 |                                unsigned char_   b_ModulNbr,                         |
1824 |                                unsigned char_   b_InputChannel,                     |
1825 |                                unsigned char *_ pb_ChannelStatus)                    |
1826 +----------------------------------------------------------------------------+
1827 | Task              : Return the status from selected digital input          |
1828 |                     (b_InputChannel) from selected chronometer             |
1829 |                     module (b_ModulNbr).                                   |
1830 +----------------------------------------------------------------------------+
1831 | Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
1832 |                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
1833 |                     unsigned char_ b_InputChannel  : Selection from digital input   |
1834 |                                             channel (0 to 2)               |
1835 |                                   CR_CHAN()             0 : Channel E               |
1836 |                                                1 : Channel F               |
1837 |                                                2 : Channel G               |
1838 +----------------------------------------------------------------------------+
1839 | Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel status.|
1840 |                                data[0]                0 : Channel is not active   |
1841 |                                                1 : Channel is active       |
1842 +----------------------------------------------------------------------------+
1843 | Return Value      :  0: No error                                           |
1844 |                     -1: The handle parameter of the board is wrong         |
1845 |                     -2: Module selection wrong                             |
1846 |                     -3: The module is not a Chronometer module             |
1847 |                     -4: The selected digital input is wrong                |
1848 |                     -5: Chronometer not initialised see function           |
1849 |                         "i_APCI1710_InitChrono"                            |
1850 +----------------------------------------------------------------------------+
1851 */
1852
1853 /*
1854 +----------------------------------------------------------------------------+
1855 | Function Name     : _INT_ i_APCI1710_ReadChronoPortValue                   |
1856 |                               (unsigned char_   b_BoardHandle,                      |
1857 |                                unsigned char_   b_ModulNbr,                         |
1858 |                                unsigned char *_ pb_PortValue)                        |
1859 +----------------------------------------------------------------------------+
1860 | Task              : Return the status from digital inputs port from        |
1861 |                     selected  (b_ModulNbr) chronometer module.             |
1862 +----------------------------------------------------------------------------+
1863 | Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
1864 |                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
1865 +----------------------------------------------------------------------------+
1866 | Output Parameters : unsigned char *_ pb_PortValue   : Digital inputs port status.
1867 |                     data[0]
1868 +----------------------------------------------------------------------------+
1869 | Return Value      :  0: No error                                           |
1870 |                     -1: The handle parameter of the board is wrong         |
1871 |                     -2: Module selection wrong                             |
1872 |                     -3: The module is not a Chronometer module             |
1873 |                     -4: Chronometer not initialised see function           |
1874 |                         "i_APCI1710_InitChrono"                            |
1875 +----------------------------------------------------------------------------+
1876 */
1877
1878 int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
1879         struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1880 {
1881         int i_ReturnValue = 0;
1882         unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
1883         unsigned int dw_Status;
1884         unsigned char *pb_ChannelStatus;
1885         unsigned char *pb_PortValue;
1886
1887         b_ModulNbr = CR_AREF(insn->chanspec);
1888         i_ReturnValue = insn->n;
1889         b_IOType = (unsigned char) data[0];
1890
1891         /**************************/
1892         /* Test the module number */
1893         /**************************/
1894
1895         if (b_ModulNbr < 4) {
1896            /***********************/
1897                 /* Test if chronometer */
1898            /***********************/
1899
1900                 if ((devpriv->s_BoardInfos.
1901                                 dw_MolduleConfiguration[b_ModulNbr] &
1902                                 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
1903               /***********************************/
1904                         /* Test if chronometer initialised */
1905               /***********************************/
1906
1907                         if (devpriv->s_ModuleInfo[b_ModulNbr].
1908                                 s_ChronoModuleInfo.b_ChronoInit == 1) {
1909                  /***********************************/
1910                                 /* Test the digital output channel */
1911                  /***********************************/
1912                                 switch (b_IOType) {
1913
1914                                 case APCI1710_CHRONO_SET_CHANNELOFF:
1915
1916                                         b_OutputChannel =
1917                                                 (unsigned char) CR_CHAN(insn->chanspec);
1918                                         if (b_OutputChannel <= 2) {
1919
1920                                                 outl(0, devpriv->s_BoardInfos.
1921                                                         ui_Address + 20 +
1922                                                         (b_OutputChannel * 4) +
1923                                                         (64 * b_ModulNbr));
1924                                         }       /*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
1925                                         else {
1926                     /****************************************/
1927                                                 /* The selected digital output is wrong */
1928                     /****************************************/
1929
1930                                                 DPRINTK("The selected digital output is wrong\n");
1931                                                 i_ReturnValue = -4;
1932
1933                                         }       /*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
1934
1935                                         break;
1936
1937                                 case APCI1710_CHRONO_SET_CHANNELON:
1938
1939                                         b_OutputChannel =
1940                                                 (unsigned char) CR_CHAN(insn->chanspec);
1941                                         if (b_OutputChannel <= 2) {
1942
1943                                                 outl(1, devpriv->s_BoardInfos.
1944                                                         ui_Address + 20 +
1945                                                         (b_OutputChannel * 4) +
1946                                                         (64 * b_ModulNbr));
1947                                         }       /*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
1948                                         else {
1949                     /****************************************/
1950                                                 /* The selected digital output is wrong */
1951                     /****************************************/
1952
1953                                                 DPRINTK("The selected digital output is wrong\n");
1954                                                 i_ReturnValue = -4;
1955
1956                                         }       /*  if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */
1957
1958                                         break;
1959
1960                                 case APCI1710_CHRONO_READ_CHANNEL:
1961                  /**********************************/
1962                                         /* Test the digital input channel */
1963                  /**********************************/
1964                                         pb_ChannelStatus = (unsigned char *) &data[0];
1965                                         b_InputChannel =
1966                                                 (unsigned char) CR_CHAN(insn->chanspec);
1967
1968                                         if (b_InputChannel <= 2) {
1969
1970                                                 dw_Status =
1971                                                         inl(devpriv->
1972                                                         s_BoardInfos.
1973                                                         ui_Address + 12 +
1974                                                         (64 * b_ModulNbr));
1975
1976                                                 *pb_ChannelStatus =
1977                                                         (unsigned char) (((dw_Status >>
1978                                                                         b_InputChannel)
1979                                                                 & 1) ^ 1);
1980                                         }       /*  if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */
1981                                         else {
1982                     /***************************************/
1983                                                 /* The selected digital input is wrong */
1984                     /***************************************/
1985
1986                                                 DPRINTK("The selected digital input is wrong\n");
1987                                                 i_ReturnValue = -4;
1988                                         }       /*  if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */
1989
1990                                         break;
1991
1992                                 case APCI1710_CHRONO_READ_PORT:
1993
1994                                         pb_PortValue = (unsigned char *) &data[0];
1995
1996                                         dw_Status =
1997                                                 inl(devpriv->s_BoardInfos.
1998                                                 ui_Address + 12 +
1999                                                 (64 * b_ModulNbr));
2000
2001                                         *pb_PortValue =
2002                                                 (unsigned char) ((dw_Status & 0x7) ^ 7);
2003                                         break;
2004                                 }
2005                         } else {
2006                  /*******************************/
2007                                 /* Chronometer not initialised */
2008                  /*******************************/
2009
2010                                 DPRINTK("Chronometer not initialised\n");
2011                                 i_ReturnValue = -5;
2012                         }
2013                 } else {
2014               /******************************************/
2015                         /* The module is not a Chronometer module */
2016               /******************************************/
2017
2018                         DPRINTK("The module is not a Chronometer module\n");
2019                         i_ReturnValue = -3;
2020                 }
2021         } else {
2022            /***********************/
2023                 /* Module number error */
2024            /***********************/
2025
2026                 DPRINTK("Module number error\n");
2027                 i_ReturnValue = -2;
2028         }
2029
2030         return i_ReturnValue;
2031 }