Merge branch 'kmemtrace-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / staging / comedi / drivers / addi-data / APCI1710_82x54.c
1 /*
2  *  Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
3  *
4  *      ADDI-DATA GmbH
5  *      Dieselstrasse 3
6  *      D-77833 Ottersweier
7  *      Tel: +19(0)7223/9493-0
8  *      Fax: +49(0)7223/9493-92
9  *      http://www.addi-data-com
10  *      info@addi-data.com
11  *
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)
15  * any later version.
16  */
17 /*
18   | Description :   APCI-1710 82X54 timer module                          |
19 */
20
21 #include "APCI1710_82x54.h"
22
23 /*
24 +----------------------------------------------------------------------------+
25 | Function Name     : _INT_     i_APCI1710_InitTimer                         |
26 |                               (BYTE_   b_BoardHandle,                      |
27 |                                BYTE_   b_ModulNbr,                         |
28 |                                BYTE_   b_TimerNbr,                         |
29 |                                BYTE_   b_TimerMode,                        |
30 |                                ULONG_ ul_ReloadValue,                      |
31 |                                BYTE_   b_InputClockSelection,              |
32 |                                BYTE_   b_InputClockLevel,                  |
33 |                                BYTE_   b_OutputLevel,                      |
34 |                                BYTE_   b_HardwareGateLevel)
35 INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
36         struct comedi_insn *insn,unsigned int *data)
37 |
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.              |
43 |                                                                            |
44 |                                                                            |
45 |                       Timer mode description table                         |
46 |                                                                            |
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" |              |                    ||
61 ||        |function.                    |              |                    ||
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      |                    ||
67 ||        |the timer.                   |              |                    ||
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-     |              |                    ||
88 ||        |RoutineX"                    |              |                    ||
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 |+--------+-----------------------------+--------------+--------------------+|
127 |                                                                            |
128 |                                                                            |
129 |                                                                            |
130 |                      Input clock selection table                           |
131 |                                                                            |
132 |  +--------------------------------+------------------------------------+   |
133 |  |       b_InputClockSelection    |           Description              |   |
134 |  |           parameter            |                                    |   |
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    |   |
140 |  |                                | available.                         |   |
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 |  +--------------------------------+------------------------------------+   |
149 |                                                                            |
150 +----------------------------------------------------------------------------+
151 | Input Parameters  : BYTE_   b_BoardHandle        : Handle of board         |
152 |                                                    APCI-1710               |
153 |                     BYTE_   b_ModulNbr           : Module number to        |
154 |                                                    configure (0 to 3)      |
155 |                     BYTE_   b_TimerNbr           : Timer number to         |
156 |                                                    configure (0 to 2)      |
157 |                     BYTE_   b_TimerMode          : Timer mode selection    |
158 |                                                    (0 to 5)                |
159 |                                                    0: Interrupt on terminal|
160 |                                                       count                |
161 |                                                    1: Hardware             |
162 |                                                       retriggerable one-   |
163 |                                                       shot                 |
164 |                                                    2: Rate generator       |
165 |                                                    3: Square wave mode     |
166 |                                                    4: Software triggered   |
167 |                                                       strobe               |
168 |                                                    5: Hardware triggered   |
169 |                                                       strobe               |
170 |                                                       See timer mode       |
171 |                                                       description table.   |
172 |                     ULONG_ ul_ReloadValue         : Start counting value   |
173 |                                                     or division factor     |
174 |                                                     See timer mode         |
175 |                                                     description table.     |
176 |                     BYTE_   b_InputClockSelection : Selection from input   |
177 |                                                     timer clock.           |
178 |                                                     See input clock        |
179 |                                                     selection table.       |
180 |                     BYTE_   b_InputClockLevel     : Selection from input   |
181 |                                                     clock level.           |
182 |                                                     0 : Low active         |
183 |                                                         (Input inverted)   |
184 |                                                     1 : High active        |
185 |                     BYTE_   b_OutputLevel,        : Selection from output  |
186 |                                                     clock level.           |
187 |                                                     0 : Low active         |
188 |                                                     1 : High active        |
189 |                                                         (Output inverted)  |
190 |                     BYTE_   b_HardwareGateLevel   : Selection from         |
191 |                                                     hardware gate level.   |
192 |                                                     0 : Low active         |
193 |                                                         (Input inverted)   |
194 |                                                     1 : High active        |
195 |                                                     If you will not used   |
196 |                                                     the hardware gate set  |
197 |                                                     this value to 0.
198 |b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);
199         b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);
200         b_TimerMode               = (BYTE) data[0];
201         ul_ReloadValue    = (ULONG) data[1];
202         b_InputClockSelection   =(BYTE) data[2];
203         b_InputClockLevel               =(BYTE) data[3];
204         b_OutputLevel                   =(BYTE) data[4];
205         b_HardwareGateLevel             =(BYTE) 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 +----------------------------------------------------------------------------+
220 */
221
222 INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s,
223                                    struct comedi_insn * insn, unsigned int * data)
224 {
225
226         INT i_ReturnValue = 0;
227         BYTE b_ModulNbr;
228         BYTE b_TimerNbr;
229         BYTE b_TimerMode;
230         ULONG ul_ReloadValue;
231         BYTE b_InputClockSelection;
232         BYTE b_InputClockLevel;
233         BYTE b_OutputLevel;
234         BYTE b_HardwareGateLevel;
235
236         //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
237         DWORD dw_Test = 0;
238         //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
239
240         i_ReturnValue = insn->n;
241         b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
242         b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
243         b_TimerMode = (BYTE) data[0];
244         ul_ReloadValue = (ULONG) data[1];
245         b_InputClockSelection = (BYTE) data[2];
246         b_InputClockLevel = (BYTE) data[3];
247         b_OutputLevel = (BYTE) data[4];
248         b_HardwareGateLevel = (BYTE) data[5];
249
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 */
255
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 */
261                                         /*
262                                            if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||
263                                            ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1))))
264                                          */
265
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 */
280
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)));
292
293                                                                                         dw_Test = (dw_Test >> 16) & 1;
294                                                                                 } else {
295                                                                                         dw_Test = 1;
296                                                                                 }
297
298                                                                                 /* Test if detection OK */
299                                                                                 if (dw_Test == 1) {
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;
303
304                                                                                         /* Save the input clock selection */
305                                                                                         devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockSelection = b_InputClockSelection;
306
307                                                                                         /* Save the input clock level */
308                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockLevel = ~b_InputClockLevel & 1;
309
310                                                                                         /* Save the output level */
311                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel = ~b_OutputLevel & 1;
312
313                                                                                         /* Save the gate level */
314                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel;
315
316                                                                                         /* Set the configuration word and disable the timer */
317                                                                                         //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
318                                                                                         /*
319                                                                                            devpriv->s_ModuleInfo [b_ModulNbr].
320                                                                                            s_82X54ModuleInfo.
321                                                                                            s_82X54TimerInfo  [b_TimerNbr].
322                                                                                            dw_ConfigurationWord = (DWORD) (((b_HardwareGateLevel         << 0) & 0x1) |
323                                                                                            ((b_InputClockLevel           << 1) & 0x2) |
324                                                                                            (((~b_OutputLevel       & 1)  << 2) & 0x4) |
325                                                                                            ((b_InputClockSelection       << 4) & 0x10));
326                                                                                          */
327                                                                                         /* Test if 10MHz selected */
328                                                                                         if (b_InputClockSelection == APCI1710_10MHZ) {
329                                                                                                 b_InputClockSelection = 2;
330                                                                                         }
331
332                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (DWORD)(((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));
335
336                                                                                         /* Initialise the 82X54 Timer */
337                                                                                         outl((DWORD) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
338
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)
343                                                                                 else {
344                                                                                         /* Input timer clock selection is wrong */
345                                                                                         i_ReturnValue = -6;
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))
349                                                                         else {
350                                                                                 /* Selection from hardware gate level is wrong */
351                                                                                 DPRINTK("Selection from hardware gate level is wrong\n");
352                                                                                 i_ReturnValue = -9;
353                                                                         }       // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))
354                                                                 }       // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
355                                                                 else {
356                                                                         /* Selection from output clock level is wrong */
357                                                                         DPRINTK("Selection from output clock level is wrong\n");
358                                                                         i_ReturnValue = -8;
359                                                                 }       // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
360                                                         }       // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
361                                                         else {
362                                                                 /* Selection from input clock level is wrong */
363                                                                 DPRINTK("Selection from input clock level is wrong\n");
364                                                                 i_ReturnValue = -7;
365                                                         }       // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
366                                                 } else {
367                                                         /* Input timer clock selection is wrong */
368                                                         DPRINTK("Input timer clock selection is wrong\n");
369                                                         i_ReturnValue = -6;
370                                                 }
371                                         } else {
372                                                 /* Input timer clock selection is wrong */
373                                                 DPRINTK("Input timer clock selection is wrong\n");
374                                                 i_ReturnValue = -6;
375                                         }
376                                 }       // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
377                                 else {
378                                         /* Timer mode selection is wrong */
379                                         DPRINTK("Timer mode selection is wrong\n");
380                                         i_ReturnValue = -5;
381                                 }       // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
382                         }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
383                         else {
384                                 /* Timer selection wrong */
385                                 DPRINTK("Timer selection wrong\n");
386                                 i_ReturnValue = -3;
387                         }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
388                 } else {
389                         /* The module is not a TIMER module */
390                         DPRINTK("The module is not a TIMER module\n");
391                         i_ReturnValue = -4;
392                 }
393         } else {
394                 /* Module number error */
395                 DPRINTK("Module number error\n");
396                 i_ReturnValue = -2;
397         }
398
399         return (i_ReturnValue);
400 }
401
402 /*
403 +----------------------------------------------------------------------------+
404 | Function Name     : _INT_     i_APCI1710_EnableTimer                       |
405 |                               (BYTE_ b_BoardHandle,                        |
406 |                                BYTE_ b_ModulNbr,                           |
407 |                                BYTE_ b_TimerNbr,                           |
408 |                                BYTE_ 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  : BYTE_   b_BoardHandle     : Handle of board            |
420 |                                                 APCI-1710                  |
421 |                     BYTE_   b_ModulNbr        : Selected module number     |
422 |                                                 (0 to 3)                   |
423 |                     BYTE_   b_TimerNbr        : Timer number to enable     |
424 |                                                 (0 to 2)                   |
425 |                     BYTE_   b_InterruptEnable : Enable or disable the      |
426 |                                                 timer interrupt.           |
427 |                                                 APCI1710_ENABLE :          |
428 |                                                 Enable the timer interrupt |
429 |                                                 APCI1710_DISABLE :         |
430 |                                                 Disable the timer interrupt|
431 i_ReturnValue=insn->n;
432         b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);
433         b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);
434         b_ActionType      = (BYTE) 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 +----------------------------------------------------------------------------+
449 */
450
451 INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
452                                            struct comedi_subdevice * s,
453                                            struct comedi_insn * insn, unsigned int * data)
454 {
455         INT i_ReturnValue = 0;
456         DWORD dw_DummyRead;
457         BYTE b_ModulNbr;
458         BYTE b_TimerNbr;
459         BYTE b_ActionType;
460         BYTE b_InterruptEnable;
461
462         i_ReturnValue = insn->n;
463         b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
464         b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
465         b_ActionType = (BYTE) data[0];  // enable disable
466
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) {
475
476                                         switch (b_ActionType) {
477                                         case APCI1710_ENABLE:
478                                                 b_InterruptEnable = (BYTE) data[1];
479                                                 /* Test the interrupt selection */
480                                                 if ((b_InterruptEnable == APCI1710_ENABLE) ||
481                                                     (b_InterruptEnable == APCI1710_DISABLE)) {
482                                                         if (b_InterruptEnable == APCI1710_ENABLE) {
483
484                                                                 dw_DummyRead = inl(devpriv->s_BoardInfos.ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
485
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;
488
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
491
492                                                         }       // if (b_InterruptEnable == APCI1710_ENABLE)
493                                                         else {
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;
496
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));
498
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)
502
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);
507
508                                                                 /* Enable the timer */
509                                                                 outl(1, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
510                                                         }
511                                                 } else {
512                                                         /* Interrupt parameter is wrong */
513                                                         DPRINTK("\n");
514                                                         i_ReturnValue = -6;
515                                                 }
516                                                 break;
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 */
521
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;
523
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));
525
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));
528                                                 }
529
530                                                 /* Disable the timer */
531                                                 outl(0, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
532                                                 break;
533                                         }       // Switch end
534                                 } else {
535                                         /* Timer not initialised see function */
536                                         DPRINTK ("Timer not initialised see function\n");
537                                         i_ReturnValue = -5;
538                                 }
539                         } else {
540                                 /* Timer selection wrong */
541                                 DPRINTK("Timer selection wrong\n");
542                                 i_ReturnValue = -3;
543                         }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
544                 } else {
545                         /* The module is not a TIMER module */
546                         DPRINTK("The module is not a TIMER module\n");
547                         i_ReturnValue = -4;
548                 }
549         } else {
550                 /* Module number error */
551                 DPRINTK("Module number error\n");
552                 i_ReturnValue = -2;
553         }
554
555         return (i_ReturnValue);
556 }
557
558 /*
559 +----------------------------------------------------------------------------+
560 | Function Name     : _INT_     i_APCI1710_ReadAllTimerValue                 |
561 |                                       (BYTE_     b_BoardHandle,            |
562 |                                        BYTE_     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  : BYTE_   b_BoardHandle     : Handle of board            |
571 |                                                 APCI-1710                  |
572 |                     BYTE_   b_ModulNbr        : Selected module number     |
573 |                                                 (0 to 3)                   |
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 +----------------------------------------------------------------------------+
591 */
592
593 INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
594                                      struct comedi_insn *insn, unsigned int *data)
595 {
596         INT i_ReturnValue = 0;
597         BYTE b_ModulNbr, b_ReadType;
598         PULONG pul_TimerValueArray;
599
600         b_ModulNbr = CR_AREF(insn->chanspec);
601         b_ReadType = CR_CHAN(insn->chanspec);
602         pul_TimerValueArray = (PULONG) data;
603         i_ReturnValue = insn->n;
604
605         switch (b_ReadType) {
606         case APCI1710_TIMER_READINTERRUPT:
607
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;
611
612                 /* Increment the read FIFO */
613                 devpriv->s_InterruptParameters.ui_Read = (devpriv->s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
614
615                 break;
616
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));
630
631                                                         /* Read the timer 0 value */
632                                                         pul_TimerValueArray[0] = inl(devpriv->s_BoardInfos.ui_Address + 0 + (64 * b_ModulNbr));
633
634                                                         /* Read the timer 1 value */
635                                                         pul_TimerValueArray[1] = inl(devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
636
637                                                         /* Read the timer 2 value */
638                                                         pul_TimerValueArray[2] = inl(devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr));
639                                                 } else {
640                                                         /* Timer 2 not initialised see function */
641                                                         DPRINTK("Timer 2 not initialised see function\n");
642                                                         i_ReturnValue = -6;
643                                                 }
644                                         } else {
645                                                 /* Timer 1 not initialised see function */
646                                                 DPRINTK("Timer 1 not initialised see function\n");
647                                                 i_ReturnValue = -5;
648                                         }
649                                 } else {
650                                         /* Timer 0 not initialised see function */
651                                         DPRINTK("Timer 0 not initialised see function\n");
652                                         i_ReturnValue = -4;
653                                 }
654                         } else {
655                                 /* The module is not a TIMER module */
656                                 DPRINTK("The module is not a TIMER module\n");
657                                 i_ReturnValue = -3;
658                         }
659                 } else {
660                         /* Module number error */
661                         DPRINTK("Module number error\n");
662                         i_ReturnValue = -2;
663                 }
664
665         }                       // End of Switch
666         return (i_ReturnValue);
667 }
668
669 /*
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 +----------------------------------------------------------------------------+
676 | Input Parameters  :
677 +----------------------------------------------------------------------------+
678 | Output Parameters : -                                                      |
679 +----------------------------------------------------------------------------+
680 | Return Value      :
681 +----------------------------------------------------------------------------+
682 */
683
684 INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
685                              struct comedi_insn * insn, unsigned int * data)
686 {
687         BYTE b_BitsType;
688         INT i_ReturnValue = 0;
689         b_BitsType = data[0];
690
691         printk("\n82X54");
692
693         switch (b_BitsType) {
694         case APCI1710_TIMER_READVALUE:
695                 i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
696                                                           (BYTE)CR_AREF(insn->chanspec),
697                                                           (BYTE)CR_CHAN(insn->chanspec),
698                                                           (PULONG) & data[0]);
699                 break;
700
701         case APCI1710_TIMER_GETOUTPUTLEVEL:
702                 i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
703                                                                (BYTE)CR_AREF(insn->chanspec),
704                                                                (BYTE)CR_CHAN(insn->chanspec),
705                                                                (PBYTE) &data[0]);
706                 break;
707
708         case APCI1710_TIMER_GETPROGRESSSTATUS:
709                 i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
710                                                                   (BYTE)CR_AREF(insn->chanspec),
711                                                                   (BYTE)CR_CHAN(insn->chanspec),
712                                                                   (PBYTE)&data[0]);
713                 break;
714
715         case APCI1710_TIMER_WRITEVALUE:
716                 i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
717                                                            (BYTE)CR_AREF(insn->chanspec),
718                                                            (BYTE)CR_CHAN(insn->chanspec),
719                                                            (ULONG)data[1]);
720
721                 break;
722
723         default:
724                 printk("Bits Config Parameter Wrong\n");
725                 i_ReturnValue = -1;
726         }
727
728         if (i_ReturnValue >= 0)
729                 i_ReturnValue = insn->n;
730         return (i_ReturnValue);
731 }
732
733 /*
734 +----------------------------------------------------------------------------+
735 | Function Name     : _INT_     i_APCI1710_ReadTimerValue                    |
736 |                                       (BYTE_     b_BoardHandle,            |
737 |                                        BYTE_     b_ModulNbr,               |
738 |                                        BYTE_     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  : BYTE_   b_BoardHandle     : Handle of board            |
745 |                                                 APCI-1710                  |
746 |                     BYTE_   b_ModulNbr        : Selected module number     |
747 |                                                 (0 to 3)                   |
748 |                     BYTE_   b_TimerNbr        : Timer number to read       |
749 |                                                 (0 to 2)                   |
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 +----------------------------------------------------------------------------+
761 */
762
763 INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
764                               BYTE b_ModulNbr, BYTE b_TimerNbr,
765                               PULONG pul_TimerValue)
766 {
767         INT i_ReturnValue = 0;
768
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 */
778                                 if (devpriv->
779                                     s_ModuleInfo[b_ModulNbr].
780                                     s_82X54ModuleInfo.
781                                     s_82X54TimerInfo[b_TimerNbr].
782                                     b_82X54Init == 1) {
783                                         /* Latch the timer value */
784                                         outl((2 << b_TimerNbr) | 0xD0,
785                                              devpriv->s_BoardInfos.
786                                              ui_Address + 12 +
787                                              (64 * b_ModulNbr));
788
789                                         /* Read the counter value */
790                                         *pul_TimerValue =
791                                             inl(devpriv->s_BoardInfos.
792                                                 ui_Address + (b_TimerNbr * 4) +
793                                                 (64 * b_ModulNbr));
794                                 } else {
795                                         /* Timer not initialised see function */
796                                         DPRINTK("Timer not initialised see function\n");
797                                         i_ReturnValue = -5;
798                                 }
799                         } else {
800                                 /* Timer selection wrong */
801                                 DPRINTK("Timer selection wrong\n");
802                                 i_ReturnValue = -3;
803                         }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
804                 } else {
805                         /* The module is not a TIMER module */
806                         DPRINTK("The module is not a TIMER module\n");
807                         i_ReturnValue = -4;
808                 }
809         } else {
810                 /* Module number error */
811                 DPRINTK("Module number error\n");
812                 i_ReturnValue = -2;
813         }
814
815         return (i_ReturnValue);
816 }
817
818         /*
819            +----------------------------------------------------------------------------+
820            | Function Name     : _INT_     i_APCI1710_GetTimerOutputLevel               |
821            |                                       (BYTE_     b_BoardHandle,            |
822            |                                        BYTE_     b_ModulNbr,               |
823            |                                        BYTE_     b_TimerNbr,               |
824            |                                        PBYTE_   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  : BYTE_   b_BoardHandle     : Handle of board            |
831            |                                                 APCI-1710                  |
832            |                     BYTE_   b_ModulNbr        : Selected module number     |
833            |                                                 (0 to 3)                   |
834            |                     BYTE_   b_TimerNbr        : Timer number to test       |
835            |                                                 (0 to 2)                   |
836            +----------------------------------------------------------------------------+
837            | Output Parameters : PBYTE_ 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            +----------------------------------------------------------------------------+
849          */
850
851 INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
852                                    BYTE b_ModulNbr, BYTE b_TimerNbr,
853                                    PBYTE pb_OutputLevel)
854 {
855         INT i_ReturnValue = 0;
856         DWORD dw_TimerStatus;
857
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));
868
869                                         /* Read the timer status */
870                                         dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
871
872                                         *pb_OutputLevel = (BYTE) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel);
873                                 } else {
874                                         /* Timer not initialised see function */
875                                         DPRINTK("Timer not initialised see function\n");
876                                         i_ReturnValue = -5;
877                                 }
878                         } else {
879                                 /* Timer selection wrong */
880                                 DPRINTK("Timer selection wrong\n");
881                                 i_ReturnValue = -3;
882                         }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
883                 } else {
884                         /* The module is not a TIMER module */
885                         DPRINTK("The module is not a TIMER module\n");
886                         i_ReturnValue = -4;
887                 }
888         } else {
889                 /* Module number error */
890                 DPRINTK("Module number error\n");
891                 i_ReturnValue = -2;
892         }
893
894         return (i_ReturnValue);
895 }
896
897 /*
898 +----------------------------------------------------------------------------+
899 | Function Name     : _INT_     i_APCI1710_GetTimerProgressStatus            |
900 |                                       (BYTE_     b_BoardHandle,            |
901 |                                        BYTE_     b_ModulNbr,               |
902 |                                        BYTE_     b_TimerNbr,               |
903 |                                        PBYTE_   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  : BYTE_   b_BoardHandle     : Handle of board            |
910 |                                                 APCI-1710                  |
911 |                     BYTE_   b_ModulNbr        : Selected module number     |
912 |                                                 (0 to 3)                   |
913 |                     BYTE_   b_TimerNbr        : Timer number to test       |
914 |                                                 (0 to 2)                   |
915 +----------------------------------------------------------------------------+
916 | Output Parameters : PBYTE_ 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 +----------------------------------------------------------------------------+
928 */
929
930 INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
931                                       BYTE b_ModulNbr, BYTE b_TimerNbr,
932                                       PBYTE pb_TimerStatus)
933 {
934         INT i_ReturnValue = 0;
935         DWORD dw_TimerStatus;
936
937         /* Test the module number */
938         if (b_ModulNbr < 4) {
939                 /* Test if 82X54 timer */
940
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));
948
949                                         /* Read the timer status */
950                                         dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
951
952                                         *pb_TimerStatus = (BYTE) ((dw_TimerStatus) >> 8) & 1;
953                                         printk("ProgressStatus : %d", *pb_TimerStatus);
954                                 } else {
955                                         /* Timer not initialised see function */
956                                         i_ReturnValue = -5;
957                                 }
958                         } else {
959                                 /* Timer selection wrong */
960                                 i_ReturnValue = -3;
961                         }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
962                 } else {
963                         /* The module is not a TIMER module */
964
965                         i_ReturnValue = -4;
966                 }
967         } else {
968                 /* Module number error */
969
970                 i_ReturnValue = -2;
971         }
972
973         return i_ReturnValue;
974 }
975
976 /*
977 +----------------------------------------------------------------------------+
978 | Function Name     : _INT_     i_APCI1710_WriteTimerValue                   |
979 |                                       (BYTE_   b_BoardHandle,              |
980 |                                        BYTE_   b_ModulNbr,                 |
981 |                                        BYTE_   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  : BYTE_   b_BoardHandle     : Handle of board            |
990 |                                                 APCI-1710                  |
991 |                     BYTE_   b_ModulNbr        : Selected module number     |
992 |                                                 (0 to 3)                   |
993 |                     BYTE_   b_TimerNbr        : Timer number to write      |
994 |                                                 (0 to 2)                   |
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 +----------------------------------------------------------------------------+
1007 */
1008
1009 INT i_APCI1710_WriteTimerValue(struct comedi_device * dev,
1010                                BYTE b_ModulNbr, BYTE b_TimerNbr,
1011                                ULONG ul_WriteValue)
1012 {
1013         INT i_ReturnValue = 0;
1014
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));
1025                                 } else {
1026                                         /* Timer not initialised see function */
1027                                         DPRINTK("Timer not initialised see function\n");
1028                                         i_ReturnValue = -5;
1029                                 }
1030                         } else {
1031                                 /* Timer selection wrong */
1032                                 DPRINTK("Timer selection wrong\n");
1033                                 i_ReturnValue = -3;
1034                         }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
1035                 } else {
1036                         /* The module is not a TIMER module */
1037                         DPRINTK("The module is not a TIMER module\n");
1038                         i_ReturnValue = -4;
1039                 }
1040         } else {
1041                 /* Module number error */
1042                 DPRINTK("Module number error\n");
1043                 i_ReturnValue = -2;
1044         }
1045
1046         return i_ReturnValue;
1047 }