APCI1710_Chrono.c revision 25985edcedea6396277003854657b5f3cb31a628
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 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 with    |
128|                         this board                                         |
129|                     -9: You can not used the 40MHz clock selection with    |
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	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 use the 40MHz clock selection with this board */
725			     /**************************************************************/
726
727								DPRINTK("You can not used the 40MHz clock selection with 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			(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
1197int 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
1358int 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
1621int 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
1878int 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}
2032