APCI1710_Chrono.c revision 1783fbfe023b7c2b912fbb020e01ff46985aa0ab
1/**
2@verbatim
3
4Copyright (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
14This 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
16This 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
18You 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
20You shoud 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
134INT 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	ULONG ul_TimerValue = 0;
139	ULONG ul_TimingInterval = 0;
140	ULONG ul_RealTimingInterval = 0;
141	double d_RealTimingInterval = 0;
142	DWORD 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 = (ULONG) 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											(ULONG)
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											(ULONG)
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												(ULONG)
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											(ULONG)
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											(ULONG)
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												(ULONG)
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											(ULONG)
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												(ULONG)
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											(ULONG)
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											(ULONG)
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												(ULONG)
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											(ULONG)
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											(ULONG)
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												(ULONG)
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)
793INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
794struct 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
843INT 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,
1081struct 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
1093INT 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			(UINT) insn->unused[0],
1111			(unsigned char *) & data[0], (PULONG) & 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			(ULONG) insn->unused[0],
1118			(PULONG) & data[0],
1119			(unsigned char *) & data[1],
1120			(unsigned char *) & data[2],
1121			(PUINT) & data[3],
1122			(PUINT) & data[4], (PUINT) & 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
1197INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
1198	unsigned char b_ModulNbr, unsigned char * pb_ChronoStatus)
1199{
1200	INT i_ReturnValue = 0;
1201	DWORD 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|                                UINT_    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|                     PULONG  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
1358INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
1359	unsigned char b_ModulNbr,
1360	UINT ui_TimeOut, unsigned char * pb_ChronoStatus, PULONG pul_ChronoValue)
1361{
1362	INT i_ReturnValue = 0;
1363	DWORD dw_Status;
1364	DWORD 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 >= 0)
1390					&& (ui_TimeOut <= 65535UL)) {
1391
1392					for (;;) {
1393			  /*******************/
1394						/* Read the status */
1395			  /*******************/
1396
1397						dw_Status =
1398							inl(devpriv->
1399							s_BoardInfos.
1400							ui_Address + 8 +
1401							(64 * b_ModulNbr));
1402
1403			  /********************/
1404						/* Test if overflow */
1405			  /********************/
1406
1407						if ((dw_Status & 8) == 8) {
1408			     /******************/
1409							/* Overflow occur */
1410			     /******************/
1411
1412							*pb_ChronoStatus = 3;
1413
1414			     /***************************/
1415							/* Test if continuous mode */
1416			     /***************************/
1417
1418							if (devpriv->
1419								s_ModuleInfo
1420								[b_ModulNbr].
1421								s_ChronoModuleInfo.
1422								b_CycleMode ==
1423								APCI1710_CONTINUOUS)
1424							{
1425				/*************************/
1426								/* Clear status register */
1427				/*************************/
1428
1429								outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
1430							}
1431
1432							break;
1433						}	// if ((dw_Status & 8) == 8)
1434						else {
1435			     /*******************************/
1436							/* Test if measurement stopped */
1437			     /*******************************/
1438
1439							if ((dw_Status & 2) ==
1440								2) {
1441				/***********************/
1442								/* A stop signal occur */
1443				/***********************/
1444
1445								*pb_ChronoStatus
1446									= 2;
1447
1448				/***************************/
1449								/* Test if continnous mode */
1450				/***************************/
1451
1452								if (devpriv->
1453									s_ModuleInfo
1454									[b_ModulNbr].
1455									s_ChronoModuleInfo.
1456									b_CycleMode
1457									==
1458									APCI1710_CONTINUOUS)
1459								{
1460				   /*************************/
1461									/* Clear status register */
1462				   /*************************/
1463
1464									outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
1465								}
1466								break;
1467							}	// if ((dw_Status & 2) == 2)
1468							else {
1469				/*******************************/
1470								/* Test if measurement started */
1471				/*******************************/
1472
1473								if ((dw_Status & 1) == 1) {
1474				   /************************/
1475									/* A start signal occur */
1476				   /************************/
1477
1478									*pb_ChronoStatus
1479										=
1480										1;
1481								}	// if ((dw_Status & 1) == 1)
1482								else {
1483				   /***************************/
1484									/* Measurement not started */
1485				   /***************************/
1486
1487									*pb_ChronoStatus
1488										=
1489										0;
1490								}	// if ((dw_Status & 1) == 1)
1491							}	// if ((dw_Status & 2) == 2)
1492						}	// if ((dw_Status & 8) == 8)
1493
1494						if (dw_TimeOut == ui_TimeOut) {
1495			     /*****************/
1496							/* Timeout occur */
1497			     /*****************/
1498
1499							break;
1500						} else {
1501			     /*************************/
1502							/* Increment the timeout */
1503			     /*************************/
1504
1505							dw_TimeOut =
1506								dw_TimeOut + 1;
1507							mdelay(1000);
1508
1509						}
1510					}	// for (;;)
1511
1512		       /*****************************/
1513					/* Test if stop signal occur */
1514		       /*****************************/
1515
1516					if (*pb_ChronoStatus == 2) {
1517			  /**********************************/
1518						/* Read the measured timing value */
1519			  /**********************************/
1520
1521						*pul_ChronoValue =
1522							inl(devpriv->
1523							s_BoardInfos.
1524							ui_Address + 4 +
1525							(64 * b_ModulNbr));
1526
1527						if (*pul_ChronoValue != 0) {
1528							*pul_ChronoValue =
1529								*pul_ChronoValue
1530								- 1;
1531						}
1532					} else {
1533			  /*************************/
1534						/* Test if timeout occur */
1535			  /*************************/
1536
1537						if ((*pb_ChronoStatus != 3)
1538							&& (dw_TimeOut ==
1539								ui_TimeOut)
1540							&& (ui_TimeOut != 0)) {
1541			     /*****************/
1542							/* Timeout occur */
1543			     /*****************/
1544
1545							*pb_ChronoStatus = 4;
1546						}
1547					}
1548
1549				} else {
1550		    /******************************/
1551					/* Timeout parameter is wrong */
1552		    /******************************/
1553					DPRINTK("Timeout parameter is wrong\n");
1554					i_ReturnValue = -5;
1555				}
1556			} else {
1557		 /*******************************/
1558				/* Chronometer not initialised */
1559		 /*******************************/
1560				DPRINTK("Chronometer not initialised\n");
1561				i_ReturnValue = -4;
1562			}
1563		} else {
1564	      /******************************************/
1565			/* The module is not a Chronometer module */
1566	      /******************************************/
1567			DPRINTK("The module is not a Chronometer module\n");
1568			i_ReturnValue = -3;
1569		}
1570	} else {
1571	   /***********************/
1572		/* Module number error */
1573	   /***********************/
1574		DPRINTK("Module number error\n");
1575		i_ReturnValue = -2;
1576	}
1577
1578	return (i_ReturnValue);
1579}
1580
1581/*
1582+----------------------------------------------------------------------------+
1583| Function Name     : _INT_ i_APCI1710_ConvertChronoValue                    |
1584|                               (unsigned char_     b_BoardHandle,                    |
1585|                                unsigned char_     b_ModulNbr,                       |
1586|                                ULONG_   ul_ChronoValue,                    |
1587|                                PULONG_ pul_Hour,                           |
1588|                                unsigned char *_   pb_Minute,                         |
1589|                                unsigned char *_   pb_Second,                         |
1590|                                PUINT_  pui_MilliSecond,                    |
1591|                                PUINT_  pui_MicroSecond,                    |
1592|                                PUINT_  pui_NanoSecond)                     |
1593+----------------------------------------------------------------------------+
1594| Task              : Convert the chronometer measured timing                |
1595|                     (ul_ChronoValue) in to h, mn, s, ms, µs, ns.           |
1596+----------------------------------------------------------------------------+
1597| Input Parameters  : unsigned char_   b_BoardHandle : Handle of board APCI-1710      |
1598|                     unsigned char_   b_ModulNbr    : Selected module number (0 to 3)|
1599|                     ULONG_ ul_ChronoValue : Measured chronometer timing    |
1600|                                             value.                         |
1601|                                             See"i_APCI1710_ReadChronoValue"|
1602+----------------------------------------------------------------------------+
1603| Output Parameters : PULONG_   pul_Hour        : Chronometer timing hour    |
1604|                     unsigned char *_     pb_Minute      : Chronometer timing minute  |
1605|                     unsigned char *_     pb_Second      : Chronometer timing second  |
1606|                     PUINT_    pui_MilliSecond  : Chronometer timing mini   |
1607|                                                 second                     |
1608|                     PUINT_    pui_MicroSecond : Chronometer timing micro   |
1609|                                                 second                     |
1610|                     PUINT_    pui_NanoSecond  : Chronometer timing nano    |
1611|                                                 second                     |
1612+----------------------------------------------------------------------------+
1613| Return Value      :  0: No error                                           |
1614|                     -1: The handle parameter of the board is wrong         |
1615|                     -2: Module selection wrong                             |
1616|                     -3: The module is not a Chronometer module             |
1617|                     -4: Chronometer not initialised see function           |
1618|                         "i_APCI1710_InitChrono"                            |
1619+----------------------------------------------------------------------------+
1620*/
1621
1622INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
1623	unsigned char b_ModulNbr,
1624	ULONG ul_ChronoValue,
1625	PULONG pul_Hour,
1626	unsigned char * pb_Minute,
1627	unsigned char * pb_Second,
1628	PUINT pui_MilliSecond, PUINT pui_MicroSecond, PUINT pui_NanoSecond)
1629{
1630	INT i_ReturnValue = 0;
1631	double d_Hour;
1632	double d_Minute;
1633	double d_Second;
1634	double d_MilliSecond;
1635	double d_MicroSecond;
1636	double d_NanoSecond;
1637
1638	/**************************/
1639	/* Test the module number */
1640	/**************************/
1641
1642	if (b_ModulNbr < 4) {
1643	   /***********************/
1644		/* Test if chronometer */
1645	   /***********************/
1646
1647		if ((devpriv->s_BoardInfos.
1648				dw_MolduleConfiguration[b_ModulNbr] &
1649				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
1650	      /***********************************/
1651			/* Test if chronometer initialised */
1652	      /***********************************/
1653
1654			if (devpriv->
1655				s_ModuleInfo[b_ModulNbr].
1656				s_ChronoModuleInfo.b_ChronoInit == 1) {
1657				fpu_begin();
1658
1659				d_Hour = (double)ul_ChronoValue *(double)
1660					devpriv->s_ModuleInfo[b_ModulNbr].
1661					s_ChronoModuleInfo.d_TimingInterval;
1662
1663				switch (devpriv->
1664					s_ModuleInfo[b_ModulNbr].
1665					s_ChronoModuleInfo.b_TimingUnit) {
1666				case 0:
1667					d_Hour = d_Hour / (double)1000.0;
1668
1669				case 1:
1670					d_Hour = d_Hour / (double)1000.0;
1671
1672				case 2:
1673					d_Hour = d_Hour / (double)1000.0;
1674
1675				case 3:
1676					d_Hour = d_Hour / (double)60.0;
1677
1678				case 4:
1679			    /**********************/
1680					/* Calculate the hour */
1681			    /**********************/
1682
1683					d_Hour = d_Hour / (double)60.0;
1684					*pul_Hour = (ULONG) d_Hour;
1685
1686			    /************************/
1687					/* Calculate the minute */
1688			    /************************/
1689
1690					d_Minute = d_Hour - *pul_Hour;
1691					d_Minute = d_Minute * 60;
1692					*pb_Minute = (unsigned char) d_Minute;
1693
1694			    /************************/
1695					/* Calculate the second */
1696			    /************************/
1697
1698					d_Second = d_Minute - *pb_Minute;
1699					d_Second = d_Second * 60;
1700					*pb_Second = (unsigned char) d_Second;
1701
1702			    /*****************************/
1703					/* Calculate the mini second */
1704			    /*****************************/
1705
1706					d_MilliSecond = d_Second - *pb_Second;
1707					d_MilliSecond = d_MilliSecond * 1000;
1708					*pui_MilliSecond = (UINT) d_MilliSecond;
1709
1710			    /******************************/
1711					/* Calculate the micro second */
1712			    /******************************/
1713
1714					d_MicroSecond =
1715						d_MilliSecond -
1716						*pui_MilliSecond;
1717					d_MicroSecond = d_MicroSecond * 1000;
1718					*pui_MicroSecond = (UINT) d_MicroSecond;
1719
1720			    /******************************/
1721					/* Calculate the micro second */
1722			    /******************************/
1723
1724					d_NanoSecond =
1725						d_MicroSecond -
1726						*pui_MicroSecond;
1727					d_NanoSecond = d_NanoSecond * 1000;
1728					*pui_NanoSecond = (UINT) d_NanoSecond;
1729					break;
1730				}
1731
1732				fpu_end();
1733			} else {
1734		 /*******************************/
1735				/* Chronometer not initialised */
1736		 /*******************************/
1737				DPRINTK("Chronometer not initialised\n");
1738				i_ReturnValue = -4;
1739			}
1740		} else {
1741	      /******************************************/
1742			/* The module is not a Chronometer module */
1743	      /******************************************/
1744			DPRINTK("The module is not a Chronometer module\n");
1745			i_ReturnValue = -3;
1746		}
1747	} else {
1748	   /***********************/
1749		/* Module number error */
1750	   /***********************/
1751		DPRINTK("Module number error\n");
1752		i_ReturnValue = -2;
1753	}
1754
1755	return (i_ReturnValue);
1756}
1757
1758/*
1759+----------------------------------------------------------------------------+
1760| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
1761	struct comedi_insn *insn,unsigned int *data)                    |
1762+----------------------------------------------------------------------------+
1763| Task              : Sets the output witch has been passed with the         |
1764|                     parameter b_Channel. Setting an output means setting an|
1765|                     output high.                                           |
1766+----------------------------------------------------------------------------+
1767| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
1768|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
1769|                     unsigned char_ b_OutputChannel : Selection from digital output  |
1770|                           CR_CHAN()                  channel (0 to 2)               |
1771|                                              0 : Channel H                 |
1772|                                              1 : Channel A                 |
1773|                                              2 : Channel B                 |
1774+----------------------------------------------------------------------------+
1775| Output Parameters : -                                                      |
1776+----------------------------------------------------------------------------+
1777| Return Value      :  0: No error                                           |
1778|                     -1: The handle parameter of the board is wrong         |
1779|                     -2: Module selection wrong                             |
1780|                     -3: The module is not a Chronometer module             |
1781|                     -4: The selected digital output is wrong               |
1782|                     -5: Chronometer not initialised see function           |
1783|                         "i_APCI1710_InitChrono"                            |
1784+----------------------------------------------------------------------------+
1785*/
1786
1787/*
1788+----------------------------------------------------------------------------+
1789| Function Name     : _INT_ i_APCI1710_SetChronoChlOff                       |
1790|                               (unsigned char_  b_BoardHandle,                       |
1791|                                unsigned char_  b_ModulNbr,                          |
1792|                                unsigned char_  b_OutputChannel)                     |
1793+----------------------------------------------------------------------------+
1794| Task              : Resets the output witch has been passed with the       |
1795|                     parameter b_Channel. Resetting an output means setting |
1796|                     an output low.                                         |
1797+----------------------------------------------------------------------------+
1798| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710
1799                        data[0] : Chl ON, Chl OFF , Chl Read , Port Read
1800
1801|                     unsigned char_ b_ModulNbr  CR_AREF    : Selected module number (0 to 3)|
1802|                     unsigned char_ b_OutputChannel CR_CHAN : Selection from digital output  |
1803|                                             channel (0 to 2)               |
1804|                                              0 : Channel H                 |
1805|                                              1 : Channel A                 |
1806|                                              2 : Channel B                 |
1807+----------------------------------------------------------------------------+
1808| Output Parameters : -                                                      |
1809+----------------------------------------------------------------------------+
1810| Return Value      :  0: No error                                           |
1811|                     -1: The handle parameter of the board is wrong         |
1812|                     -2: Module selection wrong                             |
1813|                     -3: The module is not a Chronometer module             |
1814|                     -4: The selected digital output is wrong               |
1815|                     -5: Chronometer not initialised see function           |
1816|                         "i_APCI1710_InitChrono"                            |
1817+----------------------------------------------------------------------------+
1818*/
1819
1820/*
1821+----------------------------------------------------------------------------+
1822| Function Name     : _INT_ i_APCI1710_ReadChronoChlValue                    |
1823|                               (unsigned char_   b_BoardHandle,                      |
1824|                                unsigned char_   b_ModulNbr,                         |
1825|                                unsigned char_   b_InputChannel,                     |
1826|                                unsigned char *_ pb_ChannelStatus)                    |
1827+----------------------------------------------------------------------------+
1828| Task              : Return the status from selected digital input          |
1829|                     (b_InputChannel) from selected chronometer             |
1830|                     module (b_ModulNbr).                                   |
1831+----------------------------------------------------------------------------+
1832| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
1833|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
1834|                     unsigned char_ b_InputChannel  : Selection from digital input   |
1835|                                             channel (0 to 2)               |
1836|                                   CR_CHAN()             0 : Channel E               |
1837|                                                1 : Channel F               |
1838|                                                2 : Channel G               |
1839+----------------------------------------------------------------------------+
1840| Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel status.|
1841|                                data[0]                0 : Channel is not active   |
1842|                                                1 : Channel is active       |
1843+----------------------------------------------------------------------------+
1844| Return Value      :  0: No error                                           |
1845|                     -1: The handle parameter of the board is wrong         |
1846|                     -2: Module selection wrong                             |
1847|                     -3: The module is not a Chronometer module             |
1848|                     -4: The selected digital input is wrong                |
1849|                     -5: Chronometer not initialised see function           |
1850|                         "i_APCI1710_InitChrono"                            |
1851+----------------------------------------------------------------------------+
1852*/
1853
1854/*
1855+----------------------------------------------------------------------------+
1856| Function Name     : _INT_ i_APCI1710_ReadChronoPortValue                   |
1857|                               (unsigned char_   b_BoardHandle,                      |
1858|                                unsigned char_   b_ModulNbr,                         |
1859|                                unsigned char *_ pb_PortValue)                        |
1860+----------------------------------------------------------------------------+
1861| Task              : Return the status from digital inputs port from        |
1862|                     selected  (b_ModulNbr) chronometer module.             |
1863+----------------------------------------------------------------------------+
1864| Input Parameters  : unsigned char_ b_BoardHandle   : Handle of board APCI-1710      |
1865|                     unsigned char_ b_ModulNbr      : Selected module number (0 to 3)|
1866+----------------------------------------------------------------------------+
1867| Output Parameters : unsigned char *_ pb_PortValue   : Digital inputs port status.
1868|                     data[0]
1869+----------------------------------------------------------------------------+
1870| Return Value      :  0: No error                                           |
1871|                     -1: The handle parameter of the board is wrong         |
1872|                     -2: Module selection wrong                             |
1873|                     -3: The module is not a Chronometer module             |
1874|                     -4: Chronometer not initialised see function           |
1875|                         "i_APCI1710_InitChrono"                            |
1876+----------------------------------------------------------------------------+
1877*/
1878
1879INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
1880	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1881{
1882	INT i_ReturnValue = 0;
1883	unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
1884	DWORD dw_Status;
1885	unsigned char * pb_ChannelStatus;
1886	unsigned char * pb_PortValue;
1887
1888	b_ModulNbr = CR_AREF(insn->chanspec);
1889	i_ReturnValue = insn->n;
1890	b_IOType = (unsigned char) data[0];
1891
1892	/**************************/
1893	/* Test the module number */
1894	/**************************/
1895
1896	if (b_ModulNbr < 4) {
1897	   /***********************/
1898		/* Test if chronometer */
1899	   /***********************/
1900
1901		if ((devpriv->s_BoardInfos.
1902				dw_MolduleConfiguration[b_ModulNbr] &
1903				0xFFFF0000UL) == APCI1710_CHRONOMETER) {
1904	      /***********************************/
1905			/* Test if chronometer initialised */
1906	      /***********************************/
1907
1908			if (devpriv->s_ModuleInfo[b_ModulNbr].
1909				s_ChronoModuleInfo.b_ChronoInit == 1) {
1910		 /***********************************/
1911				/* Test the digital output channel */
1912		 /***********************************/
1913				switch (b_IOType) {
1914
1915				case APCI1710_CHRONO_SET_CHANNELOFF:
1916
1917					b_OutputChannel =
1918						(unsigned char) CR_CHAN(insn->chanspec);
1919					if (b_OutputChannel <= 2) {
1920
1921						outl(0, devpriv->s_BoardInfos.
1922							ui_Address + 20 +
1923							(b_OutputChannel * 4) +
1924							(64 * b_ModulNbr));
1925					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
1926					else {
1927		    /****************************************/
1928						/* The selected digital output is wrong */
1929		    /****************************************/
1930
1931						DPRINTK("The selected digital output is wrong\n");
1932						i_ReturnValue = -4;
1933
1934					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
1935
1936					break;
1937
1938				case APCI1710_CHRONO_SET_CHANNELON:
1939
1940					b_OutputChannel =
1941						(unsigned char) CR_CHAN(insn->chanspec);
1942					if (b_OutputChannel <= 2) {
1943
1944						outl(1, devpriv->s_BoardInfos.
1945							ui_Address + 20 +
1946							(b_OutputChannel * 4) +
1947							(64 * b_ModulNbr));
1948					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
1949					else {
1950		    /****************************************/
1951						/* The selected digital output is wrong */
1952		    /****************************************/
1953
1954						DPRINTK("The selected digital output is wrong\n");
1955						i_ReturnValue = -4;
1956
1957					}	// if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
1958
1959					break;
1960
1961				case APCI1710_CHRONO_READ_CHANNEL:
1962		 /**********************************/
1963					/* Test the digital input channel */
1964		 /**********************************/
1965					pb_ChannelStatus = (unsigned char *) & data[0];
1966					b_InputChannel =
1967						(unsigned char) CR_CHAN(insn->chanspec);
1968
1969					if (b_InputChannel <= 2) {
1970
1971						dw_Status =
1972							inl(devpriv->
1973							s_BoardInfos.
1974							ui_Address + 12 +
1975							(64 * b_ModulNbr));
1976
1977						*pb_ChannelStatus =
1978							(unsigned char) (((dw_Status >>
1979									b_InputChannel)
1980								& 1) ^ 1);
1981					}	// if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
1982					else {
1983		    /***************************************/
1984						/* The selected digital input is wrong */
1985		    /***************************************/
1986
1987						DPRINTK("The selected digital input is wrong\n");
1988						i_ReturnValue = -4;
1989					}	// if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
1990
1991					break;
1992
1993				case APCI1710_CHRONO_READ_PORT:
1994
1995					pb_PortValue = (unsigned char *) & data[0];
1996
1997					dw_Status =
1998						inl(devpriv->s_BoardInfos.
1999						ui_Address + 12 +
2000						(64 * b_ModulNbr));
2001
2002					*pb_PortValue =
2003						(unsigned char) ((dw_Status & 0x7) ^ 7);
2004					break;
2005				}
2006			} else {
2007		 /*******************************/
2008				/* Chronometer not initialised */
2009		 /*******************************/
2010
2011				DPRINTK("Chronometer not initialised\n");
2012				i_ReturnValue = -5;
2013			}
2014		} else {
2015	      /******************************************/
2016			/* The module is not a Chronometer module */
2017	      /******************************************/
2018
2019			DPRINTK("The module is not a Chronometer module\n");
2020			i_ReturnValue = -3;
2021		}
2022	} else {
2023	   /***********************/
2024		/* Module number error */
2025	   /***********************/
2026
2027		DPRINTK("Module number error\n");
2028		i_ReturnValue = -2;
2029	}
2030
2031	return (i_ReturnValue);
2032}
2033