2 * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
7 * Tel: +19(0)7223/9493-0
8 * Fax: +49(0)7223/9493-92
9 * http://www.addi-data-com
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2 of the License, or (at your option)
18 | Description : APCI-1710 82X54 timer module |
21 #include "APCI1710_82x54.h"
24 +----------------------------------------------------------------------------+
25 | Function Name : _INT_ i_APCI1710_InitTimer |
26 | (unsigned char_ b_BoardHandle, |
27 | unsigned char_ b_ModulNbr, |
28 | unsigned char_ b_TimerNbr, |
29 | unsigned char_ b_TimerMode, |
30 | ULONG_ ul_ReloadValue, |
31 | unsigned char_ b_InputClockSelection, |
32 | unsigned char_ b_InputClockLevel, |
33 | unsigned char_ b_OutputLevel, |
34 | unsigned char_ b_HardwareGateLevel)
35 int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
36 struct comedi_insn *insn,unsigned int *data)
38 +----------------------------------------------------------------------------+
39 | Task : Configure the Timer (b_TimerNbr) operating mode |
40 | (b_TimerMode) from selected module (b_ModulNbr). |
41 | You must calling this function be for you call any |
42 | other function witch access of the timer. |
45 | Timer mode description table |
47 |+--------+-----------------------------+--------------+--------------------+|
48 ||Selected+ Mode description +u_ReloadValue | Hardware gate input||
49 || mode | | description | action ||
50 |+--------+-----------------------------+--------------+--------------------+|
51 || |Mode 0 is typically used | | ||
52 || |for event counting. After | | ||
53 || |the initialisation, OUT | | ||
54 || |is initially low, and | | ||
55 || 0 |will remain low until the |Start counting| Hardware gate ||
56 || |counter reaches zero. | value | ||
57 || |OUT then goes high and | | ||
58 || |remains high until a new | | ||
59 || |count is written. See | | ||
60 || |"i_APCI1710_WriteTimerValue" | | ||
62 |+--------+-----------------------------+--------------+--------------------+|
63 || |Mode 1 is similar to mode 0 | | ||
64 || |except for the gate input | | ||
65 || 1 |action. The gate input is not|Start counting| Hardware trigger ||
66 || |used for enabled or disabled | value | ||
68 || |The gate input is used for | | ||
69 || |triggered the timer. | | ||
70 |+--------+-----------------------------+--------------+--------------------+|
71 || |This mode functions like a | | ||
72 || |divide-by-ul_ReloadValue | | ||
73 || |counter. It is typically used| | ||
74 || |to generate a real time clock| | ||
75 || |interrupt. OUT will initially| | ||
76 || 2 |be high after the | Division | Hardware gate ||
77 || |initialisation. When the | factor | ||
78 || |initial count has decremented| | ||
79 || |to 1, OUT goes low for one | | ||
80 || |CLK pule. OUT then goes high | | ||
81 || |again, the counter reloads | | ||
82 || |the initial count | | ||
83 || |(ul_ReloadValue) and the | | ||
84 || |process is repeated. | | ||
85 || |This action can generated a | | ||
86 || |interrupt. See function | | ||
87 || |"i_APCI1710_SetBoardInt- | | ||
89 || |and "i_APCI1710_EnableTimer" | | ||
90 |+--------+-----------------------------+--------------+--------------------+|
91 || |Mode 3 is typically used for | | ||
92 || |baud rate generation. This | | ||
93 || |mode is similar to mode 2 | | ||
94 || |except for the duty cycle of | | ||
95 || 3 |OUT. OUT will initially be | Division | Hardware gate ||
96 || |high after the initialisation| factor | ||
97 || |When half the initial count | | ||
98 || |(ul_ReloadValue) has expired,| | ||
99 || |OUT goes low for the | | ||
100 || |remainder of the count. The | | ||
101 || |mode is periodic; the | | ||
102 || |sequence above is repeated | | ||
103 || |indefinitely. | | ||
104 |+--------+-----------------------------+--------------+--------------------+|
105 || |OUT will be initially high | | ||
106 || |after the initialisation. | | ||
107 || |When the initial count | | ||
108 || 4 |expires OUT will go low for |Start counting| Hardware gate ||
109 || |one CLK pulse and then go | value | ||
110 || |high again. | | ||
111 || |The counting sequences is | | ||
112 || |triggered by writing a new | | ||
113 || |value. See | | ||
114 || |"i_APCI1710_WriteTimerValue" | | ||
115 || |function. If a new count is | | ||
116 || |written during counting, | | ||
117 || |it will be loaded on the | | ||
118 || |next CLK pulse | | ||
119 |+--------+-----------------------------+--------------+--------------------+|
120 || |Mode 5 is similar to mode 4 | | ||
121 || |except for the gate input | | ||
122 || |action. The gate input is not| | ||
123 || 5 |used for enabled or disabled |Start counting| Hardware trigger ||
124 || |the timer. The gate input is | value | ||
125 || |used for triggered the timer.| | ||
126 |+--------+-----------------------------+--------------+--------------------+|
130 | Input clock selection table |
132 | +--------------------------------+------------------------------------+ |
133 | | b_InputClockSelection | Description | |
135 | +--------------------------------+------------------------------------+ |
136 | | APCI1710_PCI_BUS_CLOCK | For the timer input clock, the PCI | |
137 | | | bus clock / 4 is used. This PCI bus| |
138 | | | clock can be 30MHz or 33MHz. For | |
139 | | | Timer 0 only this selection are | |
141 | +--------------------------------+------------------------------------+ |
142 | | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the| |
143 | | | possibility to inject a input clock| |
144 | | | for Timer 1 or Timer 2. The source | |
145 | | | from this clock can eat the output | |
146 | | | clock from Timer 0 or any other | |
147 | | | clock source. | |
148 | +--------------------------------+------------------------------------+ |
150 +----------------------------------------------------------------------------+
151 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board |
153 | unsigned char_ b_ModulNbr : Module number to |
154 | configure (0 to 3) |
155 | unsigned char_ b_TimerNbr : Timer number to |
156 | configure (0 to 2) |
157 | unsigned char_ b_TimerMode : Timer mode selection |
159 | 0: Interrupt on terminal|
162 | retriggerable one- |
164 | 2: Rate generator |
165 | 3: Square wave mode |
166 | 4: Software triggered |
168 | 5: Hardware triggered |
171 | description table. |
172 | ULONG_ ul_ReloadValue : Start counting value |
173 | or division factor |
175 | description table. |
176 | unsigned char_ b_InputClockSelection : Selection from input |
180 | unsigned char_ b_InputClockLevel : Selection from input |
185 | unsigned char_ b_OutputLevel, : Selection from output |
189 | (Output inverted) |
190 | unsigned char_ b_HardwareGateLevel : Selection from |
191 | hardware gate level. |
195 | If you will not used |
196 | the hardware gate set |
198 |b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
199 b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
200 b_TimerMode = (unsigned char) data[0];
201 ul_ReloadValue = (unsigned int) data[1];
202 b_InputClockSelection =(unsigned char) data[2];
203 b_InputClockLevel =(unsigned char) data[3];
204 b_OutputLevel =(unsigned char) data[4];
205 b_HardwareGateLevel =(unsigned char) data[5];
206 +----------------------------------------------------------------------------+
207 | Output Parameters : - |
208 +----------------------------------------------------------------------------+
209 | Return Value : 0: No error |
210 | -1: The handle parameter of the board is wrong |
211 | -2: Module selection wrong |
212 | -3: Timer selection wrong |
213 | -4: The module is not a TIMER module |
214 | -5: Timer mode selection is wrong |
215 | -6: Input timer clock selection is wrong |
216 | -7: Selection from input clock level is wrong |
217 | -8: Selection from output clock level is wrong |
218 | -9: Selection from hardware gate level is wrong |
219 +----------------------------------------------------------------------------+
222 int i_APCI1710_InsnConfigInitTimer(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
223 struct comedi_insn
*insn
, unsigned int *data
)
226 int i_ReturnValue
= 0;
227 unsigned char b_ModulNbr
;
228 unsigned char b_TimerNbr
;
229 unsigned char b_TimerMode
;
230 unsigned int ul_ReloadValue
;
231 unsigned char b_InputClockSelection
;
232 unsigned char b_InputClockLevel
;
233 unsigned char b_OutputLevel
;
234 unsigned char b_HardwareGateLevel
;
236 /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
237 unsigned int dw_Test
= 0;
238 /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
240 i_ReturnValue
= insn
->n
;
241 b_ModulNbr
= (unsigned char) CR_AREF(insn
->chanspec
);
242 b_TimerNbr
= (unsigned char) CR_CHAN(insn
->chanspec
);
243 b_TimerMode
= (unsigned char) data
[0];
244 ul_ReloadValue
= (unsigned int) data
[1];
245 b_InputClockSelection
= (unsigned char) data
[2];
246 b_InputClockLevel
= (unsigned char) data
[3];
247 b_OutputLevel
= (unsigned char) data
[4];
248 b_HardwareGateLevel
= (unsigned char) data
[5];
250 /* Test the module number */
251 if (b_ModulNbr
< 4) {
252 /* Test if 82X54 timer */
253 if ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0xFFFF0000UL
) == APCI1710_82X54_TIMER
) {
254 /* Test the timer number */
256 if (b_TimerNbr
<= 2) {
257 /* Test the timer mode */
258 if (b_TimerMode
<= 5) {
259 /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
260 /* Test te imput clock selection */
262 if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||
263 ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1))))
266 if (((b_TimerNbr
== 0) &&
267 (b_InputClockSelection
== APCI1710_PCI_BUS_CLOCK
)) ||
268 ((b_TimerNbr
== 0) &&
269 (b_InputClockSelection
== APCI1710_10MHZ
)) ||
270 ((b_TimerNbr
!= 0) &&
271 ((b_InputClockSelection
== APCI1710_PCI_BUS_CLOCK
) ||
272 (b_InputClockSelection
== APCI1710_FRONT_CONNECTOR_INPUT
) ||
273 (b_InputClockSelection
== APCI1710_10MHZ
)))) {
274 /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
275 if (((b_InputClockSelection
== APCI1710_10MHZ
) &&
276 ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0x0000FFFFUL
) >= 0x3131)) ||
277 (b_InputClockSelection
!= APCI1710_10MHZ
)) {
278 /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
279 /* Test the input clock level selection */
281 if ((b_InputClockLevel
== 0) ||
282 (b_InputClockLevel
== 1)) {
283 /* Test the output clock level selection */
284 if ((b_OutputLevel
== 0) || (b_OutputLevel
== 1)) {
285 /* Test the hardware gate level selection */
286 if ((b_HardwareGateLevel
== 0) || (b_HardwareGateLevel
== 1)) {
287 /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
288 /* Test if version > 1.1 and clock selection = 10MHz */
289 if ((b_InputClockSelection
== APCI1710_10MHZ
) && ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0x0000FFFFUL
) > 0x3131)) {
290 /* Test if 40MHz quartz on board */
291 dw_Test
= inl(devpriv
->s_BoardInfos
.ui_Address
+ (16 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
)));
293 dw_Test
= (dw_Test
>> 16) & 1;
298 /* Test if detection OK */
300 /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
301 /* Initialisation OK */
302 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_82X54Init
= 1;
304 /* Save the input clock selection */
305 devpriv
-> s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_InputClockSelection
= b_InputClockSelection
;
307 /* Save the input clock level */
308 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_InputClockLevel
= ~b_InputClockLevel
& 1;
310 /* Save the output level */
311 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_OutputLevel
= ~b_OutputLevel
& 1;
313 /* Save the gate level */
314 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_HardwareGateLevel
= b_HardwareGateLevel
;
316 /* Set the configuration word and disable the timer */
317 /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
319 devpriv->s_ModuleInfo [b_ModulNbr].
321 s_82X54TimerInfo [b_TimerNbr].
322 dw_ConfigurationWord = (unsigned int) (((b_HardwareGateLevel << 0) & 0x1) |
323 ((b_InputClockLevel << 1) & 0x2) |
324 (((~b_OutputLevel & 1) << 2) & 0x4) |
325 ((b_InputClockSelection << 4) & 0x10));
327 /* Test if 10MHz selected */
328 if (b_InputClockSelection
== APCI1710_10MHZ
) {
329 b_InputClockSelection
= 2;
332 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
= (unsigned int)(((b_HardwareGateLevel
<< 0) & 0x1) | ((b_InputClockLevel
<< 1) & 0x2) | (((~b_OutputLevel
& 1) << 2) & 0x4) | ((b_InputClockSelection
<< 4) & 0x30));
333 /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
334 outl(devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
, devpriv
->s_BoardInfos
.ui_Address
+ 32 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
336 /* Initialise the 82X54 Timer */
337 outl((unsigned int) b_TimerMode
, devpriv
->s_BoardInfos
.ui_Address
+ 16 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
339 /* Write the reload value */
340 outl(ul_ReloadValue
, devpriv
->s_BoardInfos
.ui_Address
+ 0 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
341 /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
342 } /* if (dw_Test == 1) */
344 /* Input timer clock selection is wrong */
346 } /* if (dw_Test == 1) */
347 /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
348 } /* if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
350 /* Selection from hardware gate level is wrong */
351 DPRINTK("Selection from hardware gate level is wrong\n");
353 } /* if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
354 } /* if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
356 /* Selection from output clock level is wrong */
357 DPRINTK("Selection from output clock level is wrong\n");
359 } /* if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
360 } /* if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
362 /* Selection from input clock level is wrong */
363 DPRINTK("Selection from input clock level is wrong\n");
365 } /* if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
367 /* Input timer clock selection is wrong */
368 DPRINTK("Input timer clock selection is wrong\n");
372 /* Input timer clock selection is wrong */
373 DPRINTK("Input timer clock selection is wrong\n");
376 } /* if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
378 /* Timer mode selection is wrong */
379 DPRINTK("Timer mode selection is wrong\n");
381 } /* if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
382 } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
384 /* Timer selection wrong */
385 DPRINTK("Timer selection wrong\n");
387 } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
389 /* The module is not a TIMER module */
390 DPRINTK("The module is not a TIMER module\n");
394 /* Module number error */
395 DPRINTK("Module number error\n");
399 return (i_ReturnValue
);
403 +----------------------------------------------------------------------------+
404 | Function Name : _INT_ i_APCI1710_EnableTimer |
405 | (unsigned char_ b_BoardHandle, |
406 | unsigned char_ b_ModulNbr, |
407 | unsigned char_ b_TimerNbr, |
408 | unsigned char_ b_InterruptEnable)
409 int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
410 struct comedi_insn *insn,unsigned int *data) |
411 +----------------------------------------------------------------------------+
412 | Task : Enable OR Disable the Timer (b_TimerNbr) from selected module |
413 | (b_ModulNbr). You must calling the |
414 | "i_APCI1710_InitTimer" function be for you call this |
415 | function. If you enable the timer interrupt, the timer |
416 | generate a interrupt after the timer value reach |
417 | the zero. See function "i_APCI1710_SetBoardIntRoutineX"|
418 +----------------------------------------------------------------------------+
419 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board |
421 | unsigned char_ b_ModulNbr : Selected module number |
423 | unsigned char_ b_TimerNbr : Timer number to enable |
425 | unsigned char_ b_InterruptEnable : Enable or disable the |
427 | APCI1710_ENABLE : |
428 | Enable the timer interrupt |
429 | APCI1710_DISABLE : |
430 | Disable the timer interrupt|
431 i_ReturnValue=insn->n;
432 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
433 b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
434 b_ActionType = (unsigned char) data[0]; /* enable disable */
435 +----------------------------------------------------------------------------+
436 | Output Parameters
: - |
437 +----------------------------------------------------------------------------+
438 | Return Value
: 0: No error
|
439 | -1: The handle parameter of the board is wrong
|
440 | -2: Module selection wrong
|
441 | -3: Timer selection wrong
|
442 | -4: The module is
not a TIMER module
|
443 | -5: Timer
not initialised see function
|
444 | "i_APCI1710_InitTimer" |
445 | -6: Interrupt parameter is wrong
|
446 | -7: Interrupt function
not initialised
. |
447 | See function
"i_APCI1710_SetBoardIntRoutineX" |
448 +----------------------------------------------------------------------------+
451 int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device
*dev
,
452 struct comedi_subdevice
*s
,
453 struct comedi_insn
*insn
, unsigned int *data
)
455 int i_ReturnValue
= 0;
456 unsigned int dw_DummyRead
;
457 unsigned char b_ModulNbr
;
458 unsigned char b_TimerNbr
;
459 unsigned char b_ActionType
;
460 unsigned char b_InterruptEnable
;
462 i_ReturnValue
= insn
->n
;
463 b_ModulNbr
= (unsigned char) CR_AREF(insn
->chanspec
);
464 b_TimerNbr
= (unsigned char) CR_CHAN(insn
->chanspec
);
465 b_ActionType
= (unsigned char) data
[0]; /* enable disable */
467 /* Test the module number */
468 if (b_ModulNbr
< 4) {
469 /* Test if 82X54 timer */
470 if ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0xFFFF0000UL
) == APCI1710_82X54_TIMER
) {
471 /* Test the timer number */
472 if (b_TimerNbr
<= 2) {
473 /* Test if timer initialised */
474 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_82X54Init
== 1) {
476 switch (b_ActionType
) {
477 case APCI1710_ENABLE
:
478 b_InterruptEnable
= (unsigned char) data
[1];
479 /* Test the interrupt selection */
480 if ((b_InterruptEnable
== APCI1710_ENABLE
) ||
481 (b_InterruptEnable
== APCI1710_DISABLE
)) {
482 if (b_InterruptEnable
== APCI1710_ENABLE
) {
484 dw_DummyRead
= inl(devpriv
->s_BoardInfos
.ui_Address
+ 12 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
486 /* Enable the interrupt */
487 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
= devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
| 0x8;
489 outl(devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
, devpriv
->s_BoardInfos
.ui_Address
+ 32 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
490 devpriv
->tsk_Current
= current
; /* Save the current process task structure */
492 } /* if (b_InterruptEnable == APCI1710_ENABLE) */
494 /* Disable the interrupt */
495 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
= devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
& 0xF7;
497 outl(devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
, devpriv
->s_BoardInfos
.ui_Address
+ 32 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
499 /* Save the interrupt flag */
500 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.b_InterruptMask
= devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.b_InterruptMask
& (0xFF - (1 << b_TimerNbr
));
501 } /* if (b_InterruptEnable == APCI1710_ENABLE) */
503 /* Test if error occur */
504 if (i_ReturnValue
>= 0) {
505 /* Save the interrupt flag */
506 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.b_InterruptMask
= devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.b_InterruptMask
| ((1 & b_InterruptEnable
) << b_TimerNbr
);
508 /* Enable the timer */
509 outl(1, devpriv
->s_BoardInfos
.ui_Address
+ 44 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
512 /* Interrupt parameter is wrong */
517 case APCI1710_DISABLE
:
518 /* Test the interrupt flag */
519 if (((devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.b_InterruptMask
>> b_TimerNbr
) & 1) == 1) {
520 /* Disable the interrupt */
522 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
]. dw_ConfigurationWord
= devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
& 0xF7;
524 outl(devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].dw_ConfigurationWord
, devpriv
->s_BoardInfos
.ui_Address
+ 32 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
526 /* Save the interrupt flag */
527 devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.b_InterruptMask
= devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.b_InterruptMask
& (0xFF - (1 << b_TimerNbr
));
530 /* Disable the timer */
531 outl(0, devpriv
->s_BoardInfos
.ui_Address
+ 44 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
535 /* Timer not initialised see function */
536 DPRINTK ("Timer not initialised see function\n");
540 /* Timer selection wrong */
541 DPRINTK("Timer selection wrong\n");
543 } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
545 /* The module is not a TIMER module */
546 DPRINTK("The module is not a TIMER module\n");
550 /* Module number error */
551 DPRINTK("Module number error\n");
555 return (i_ReturnValue
);
559 +----------------------------------------------------------------------------+
560 | Function Name : _INT_ i_APCI1710_ReadAllTimerValue |
561 | (unsigned char_ b_BoardHandle, |
562 | unsigned char_ b_ModulNbr, |
563 | PULONG_ pul_TimerValueArray)
564 int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
565 struct comedi_insn *insn,unsigned int *data) |
566 +----------------------------------------------------------------------------+
567 | Task : Return the all timer values from selected timer |
568 | module (b_ModulNbr). |
569 +----------------------------------------------------------------------------+
570 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board |
572 | unsigned char_ b_ModulNbr : Selected module number |
574 +----------------------------------------------------------------------------+
575 | Output Parameters : PULONG_ pul_TimerValueArray : Timer value array. |
576 | Element 0 contain the timer 0 value. |
577 | Element 1 contain the timer 1 value. |
578 | Element 2 contain the timer 2 value. |
579 +----------------------------------------------------------------------------+
580 | Return Value : 0: No error |
581 | -1: The handle parameter of the board is wrong |
582 | -2: Module selection wrong |
583 | -3: The module is not a TIMER module |
584 | -4: Timer 0 not initialised see function |
585 | "i_APCI1710_InitTimer" |
586 | -5: Timer 1 not initialised see function |
587 | "i_APCI1710_InitTimer" |
588 | -6: Timer 2 not initialised see function |
589 | "i_APCI1710_InitTimer" |
590 +----------------------------------------------------------------------------+
593 int i_APCI1710_InsnReadAllTimerValue(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
594 struct comedi_insn
*insn
, unsigned int *data
)
596 int i_ReturnValue
= 0;
597 unsigned char b_ModulNbr
, b_ReadType
;
598 unsigned int *pul_TimerValueArray
;
600 b_ModulNbr
= CR_AREF(insn
->chanspec
);
601 b_ReadType
= CR_CHAN(insn
->chanspec
);
602 pul_TimerValueArray
= (unsigned int *) data
;
603 i_ReturnValue
= insn
->n
;
605 switch (b_ReadType
) {
606 case APCI1710_TIMER_READINTERRUPT
:
608 data
[0] = devpriv
->s_InterruptParameters
.s_FIFOInterruptParameters
[devpriv
->s_InterruptParameters
.ui_Read
].b_OldModuleMask
;
609 data
[1] = devpriv
->s_InterruptParameters
.s_FIFOInterruptParameters
[devpriv
->s_InterruptParameters
.ui_Read
].ul_OldInterruptMask
;
610 data
[2] = devpriv
->s_InterruptParameters
.s_FIFOInterruptParameters
[devpriv
->s_InterruptParameters
.ui_Read
].ul_OldCounterLatchValue
;
612 /* Increment the read FIFO */
613 devpriv
->s_InterruptParameters
.ui_Read
= (devpriv
->s_InterruptParameters
.ui_Read
+ 1) % APCI1710_SAVE_INTERRUPT
;
617 case APCI1710_TIMER_READALLTIMER
:
618 /* Test the module number */
619 if (b_ModulNbr
< 4) {
620 /* Test if 82X54 timer */
621 if ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0xFFFF0000UL
) == APCI1710_82X54_TIMER
) {
622 /* Test if timer 0 iniutialised */
623 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[0].b_82X54Init
== 1) {
624 /* Test if timer 1 iniutialised */
625 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[1].b_82X54Init
== 1) {
626 /* Test if timer 2 iniutialised */
627 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[2].b_82X54Init
== 1) {
628 /* Latch all counter */
629 outl(0x17, devpriv
->s_BoardInfos
.ui_Address
+ 12 + (64 * b_ModulNbr
));
631 /* Read the timer 0 value */
632 pul_TimerValueArray
[0] = inl(devpriv
->s_BoardInfos
.ui_Address
+ 0 + (64 * b_ModulNbr
));
634 /* Read the timer 1 value */
635 pul_TimerValueArray
[1] = inl(devpriv
->s_BoardInfos
.ui_Address
+ 4 + (64 * b_ModulNbr
));
637 /* Read the timer 2 value */
638 pul_TimerValueArray
[2] = inl(devpriv
->s_BoardInfos
.ui_Address
+ 8 + (64 * b_ModulNbr
));
640 /* Timer 2 not initialised see function */
641 DPRINTK("Timer 2 not initialised see function\n");
645 /* Timer 1 not initialised see function */
646 DPRINTK("Timer 1 not initialised see function\n");
650 /* Timer 0 not initialised see function */
651 DPRINTK("Timer 0 not initialised see function\n");
655 /* The module is not a TIMER module */
656 DPRINTK("The module is not a TIMER module\n");
660 /* Module number error */
661 DPRINTK("Module number error\n");
665 } /* End of Switch */
666 return (i_ReturnValue
);
670 +----------------------------------------------------------------------------+
671 | Function Name :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
672 struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
673 +----------------------------------------------------------------------------+
674 | Task : Read write functions for Timer |
675 +----------------------------------------------------------------------------+
677 +----------------------------------------------------------------------------+
678 | Output Parameters : - |
679 +----------------------------------------------------------------------------+
681 +----------------------------------------------------------------------------+
684 int i_APCI1710_InsnBitsTimer(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
685 struct comedi_insn
*insn
, unsigned int *data
)
687 unsigned char b_BitsType
;
688 int i_ReturnValue
= 0;
689 b_BitsType
= data
[0];
693 switch (b_BitsType
) {
694 case APCI1710_TIMER_READVALUE
:
695 i_ReturnValue
= i_APCI1710_ReadTimerValue(dev
,
696 (unsigned char)CR_AREF(insn
->chanspec
),
697 (unsigned char)CR_CHAN(insn
->chanspec
),
698 (unsigned int *) & data
[0]);
701 case APCI1710_TIMER_GETOUTPUTLEVEL
:
702 i_ReturnValue
= i_APCI1710_GetTimerOutputLevel(dev
,
703 (unsigned char)CR_AREF(insn
->chanspec
),
704 (unsigned char)CR_CHAN(insn
->chanspec
),
705 (unsigned char *) &data
[0]);
708 case APCI1710_TIMER_GETPROGRESSSTATUS
:
709 i_ReturnValue
= i_APCI1710_GetTimerProgressStatus(dev
,
710 (unsigned char)CR_AREF(insn
->chanspec
),
711 (unsigned char)CR_CHAN(insn
->chanspec
),
712 (unsigned char *)&data
[0]);
715 case APCI1710_TIMER_WRITEVALUE
:
716 i_ReturnValue
= i_APCI1710_WriteTimerValue(dev
,
717 (unsigned char)CR_AREF(insn
->chanspec
),
718 (unsigned char)CR_CHAN(insn
->chanspec
),
719 (unsigned int)data
[1]);
724 printk("Bits Config Parameter Wrong\n");
728 if (i_ReturnValue
>= 0)
729 i_ReturnValue
= insn
->n
;
730 return (i_ReturnValue
);
734 +----------------------------------------------------------------------------+
735 | Function Name : _INT_ i_APCI1710_ReadTimerValue |
736 | (unsigned char_ b_BoardHandle, |
737 | unsigned char_ b_ModulNbr, |
738 | unsigned char_ b_TimerNbr, |
739 | PULONG_ pul_TimerValue) |
740 +----------------------------------------------------------------------------+
741 | Task : Return the timer value from selected digital timer |
742 | (b_TimerNbr) from selected timer module (b_ModulNbr). |
743 +----------------------------------------------------------------------------+
744 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board |
746 | unsigned char_ b_ModulNbr : Selected module number |
748 | unsigned char_ b_TimerNbr : Timer number to read |
750 +----------------------------------------------------------------------------+
751 | Output Parameters : PULONG_ pul_TimerValue : Timer value |
752 +----------------------------------------------------------------------------+
753 | Return Value : 0: No error |
754 | -1: The handle parameter of the board is wrong |
755 | -2: Module selection wrong |
756 | -3: Timer selection wrong |
757 | -4: The module is not a TIMER module |
758 | -5: Timer not initialised see function |
759 | "i_APCI1710_InitTimer" |
760 +----------------------------------------------------------------------------+
763 int i_APCI1710_ReadTimerValue(struct comedi_device
*dev
,
764 unsigned char b_ModulNbr
, unsigned char b_TimerNbr
,
765 unsigned int *pul_TimerValue
)
767 int i_ReturnValue
= 0;
769 /* Test the module number */
770 if (b_ModulNbr
< 4) {
771 /* Test if 82X54 timer */
772 if ((devpriv
->s_BoardInfos
.
773 dw_MolduleConfiguration
[b_ModulNbr
] &
774 0xFFFF0000UL
) == APCI1710_82X54_TIMER
) {
775 /* Test the timer number */
776 if (b_TimerNbr
<= 2) {
777 /* Test if timer initialised */
779 s_ModuleInfo
[b_ModulNbr
].
781 s_82X54TimerInfo
[b_TimerNbr
].
783 /* Latch the timer value */
784 outl((2 << b_TimerNbr
) | 0xD0,
785 devpriv
->s_BoardInfos
.
789 /* Read the counter value */
791 inl(devpriv
->s_BoardInfos
.
792 ui_Address
+ (b_TimerNbr
* 4) +
795 /* Timer not initialised see function */
796 DPRINTK("Timer not initialised see function\n");
800 /* Timer selection wrong */
801 DPRINTK("Timer selection wrong\n");
803 } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
805 /* The module is not a TIMER module */
806 DPRINTK("The module is not a TIMER module\n");
810 /* Module number error */
811 DPRINTK("Module number error\n");
815 return (i_ReturnValue
);
819 +----------------------------------------------------------------------------+
820 | Function Name : _INT_ i_APCI1710_GetTimerOutputLevel |
821 | (unsigned char_ b_BoardHandle, |
822 | unsigned char_ b_ModulNbr, |
823 | unsigned char_ b_TimerNbr, |
824 | unsigned char *_ pb_OutputLevel) |
825 +----------------------------------------------------------------------------+
826 | Task : Return the output signal level (pb_OutputLevel) from |
827 | selected digital timer (b_TimerNbr) from selected timer|
828 | module (b_ModulNbr). |
829 +----------------------------------------------------------------------------+
830 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board |
832 | unsigned char_ b_ModulNbr : Selected module number |
834 | unsigned char_ b_TimerNbr : Timer number to test |
836 +----------------------------------------------------------------------------+
837 | Output Parameters : unsigned char *_ pb_OutputLevel : Output signal level |
838 | 0 : The output is low |
839 | 1 : The output is high |
840 +----------------------------------------------------------------------------+
841 | Return Value : 0: No error |
842 | -1: The handle parameter of the board is wrong |
843 | -2: Module selection wrong |
844 | -3: Timer selection wrong |
845 | -4: The module is not a TIMER module |
846 | -5: Timer not initialised see function |
847 | "i_APCI1710_InitTimer" |
848 +----------------------------------------------------------------------------+
851 int i_APCI1710_GetTimerOutputLevel(struct comedi_device
*dev
,
852 unsigned char b_ModulNbr
, unsigned char b_TimerNbr
,
853 unsigned char *pb_OutputLevel
)
855 int i_ReturnValue
= 0;
856 unsigned int dw_TimerStatus
;
858 /* Test the module number */
859 if (b_ModulNbr
< 4) {
860 /* Test if 82X54 timer */
861 if ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0xFFFF0000UL
) == APCI1710_82X54_TIMER
) {
862 /* Test the timer number */
863 if (b_TimerNbr
<= 2) {
864 /* Test if timer initialised */
865 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_82X54Init
== 1) {
866 /* Latch the timer value */
867 outl((2 << b_TimerNbr
) | 0xE0, devpriv
->s_BoardInfos
.ui_Address
+ 12 + (64 * b_ModulNbr
));
869 /* Read the timer status */
870 dw_TimerStatus
= inl(devpriv
->s_BoardInfos
.ui_Address
+ 16 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
872 *pb_OutputLevel
= (unsigned char) (((dw_TimerStatus
>> 7) & 1) ^ devpriv
-> s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_OutputLevel
);
874 /* Timer not initialised see function */
875 DPRINTK("Timer not initialised see function\n");
879 /* Timer selection wrong */
880 DPRINTK("Timer selection wrong\n");
882 } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
884 /* The module is not a TIMER module */
885 DPRINTK("The module is not a TIMER module\n");
889 /* Module number error */
890 DPRINTK("Module number error\n");
894 return (i_ReturnValue
);
898 +----------------------------------------------------------------------------+
899 | Function Name : _INT_ i_APCI1710_GetTimerProgressStatus |
900 | (unsigned char_ b_BoardHandle, |
901 | unsigned char_ b_ModulNbr, |
902 | unsigned char_ b_TimerNbr, |
903 | unsigned char *_ pb_TimerStatus) |
904 +----------------------------------------------------------------------------+
905 | Task : Return the progress status (pb_TimerStatus) from |
906 | selected digital timer (b_TimerNbr) from selected timer|
907 | module (b_ModulNbr). |
908 +----------------------------------------------------------------------------+
909 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board |
911 | unsigned char_ b_ModulNbr : Selected module number |
913 | unsigned char_ b_TimerNbr : Timer number to test |
915 +----------------------------------------------------------------------------+
916 | Output Parameters : unsigned char *_ pb_TimerStatus : Output signal level |
917 | 0 : Timer not in progress |
918 | 1 : Timer in progress |
919 +----------------------------------------------------------------------------+
920 | Return Value : 0: No error |
921 | -1: The handle parameter of the board is wrong |
922 | -2: Module selection wrong |
923 | -3: Timer selection wrong |
924 | -4: The module is not a TIMER module |
925 | -5: Timer not initialised see function |
926 | "i_APCI1710_InitTimer" |
927 +----------------------------------------------------------------------------+
930 int i_APCI1710_GetTimerProgressStatus(struct comedi_device
*dev
,
931 unsigned char b_ModulNbr
, unsigned char b_TimerNbr
,
932 unsigned char *pb_TimerStatus
)
934 int i_ReturnValue
= 0;
935 unsigned int dw_TimerStatus
;
937 /* Test the module number */
938 if (b_ModulNbr
< 4) {
939 /* Test if 82X54 timer */
941 if ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0xFFFF0000UL
) == APCI1710_82X54_TIMER
) {
942 /* Test the timer number */
943 if (b_TimerNbr
<= 2) {
944 /* Test if timer initialised */
945 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_82X54Init
== 1) {
946 /* Latch the timer value */
947 outl((2 << b_TimerNbr
) | 0xE0, devpriv
->s_BoardInfos
.ui_Address
+ 12 + (64 * b_ModulNbr
));
949 /* Read the timer status */
950 dw_TimerStatus
= inl(devpriv
->s_BoardInfos
.ui_Address
+ 16 + (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
952 *pb_TimerStatus
= (unsigned char) ((dw_TimerStatus
) >> 8) & 1;
953 printk("ProgressStatus : %d", *pb_TimerStatus
);
955 /* Timer not initialised see function */
959 /* Timer selection wrong */
961 } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
963 /* The module is not a TIMER module */
968 /* Module number error */
973 return i_ReturnValue
;
977 +----------------------------------------------------------------------------+
978 | Function Name : _INT_ i_APCI1710_WriteTimerValue |
979 | (unsigned char_ b_BoardHandle, |
980 | unsigned char_ b_ModulNbr, |
981 | unsigned char_ b_TimerNbr, |
982 | ULONG_ ul_WriteValue) |
983 +----------------------------------------------------------------------------+
984 | Task : Write the value (ul_WriteValue) into the selected timer|
985 | (b_TimerNbr) from selected timer module (b_ModulNbr). |
986 | The action in depend of the time mode selection. |
987 | See timer mode description table. |
988 +----------------------------------------------------------------------------+
989 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board |
991 | unsigned char_ b_ModulNbr : Selected module number |
993 | unsigned char_ b_TimerNbr : Timer number to write |
995 | ULONG_ ul_WriteValue : Value to write |
996 +----------------------------------------------------------------------------+
997 | Output Parameters : - |
998 +----------------------------------------------------------------------------+
999 | Return Value : 0: No error |
1000 | -1: The handle parameter of the board is wrong |
1001 | -2: Module selection wrong |
1002 | -3: Timer selection wrong |
1003 | -4: The module is not a TIMER module |
1004 | -5: Timer not initialised see function |
1005 | "i_APCI1710_InitTimer" |
1006 +----------------------------------------------------------------------------+
1009 int i_APCI1710_WriteTimerValue(struct comedi_device
*dev
,
1010 unsigned char b_ModulNbr
, unsigned char b_TimerNbr
,
1011 unsigned int ul_WriteValue
)
1013 int i_ReturnValue
= 0;
1015 /* Test the module number */
1016 if (b_ModulNbr
< 4) {
1017 /* Test if 82X54 timer */
1018 if ((devpriv
->s_BoardInfos
.dw_MolduleConfiguration
[b_ModulNbr
] & 0xFFFF0000UL
) == APCI1710_82X54_TIMER
) {
1019 /* Test the timer number */
1020 if (b_TimerNbr
<= 2) {
1021 /* Test if timer initialised */
1022 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].s_82X54ModuleInfo
.s_82X54TimerInfo
[b_TimerNbr
].b_82X54Init
== 1) {
1023 /* Write the value */
1024 outl(ul_WriteValue
, devpriv
->s_BoardInfos
.ui_Address
+ (b_TimerNbr
* 4) + (64 * b_ModulNbr
));
1026 /* Timer not initialised see function */
1027 DPRINTK("Timer not initialised see function\n");
1031 /* Timer selection wrong */
1032 DPRINTK("Timer selection wrong\n");
1034 } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
1036 /* The module is not a TIMER module */
1037 DPRINTK("The module is not a TIMER module\n");
1041 /* Module number error */
1042 DPRINTK("Module number error\n");
1046 return i_ReturnValue
;