Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[firefly-linux-kernel-4.4.55.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 #define APCI1710_PCI_BUS_CLOCK                  0
22 #define APCI1710_FRONT_CONNECTOR_INPUT          1
23 #define APCI1710_TIMER_READVALUE                0
24 #define APCI1710_TIMER_GETOUTPUTLEVEL           1
25 #define APCI1710_TIMER_GETPROGRESSSTATUS        2
26 #define APCI1710_TIMER_WRITEVALUE               3
27
28 #define APCI1710_TIMER_READINTERRUPT            1
29 #define APCI1710_TIMER_READALLTIMER             2
30
31 #ifndef APCI1710_10MHZ
32 #define APCI1710_10MHZ                          10
33 #endif
34
35 /*
36 +----------------------------------------------------------------------------+
37 | Function Name     : _INT_     i_APCI1710_InitTimer                         |
38 |                               (unsigned char_   b_BoardHandle,                      |
39 |                                unsigned char_   b_ModulNbr,                         |
40 |                                unsigned char_   b_TimerNbr,                         |
41 |                                unsigned char_   b_TimerMode,                        |
42 |                                ULONG_ ul_ReloadValue,                      |
43 |                                unsigned char_   b_InputClockSelection,              |
44 |                                unsigned char_   b_InputClockLevel,                  |
45 |                                unsigned char_   b_OutputLevel,                      |
46 |                                unsigned char_   b_HardwareGateLevel)
47 int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
48         struct comedi_insn *insn,unsigned int *data)
49 |
50 +----------------------------------------------------------------------------+
51 | Task              : Configure the Timer (b_TimerNbr) operating mode        |
52 |                     (b_TimerMode) from selected module (b_ModulNbr).       |
53 |                     You must calling this function be for you call any     |
54 |                     other function witch access of the timer.              |
55 |                                                                            |
56 |                                                                            |
57 |                       Timer mode description table                         |
58 |                                                                            |
59 |+--------+-----------------------------+--------------+--------------------+|
60 ||Selected+      Mode description       +u_ReloadValue | Hardware gate input||
61 ||  mode  |                             |  description |      action        ||
62 |+--------+-----------------------------+--------------+--------------------+|
63 ||        |Mode 0 is typically used     |              |                    ||
64 ||        |for event counting. After    |              |                    ||
65 ||        |the initialisation, OUT      |              |                    ||
66 ||        |is initially low, and        |              |                    ||
67 ||   0    |will remain low until the    |Start counting|   Hardware gate    ||
68 ||        |counter reaches zero.        |   value      |                    ||
69 ||        |OUT then goes high and       |              |                    ||
70 ||        |remains high until a new     |              |                    ||
71 ||        |count is written. See        |              |                    ||
72 ||        |"i_APCI1710_WriteTimerValue" |              |                    ||
73 ||        |function.                    |              |                    ||
74 |+--------+-----------------------------+--------------+--------------------+|
75 ||        |Mode 1 is similar to mode 0  |              |                    ||
76 ||        |except for the gate input    |              |                    ||
77 ||   1    |action. The gate input is not|Start counting|  Hardware trigger  ||
78 ||        |used for enabled or disabled |   value      |                    ||
79 ||        |the timer.                   |              |                    ||
80 ||        |The gate input is used for   |              |                    ||
81 ||        |triggered the timer.         |              |                    ||
82 |+--------+-----------------------------+--------------+--------------------+|
83 ||        |This mode functions like a   |              |                    ||
84 ||        |divide-by-ul_ReloadValue     |              |                    ||
85 ||        |counter. It is typically used|              |                    ||
86 ||        |to generate a real time clock|              |                    ||
87 ||        |interrupt. OUT will initially|              |                    ||
88 ||   2    |be high after the            |   Division   |  Hardware gate     ||
89 ||        |initialisation. When the     |    factor    |                    ||
90 ||        |initial count has decremented|              |                    ||
91 ||        |to 1, OUT goes low for one   |              |                    ||
92 ||        |CLK pule. OUT then goes high |              |                    ||
93 ||        |again, the counter reloads   |              |                    ||
94 ||        |the initial count            |              |                    ||
95 ||        |(ul_ReloadValue) and the     |              |                    ||
96 ||        |process is repeated.         |              |                    ||
97 ||        |This action can generated a  |              |                    ||
98 ||        |interrupt. See function      |              |                    ||
99 ||        |"i_APCI1710_SetBoardInt-     |              |                    ||
100 ||        |RoutineX"                    |              |                    ||
101 ||        |and "i_APCI1710_EnableTimer" |              |                    ||
102 |+--------+-----------------------------+--------------+--------------------+|
103 ||        |Mode 3 is typically used for |              |                    ||
104 ||        |baud rate generation. This   |              |                    ||
105 ||        |mode is similar to mode 2    |              |                    ||
106 ||        |except for the duty cycle of |              |                    ||
107 ||   3    |OUT. OUT will initially be   |  Division    |   Hardware gate    ||
108 ||        |high after the initialisation|   factor     |                    ||
109 ||        |When half the initial count  |              |                    ||
110 ||        |(ul_ReloadValue) has expired,|              |                    ||
111 ||        |OUT goes low for the         |              |                    ||
112 ||        |remainder of the count. The  |              |                    ||
113 ||        |mode is periodic; the        |              |                    ||
114 ||        |sequence above is repeated   |              |                    ||
115 ||        |indefinitely.                |              |                    ||
116 |+--------+-----------------------------+--------------+--------------------+|
117 ||        |OUT will be initially high   |              |                    ||
118 ||        |after the initialisation.    |              |                    ||
119 ||        |When the initial count       |              |                    ||
120 ||   4    |expires OUT will go low for  |Start counting|  Hardware gate     ||
121 ||        |one CLK pulse and then go    |    value     |                    ||
122 ||        |high again.                  |              |                    ||
123 ||        |The counting sequences is    |              |                    ||
124 ||        |triggered by writing a new   |              |                    ||
125 ||        |value. See                   |              |                    ||
126 ||        |"i_APCI1710_WriteTimerValue" |              |                    ||
127 ||        |function. If a new count is  |              |                    ||
128 ||        |written during counting,     |              |                    ||
129 ||        |it will be loaded on the     |              |                    ||
130 ||        |next CLK pulse               |              |                    ||
131 |+--------+-----------------------------+--------------+--------------------+|
132 ||        |Mode 5 is similar to mode 4  |              |                    ||
133 ||        |except for the gate input    |              |                    ||
134 ||        |action. The gate input is not|              |                    ||
135 ||   5    |used for enabled or disabled |Start counting|  Hardware trigger  ||
136 ||        |the timer. The gate input is |    value     |                    ||
137 ||        |used for triggered the timer.|              |                    ||
138 |+--------+-----------------------------+--------------+--------------------+|
139 |                                                                            |
140 |                                                                            |
141 |                                                                            |
142 |                      Input clock selection table                           |
143 |                                                                            |
144 |  +--------------------------------+------------------------------------+   |
145 |  |       b_InputClockSelection    |           Description              |   |
146 |  |           parameter            |                                    |   |
147 |  +--------------------------------+------------------------------------+   |
148 |  |    APCI1710_PCI_BUS_CLOCK      | For the timer input clock, the PCI |   |
149 |  |                                | bus clock / 4 is used. This PCI bus|   |
150 |  |                                | clock can be 30MHz or 33MHz. For   |   |
151 |  |                                | Timer 0 only this selection are    |   |
152 |  |                                | available.                         |   |
153 |  +--------------------------------+------------------------------------+   |
154 |  | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the|   |
155 |  |                                | possibility to inject a input clock|   |
156 |  |                                | for Timer 1 or Timer 2. The source |   |
157 |  |                                | from this clock can eat the output |   |
158 |  |                                | clock from Timer 0 or any other    |   |
159 |  |                                | clock source.                      |   |
160 |  +--------------------------------+------------------------------------+   |
161 |                                                                            |
162 +----------------------------------------------------------------------------+
163 | Input Parameters  : unsigned char_   b_BoardHandle        : Handle of board         |
164 |                                                    APCI-1710               |
165 |                     unsigned char_   b_ModulNbr           : Module number to        |
166 |                                                    configure (0 to 3)      |
167 |                     unsigned char_   b_TimerNbr           : Timer number to         |
168 |                                                    configure (0 to 2)      |
169 |                     unsigned char_   b_TimerMode          : Timer mode selection    |
170 |                                                    (0 to 5)                |
171 |                                                    0: Interrupt on terminal|
172 |                                                       count                |
173 |                                                    1: Hardware             |
174 |                                                       retriggerable one-   |
175 |                                                       shot                 |
176 |                                                    2: Rate generator       |
177 |                                                    3: Square wave mode     |
178 |                                                    4: Software triggered   |
179 |                                                       strobe               |
180 |                                                    5: Hardware triggered   |
181 |                                                       strobe               |
182 |                                                       See timer mode       |
183 |                                                       description table.   |
184 |                     ULONG_ ul_ReloadValue         : Start counting value   |
185 |                                                     or division factor     |
186 |                                                     See timer mode         |
187 |                                                     description table.     |
188 |                     unsigned char_   b_InputClockSelection : Selection from input   |
189 |                                                     timer clock.           |
190 |                                                     See input clock        |
191 |                                                     selection table.       |
192 |                     unsigned char_   b_InputClockLevel     : Selection from input   |
193 |                                                     clock level.           |
194 |                                                     0 : Low active         |
195 |                                                         (Input inverted)   |
196 |                                                     1 : High active        |
197 |                     unsigned char_   b_OutputLevel,        : Selection from output  |
198 |                                                     clock level.           |
199 |                                                     0 : Low active         |
200 |                                                     1 : High active        |
201 |                                                         (Output inverted)  |
202 |                     unsigned char_   b_HardwareGateLevel   : Selection from         |
203 |                                                     hardware gate level.   |
204 |                                                     0 : Low active         |
205 |                                                         (Input inverted)   |
206 |                                                     1 : High active        |
207 |                                                     If you will not used   |
208 |                                                     the hardware gate set  |
209 |                                                     this value to 0.
210 |b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
211         b_TimerNbr                = (unsigned char) CR_CHAN(insn->chanspec);
212         b_TimerMode               = (unsigned char) data[0];
213         ul_ReloadValue    = (unsigned int) data[1];
214         b_InputClockSelection   =(unsigned char) data[2];
215         b_InputClockLevel               =(unsigned char) data[3];
216         b_OutputLevel                   =(unsigned char) data[4];
217         b_HardwareGateLevel             =(unsigned char) data[5];
218 +----------------------------------------------------------------------------+
219 | Output Parameters : -                                                      |
220 +----------------------------------------------------------------------------+
221 | Return Value      : 0: No error                                            |
222 |                    -1: The handle parameter of the board is wrong          |
223 |                    -2: Module selection wrong                              |
224 |                    -3: Timer selection wrong                               |
225 |                    -4: The module is not a TIMER module                    |
226 |                    -5: Timer mode selection is wrong                       |
227 |                    -6: Input timer clock selection is wrong                |
228 |                    -7: Selection from input clock level is wrong           |
229 |                    -8: Selection from output clock level is wrong          |
230 |                    -9: Selection from hardware gate level is wrong         |
231 +----------------------------------------------------------------------------+
232 */
233 static int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev,
234                                           struct comedi_subdevice *s,
235                                           struct comedi_insn *insn,
236                                           unsigned int *data)
237 {
238         struct addi_private *devpriv = dev->private;
239         int i_ReturnValue = 0;
240         unsigned char b_ModulNbr;
241         unsigned char b_TimerNbr;
242         unsigned char b_TimerMode;
243         unsigned int ul_ReloadValue;
244         unsigned char b_InputClockSelection;
245         unsigned char b_InputClockLevel;
246         unsigned char b_OutputLevel;
247         unsigned char b_HardwareGateLevel;
248
249         /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
250         unsigned int dw_Test = 0;
251         /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
252
253         i_ReturnValue = insn->n;
254         b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
255         b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
256         b_TimerMode = (unsigned char) data[0];
257         ul_ReloadValue = (unsigned int) data[1];
258         b_InputClockSelection = (unsigned char) data[2];
259         b_InputClockLevel = (unsigned char) data[3];
260         b_OutputLevel = (unsigned char) data[4];
261         b_HardwareGateLevel = (unsigned char) data[5];
262
263         /* Test the module number */
264         if (b_ModulNbr < 4) {
265                 /* Test if 82X54 timer */
266                 if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
267                         /* Test the timer number */
268
269                         if (b_TimerNbr <= 2) {
270                                 /* Test the timer mode */
271                                 if (b_TimerMode <= 5) {
272                                         /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
273                                         /* Test te imput clock selection */
274                                         /*
275                                            if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||
276                                            ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1))))
277                                          */
278
279                                         if (((b_TimerNbr == 0) &&
280                                              (b_InputClockSelection == APCI1710_PCI_BUS_CLOCK)) ||
281                                             ((b_TimerNbr == 0) &&
282                                              (b_InputClockSelection == APCI1710_10MHZ)) ||
283                                             ((b_TimerNbr != 0) &&
284                                              ((b_InputClockSelection == APCI1710_PCI_BUS_CLOCK) ||
285                                               (b_InputClockSelection == APCI1710_FRONT_CONNECTOR_INPUT) ||
286                                               (b_InputClockSelection == APCI1710_10MHZ)))) {
287                                                 /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
288                                                 if (((b_InputClockSelection == APCI1710_10MHZ) &&
289                                                      ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) ||
290                                                      (b_InputClockSelection != APCI1710_10MHZ)) {
291                                                         /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */
292                                                         /* Test the input clock level selection */
293
294                                                         if ((b_InputClockLevel == 0) ||
295                                                             (b_InputClockLevel == 1)) {
296                                                                 /* Test the output clock level selection */
297                                                                 if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) {
298                                                                         /* Test the hardware gate level selection */
299                                                                         if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) {
300                                                                                 /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
301                                                                                 /* Test if version > 1.1 and clock selection = 10MHz */
302                                                                                 if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) {
303                                                                                         /* Test if 40MHz quartz on board */
304                                                                                         dw_Test = inl(devpriv->s_BoardInfos.ui_Address + (16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)));
305
306                                                                                         dw_Test = (dw_Test >> 16) & 1;
307                                                                                 } else {
308                                                                                         dw_Test = 1;
309                                                                                 }
310
311                                                                                 /* Test if detection OK */
312                                                                                 if (dw_Test == 1) {
313                                                                                         /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
314                                                                                         /* Initialisation OK */
315                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init = 1;
316
317                                                                                         /* Save the input clock selection */
318                                                                                         devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockSelection = b_InputClockSelection;
319
320                                                                                         /* Save the input clock level */
321                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockLevel = ~b_InputClockLevel & 1;
322
323                                                                                         /* Save the output level */
324                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel = ~b_OutputLevel & 1;
325
326                                                                                         /* Save the gate level */
327                                                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel;
328
329                                                                                         /* Set the configuration word and disable the timer */
330                                                                                         /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
331                                                                                         /*
332                                                                                            devpriv->s_ModuleInfo [b_ModulNbr].
333                                                                                            s_82X54ModuleInfo.
334                                                                                            s_82X54TimerInfo  [b_TimerNbr].
335                                                                                            dw_ConfigurationWord = (unsigned int) (((b_HardwareGateLevel         << 0) & 0x1) |
336                                                                                            ((b_InputClockLevel           << 1) & 0x2) |
337                                                                                            (((~b_OutputLevel       & 1)  << 2) & 0x4) |
338                                                                                            ((b_InputClockSelection       << 4) & 0x10));
339                                                                                          */
340                                                                                         /* Test if 10MHz selected */
341                                                                                         if (b_InputClockSelection == APCI1710_10MHZ) {
342                                                                                                 b_InputClockSelection = 2;
343                                                                                         }
344
345                                                                                         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));
346                                                                                         /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
347                                                                                         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));
348
349                                                                                         /* Initialise the 82X54 Timer */
350                                                                                         outl((unsigned int) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
351
352                                                                                         /* Write the reload value */
353                                                                                         outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
354                                                                                         /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
355                                                                                 }       /*  if (dw_Test == 1) */
356                                                                                 else {
357                                                                                         /* Input timer clock selection is wrong */
358                                                                                         i_ReturnValue = -6;
359                                                                                 }       /*  if (dw_Test == 1) */
360                                                                                 /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
361                                                                         }       /*  if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
362                                                                         else {
363                                                                                 /* Selection from hardware gate level is wrong */
364                                                                                 DPRINTK("Selection from hardware gate level is wrong\n");
365                                                                                 i_ReturnValue = -9;
366                                                                         }       /*  if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */
367                                                                 }       /*  if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
368                                                                 else {
369                                                                         /* Selection from output clock level is wrong */
370                                                                         DPRINTK("Selection from output clock level is wrong\n");
371                                                                         i_ReturnValue = -8;
372                                                                 }       /*  if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */
373                                                         }       /*  if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
374                                                         else {
375                                                                 /* Selection from input clock level is wrong */
376                                                                 DPRINTK("Selection from input clock level is wrong\n");
377                                                                 i_ReturnValue = -7;
378                                                         }       /*  if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */
379                                                 } else {
380                                                         /* Input timer clock selection is wrong */
381                                                         DPRINTK("Input timer clock selection is wrong\n");
382                                                         i_ReturnValue = -6;
383                                                 }
384                                         } else {
385                                                 /* Input timer clock selection is wrong */
386                                                 DPRINTK("Input timer clock selection is wrong\n");
387                                                 i_ReturnValue = -6;
388                                         }
389                                 }       /*  if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
390                                 else {
391                                         /* Timer mode selection is wrong */
392                                         DPRINTK("Timer mode selection is wrong\n");
393                                         i_ReturnValue = -5;
394                                 }       /*  if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */
395                         }       /*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
396                         else {
397                                 /* Timer selection wrong */
398                                 DPRINTK("Timer selection wrong\n");
399                                 i_ReturnValue = -3;
400                         }       /*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
401                 } else {
402                         /* The module is not a TIMER module */
403                         DPRINTK("The module is not a TIMER module\n");
404                         i_ReturnValue = -4;
405                 }
406         } else {
407                 /* Module number error */
408                 DPRINTK("Module number error\n");
409                 i_ReturnValue = -2;
410         }
411
412         return i_ReturnValue;
413 }
414
415 /*
416 +----------------------------------------------------------------------------+
417 | Function Name     : _INT_     i_APCI1710_EnableTimer                       |
418 |                               (unsigned char_ b_BoardHandle,                        |
419 |                                unsigned char_ b_ModulNbr,                           |
420 |                                unsigned char_ b_TimerNbr,                           |
421 |                                unsigned char_ b_InterruptEnable)
422 int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
423         struct comedi_insn *insn,unsigned int *data)                |
424 +----------------------------------------------------------------------------+
425 | Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
426 |                     (b_ModulNbr). You must calling the                     |
427 |                     "i_APCI1710_InitTimer" function be for you call this   |
428 |                     function. If you enable the timer interrupt, the timer |
429 |                     generate a interrupt after the timer value reach       |
430 |                     the zero. See function "i_APCI1710_SetBoardIntRoutineX"|
431 +----------------------------------------------------------------------------+
432 | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
433 |                                                 APCI-1710                  |
434 |                     unsigned char_   b_ModulNbr        : Selected module number     |
435 |                                                 (0 to 3)                   |
436 |                     unsigned char_   b_TimerNbr        : Timer number to enable     |
437 |                                                 (0 to 2)                   |
438 |                     unsigned char_   b_InterruptEnable : Enable or disable the      |
439 |                                                 timer interrupt.           |
440 |                                                 APCI1710_ENABLE :          |
441 |                                                 Enable the timer interrupt |
442 |                                                 APCI1710_DISABLE :         |
443 |                                                 Disable the timer interrupt|
444 i_ReturnValue=insn->n;
445         b_ModulNbr        = (unsigned char) CR_AREF(insn->chanspec);
446         b_TimerNbr                = (unsigned char) CR_CHAN(insn->chanspec);
447         b_ActionType      = (unsigned char) data[0]; /*  enable disable */
448 +----------------------------------------------------------------------------+
449 | Output Parameters : -                                                      |
450 +----------------------------------------------------------------------------+
451 | Return Value      : 0: No error                                            |
452 |                    -1: The handle parameter of the board is wrong          |
453 |                    -2: Module selection wrong                              |
454 |                    -3: Timer selection wrong                               |
455 |                    -4: The module is not a TIMER module                    |
456 |                    -5: Timer not initialised see function                  |
457 |                        "i_APCI1710_InitTimer"                              |
458 |                    -6: Interrupt parameter is wrong                        |
459 |                    -7: Interrupt function not initialised.                 |
460 |                        See function "i_APCI1710_SetBoardIntRoutineX"       |
461 +----------------------------------------------------------------------------+
462 */
463 static int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
464                                                  struct comedi_subdevice *s,
465                                                  struct comedi_insn *insn,
466                                                  unsigned int *data)
467 {
468         struct addi_private *devpriv = dev->private;
469         int i_ReturnValue = 0;
470         unsigned int dw_DummyRead;
471         unsigned char b_ModulNbr;
472         unsigned char b_TimerNbr;
473         unsigned char b_ActionType;
474         unsigned char b_InterruptEnable;
475
476         i_ReturnValue = insn->n;
477         b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
478         b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec);
479         b_ActionType = (unsigned char) data[0]; /*  enable disable */
480
481         /* Test the module number */
482         if (b_ModulNbr < 4) {
483                 /* Test if 82X54 timer */
484                 if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
485                         /* Test the timer number */
486                         if (b_TimerNbr <= 2) {
487                                 /* Test if timer initialised */
488                                 if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
489
490                                         switch (b_ActionType) {
491                                         case APCI1710_ENABLE:
492                                                 b_InterruptEnable = (unsigned char) data[1];
493                                                 /* Test the interrupt selection */
494                                                 if ((b_InterruptEnable == APCI1710_ENABLE) ||
495                                                     (b_InterruptEnable == APCI1710_DISABLE)) {
496                                                         if (b_InterruptEnable == APCI1710_ENABLE) {
497
498                                                                 dw_DummyRead = inl(devpriv->s_BoardInfos.ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
499
500                                                                 /* Enable the interrupt */
501                                                                 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;
502
503                                                                 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));
504                                                                 devpriv->tsk_Current = current; /*  Save the current process task structure */
505
506                                                         }       /*  if (b_InterruptEnable == APCI1710_ENABLE) */
507                                                         else {
508                                                                 /* Disable the interrupt */
509                                                                 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;
510
511                                                                 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));
512
513                                                                 /* Save the interrupt flag */
514                                                                 devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));
515                                                         }       /*  if (b_InterruptEnable == APCI1710_ENABLE) */
516
517                                                         /* Test if error occur */
518                                                         if (i_ReturnValue >= 0) {
519                                                                 /* Save the interrupt flag */
520                                                                 devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask | ((1 & b_InterruptEnable) << b_TimerNbr);
521
522                                                                 /* Enable the timer */
523                                                                 outl(1, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
524                                                         }
525                                                 } else {
526                                                         /* Interrupt parameter is wrong */
527                                                         DPRINTK("\n");
528                                                         i_ReturnValue = -6;
529                                                 }
530                                                 break;
531                                         case APCI1710_DISABLE:
532                                                 /* Test the interrupt flag */
533                                                 if (((devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask >> b_TimerNbr) & 1) == 1) {
534                                                         /* Disable the interrupt */
535
536                                                         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;
537
538                                                         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));
539
540                                                         /* Save the interrupt flag */
541                                                         devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));
542                                                 }
543
544                                                 /* Disable the timer */
545                                                 outl(0, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
546                                                 break;
547                                         }       /*  Switch end */
548                                 } else {
549                                         /* Timer not initialised see function */
550                                         DPRINTK ("Timer not initialised see function\n");
551                                         i_ReturnValue = -5;
552                                 }
553                         } else {
554                                 /* Timer selection wrong */
555                                 DPRINTK("Timer selection wrong\n");
556                                 i_ReturnValue = -3;
557                         }       /*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
558                 } else {
559                         /* The module is not a TIMER module */
560                         DPRINTK("The module is not a TIMER module\n");
561                         i_ReturnValue = -4;
562                 }
563         } else {
564                 /* Module number error */
565                 DPRINTK("Module number error\n");
566                 i_ReturnValue = -2;
567         }
568
569         return i_ReturnValue;
570 }
571
572 /*
573 +----------------------------------------------------------------------------+
574 | Function Name     : _INT_     i_APCI1710_ReadAllTimerValue                 |
575 |                                       (unsigned char_     b_BoardHandle,            |
576 |                                        unsigned char_     b_ModulNbr,               |
577 |                                        PULONG_ pul_TimerValueArray)
578 int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
579         struct comedi_insn *insn,unsigned int *data)        |
580 +----------------------------------------------------------------------------+
581 | Task              : Return the all timer values from selected timer        |
582 |                     module (b_ModulNbr).                                   |
583 +----------------------------------------------------------------------------+
584 | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
585 |                                                 APCI-1710                  |
586 |                     unsigned char_   b_ModulNbr        : Selected module number     |
587 |                                                 (0 to 3)                   |
588 +----------------------------------------------------------------------------+
589 | Output Parameters : PULONG_ pul_TimerValueArray : Timer value array.       |
590 |                           Element 0 contain the timer 0 value.             |
591 |                           Element 1 contain the timer 1 value.             |
592 |                           Element 2 contain the timer 2 value.             |
593 +----------------------------------------------------------------------------+
594 | Return Value      : 0: No error                                            |
595 |                    -1: The handle parameter of the board is wrong          |
596 |                    -2: Module selection wrong                              |
597 |                    -3: The module is not a TIMER module                    |
598 |                    -4: Timer 0 not initialised see function                |
599 |                        "i_APCI1710_InitTimer"                              |
600 |                    -5: Timer 1 not initialised see function                |
601 |                        "i_APCI1710_InitTimer"                              |
602 |                    -6: Timer 2 not initialised see function                |
603 |                        "i_APCI1710_InitTimer"                              |
604 +----------------------------------------------------------------------------+
605 */
606 static int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,
607                                             struct comedi_subdevice *s,
608                                             struct comedi_insn *insn,
609                                             unsigned int *data)
610 {
611         struct addi_private *devpriv = dev->private;
612         int i_ReturnValue = 0;
613         unsigned char b_ModulNbr, b_ReadType;
614         unsigned int *pul_TimerValueArray;
615
616         b_ModulNbr = CR_AREF(insn->chanspec);
617         b_ReadType = CR_CHAN(insn->chanspec);
618         pul_TimerValueArray = (unsigned int *) data;
619         i_ReturnValue = insn->n;
620
621         switch (b_ReadType) {
622         case APCI1710_TIMER_READINTERRUPT:
623
624                 data[0] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].b_OldModuleMask;
625                 data[1] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldInterruptMask;
626                 data[2] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
627
628                 /* Increment the read FIFO */
629                 devpriv->s_InterruptParameters.ui_Read = (devpriv->s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
630
631                 break;
632
633         case APCI1710_TIMER_READALLTIMER:
634                 /* Test the module number */
635                 if (b_ModulNbr < 4) {
636                         /* Test if 82X54 timer */
637                         if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
638                                 /* Test if timer 0 iniutialised */
639                                 if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[0].b_82X54Init == 1) {
640                                         /* Test if timer 1 iniutialised */
641                                         if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[1].b_82X54Init == 1) {
642                                                 /* Test if timer 2 iniutialised */
643                                                 if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[2].b_82X54Init == 1) {
644                                                         /* Latch all counter */
645                                                         outl(0x17, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
646
647                                                         /* Read the timer 0 value */
648                                                         pul_TimerValueArray[0] = inl(devpriv->s_BoardInfos.ui_Address + 0 + (64 * b_ModulNbr));
649
650                                                         /* Read the timer 1 value */
651                                                         pul_TimerValueArray[1] = inl(devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
652
653                                                         /* Read the timer 2 value */
654                                                         pul_TimerValueArray[2] = inl(devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr));
655                                                 } else {
656                                                         /* Timer 2 not initialised see function */
657                                                         DPRINTK("Timer 2 not initialised see function\n");
658                                                         i_ReturnValue = -6;
659                                                 }
660                                         } else {
661                                                 /* Timer 1 not initialised see function */
662                                                 DPRINTK("Timer 1 not initialised see function\n");
663                                                 i_ReturnValue = -5;
664                                         }
665                                 } else {
666                                         /* Timer 0 not initialised see function */
667                                         DPRINTK("Timer 0 not initialised see function\n");
668                                         i_ReturnValue = -4;
669                                 }
670                         } else {
671                                 /* The module is not a TIMER module */
672                                 DPRINTK("The module is not a TIMER module\n");
673                                 i_ReturnValue = -3;
674                         }
675                 } else {
676                         /* Module number error */
677                         DPRINTK("Module number error\n");
678                         i_ReturnValue = -2;
679                 }
680
681         }                       /*  End of Switch */
682         return i_ReturnValue;
683 }
684
685 /*
686 +----------------------------------------------------------------------------+
687 | Function Name     : _INT_     i_APCI1710_ReadTimerValue                    |
688 |                                       (unsigned char_     b_BoardHandle,            |
689 |                                        unsigned char_     b_ModulNbr,               |
690 |                                        unsigned char_     b_TimerNbr,               |
691 |                                        PULONG_ pul_TimerValue)             |
692 +----------------------------------------------------------------------------+
693 | Task              : Return the timer value from selected digital timer     |
694 |                     (b_TimerNbr) from selected timer  module (b_ModulNbr). |
695 +----------------------------------------------------------------------------+
696 | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
697 |                                                 APCI-1710                  |
698 |                     unsigned char_   b_ModulNbr        : Selected module number     |
699 |                                                 (0 to 3)                   |
700 |                     unsigned char_   b_TimerNbr        : Timer number to read       |
701 |                                                 (0 to 2)                   |
702 +----------------------------------------------------------------------------+
703 | Output Parameters : PULONG_ pul_TimerValue    : Timer value                |
704 +----------------------------------------------------------------------------+
705 | Return Value      : 0: No error                                            |
706 |                    -1: The handle parameter of the board is wrong          |
707 |                    -2: Module selection wrong                              |
708 |                    -3: Timer selection wrong                               |
709 |                    -4: The module is not a TIMER module                    |
710 |                    -5: Timer not initialised see function                  |
711 |                        "i_APCI1710_InitTimer"                              |
712 +----------------------------------------------------------------------------+
713 */
714 static int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
715                                      unsigned char b_ModulNbr,
716                                      unsigned char b_TimerNbr,
717                                      unsigned int *pul_TimerValue)
718 {
719         struct addi_private *devpriv = dev->private;
720         int i_ReturnValue = 0;
721
722         /* Test the module number */
723         if (b_ModulNbr < 4) {
724                 /* Test if 82X54 timer */
725                 if ((devpriv->s_BoardInfos.
726                      dw_MolduleConfiguration[b_ModulNbr] &
727                      0xFFFF0000UL) == APCI1710_82X54_TIMER) {
728                         /* Test the timer number */
729                         if (b_TimerNbr <= 2) {
730                                 /* Test if timer initialised */
731                                 if (devpriv->
732                                     s_ModuleInfo[b_ModulNbr].
733                                     s_82X54ModuleInfo.
734                                     s_82X54TimerInfo[b_TimerNbr].
735                                     b_82X54Init == 1) {
736                                         /* Latch the timer value */
737                                         outl((2 << b_TimerNbr) | 0xD0,
738                                              devpriv->s_BoardInfos.
739                                              ui_Address + 12 +
740                                              (64 * b_ModulNbr));
741
742                                         /* Read the counter value */
743                                         *pul_TimerValue =
744                                             inl(devpriv->s_BoardInfos.
745                                                 ui_Address + (b_TimerNbr * 4) +
746                                                 (64 * b_ModulNbr));
747                                 } else {
748                                         /* Timer not initialised see function */
749                                         DPRINTK("Timer not initialised see function\n");
750                                         i_ReturnValue = -5;
751                                 }
752                         } else {
753                                 /* Timer selection wrong */
754                                 DPRINTK("Timer selection wrong\n");
755                                 i_ReturnValue = -3;
756                         }       /*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
757                 } else {
758                         /* The module is not a TIMER module */
759                         DPRINTK("The module is not a TIMER module\n");
760                         i_ReturnValue = -4;
761                 }
762         } else {
763                 /* Module number error */
764                 DPRINTK("Module number error\n");
765                 i_ReturnValue = -2;
766         }
767
768         return i_ReturnValue;
769 }
770
771         /*
772            +----------------------------------------------------------------------------+
773            | Function Name     : _INT_     i_APCI1710_GetTimerOutputLevel               |
774            |                                       (unsigned char_     b_BoardHandle,            |
775            |                                        unsigned char_     b_ModulNbr,               |
776            |                                        unsigned char_     b_TimerNbr,               |
777            |                                        unsigned char *_   pb_OutputLevel)            |
778            +----------------------------------------------------------------------------+
779            | Task              : Return the output signal level (pb_OutputLevel) from   |
780            |                     selected digital timer (b_TimerNbr) from selected timer|
781            |                     module (b_ModulNbr).                                   |
782            +----------------------------------------------------------------------------+
783            | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
784            |                                                 APCI-1710                  |
785            |                     unsigned char_   b_ModulNbr        : Selected module number     |
786            |                                                 (0 to 3)                   |
787            |                     unsigned char_   b_TimerNbr        : Timer number to test       |
788            |                                                 (0 to 2)                   |
789            +----------------------------------------------------------------------------+
790            | Output Parameters : unsigned char *_ pb_OutputLevel     : Output signal level        |
791            |                                                 0 : The output is low      |
792            |                                                 1 : The output is high     |
793            +----------------------------------------------------------------------------+
794            | Return Value      : 0: No error                                            |
795            |                    -1: The handle parameter of the board is wrong          |
796            |                    -2: Module selection wrong                              |
797            |                    -3: Timer selection wrong                               |
798            |                    -4: The module is not a TIMER module                    |
799            |                    -5: Timer not initialised see function                  |
800            |                        "i_APCI1710_InitTimer"                              |
801            +----------------------------------------------------------------------------+
802          */
803 static int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
804                                           unsigned char b_ModulNbr,
805                                           unsigned char b_TimerNbr,
806                                           unsigned char *pb_OutputLevel)
807 {
808         struct addi_private *devpriv = dev->private;
809         int i_ReturnValue = 0;
810         unsigned int dw_TimerStatus;
811
812         /* Test the module number */
813         if (b_ModulNbr < 4) {
814                 /* Test if 82X54 timer */
815                 if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
816                         /* Test the timer number */
817                         if (b_TimerNbr <= 2) {
818                                 /* Test if timer initialised */
819                                 if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
820                                         /* Latch the timer value */
821                                         outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
822
823                                         /* Read the timer status */
824                                         dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
825
826                                         *pb_OutputLevel = (unsigned char) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel);
827                                 } else {
828                                         /* Timer not initialised see function */
829                                         DPRINTK("Timer not initialised see function\n");
830                                         i_ReturnValue = -5;
831                                 }
832                         } else {
833                                 /* Timer selection wrong */
834                                 DPRINTK("Timer selection wrong\n");
835                                 i_ReturnValue = -3;
836                         }       /*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
837                 } else {
838                         /* The module is not a TIMER module */
839                         DPRINTK("The module is not a TIMER module\n");
840                         i_ReturnValue = -4;
841                 }
842         } else {
843                 /* Module number error */
844                 DPRINTK("Module number error\n");
845                 i_ReturnValue = -2;
846         }
847
848         return i_ReturnValue;
849 }
850
851 /*
852 +----------------------------------------------------------------------------+
853 | Function Name     : _INT_     i_APCI1710_GetTimerProgressStatus            |
854 |                                       (unsigned char_     b_BoardHandle,            |
855 |                                        unsigned char_     b_ModulNbr,               |
856 |                                        unsigned char_     b_TimerNbr,               |
857 |                                        unsigned char *_   pb_TimerStatus)            |
858 +----------------------------------------------------------------------------+
859 | Task              : Return the progress status (pb_TimerStatus) from       |
860 |                     selected digital timer (b_TimerNbr) from selected timer|
861 |                     module (b_ModulNbr).                                   |
862 +----------------------------------------------------------------------------+
863 | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
864 |                                                 APCI-1710                  |
865 |                     unsigned char_   b_ModulNbr        : Selected module number     |
866 |                                                 (0 to 3)                   |
867 |                     unsigned char_   b_TimerNbr        : Timer number to test       |
868 |                                                 (0 to 2)                   |
869 +----------------------------------------------------------------------------+
870 | Output Parameters : unsigned char *_ pb_TimerStatus     : Output signal level        |
871 |                                                 0 : Timer not in progress  |
872 |                                                 1 : Timer in progress      |
873 +----------------------------------------------------------------------------+
874 | Return Value      : 0: No error                                            |
875 |                    -1: The handle parameter of the board is wrong          |
876 |                    -2: Module selection wrong                              |
877 |                    -3: Timer selection wrong                               |
878 |                    -4: The module is not a TIMER module                    |
879 |                    -5: Timer not initialised see function                  |
880 |                        "i_APCI1710_InitTimer"                              |
881 +----------------------------------------------------------------------------+
882 */
883 static int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
884                                              unsigned char b_ModulNbr,
885                                              unsigned char b_TimerNbr,
886                                              unsigned char *pb_TimerStatus)
887 {
888         struct addi_private *devpriv = dev->private;
889         int i_ReturnValue = 0;
890         unsigned int dw_TimerStatus;
891
892         /* Test the module number */
893         if (b_ModulNbr < 4) {
894                 /* Test if 82X54 timer */
895
896                 if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
897                         /* Test the timer number */
898                         if (b_TimerNbr <= 2) {
899                                 /* Test if timer initialised */
900                                 if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
901                                         /* Latch the timer value */
902                                         outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
903
904                                         /* Read the timer status */
905                                         dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
906
907                                         *pb_TimerStatus = (unsigned char) ((dw_TimerStatus) >> 8) & 1;
908                                         printk("ProgressStatus : %d", *pb_TimerStatus);
909                                 } else {
910                                         /* Timer not initialised see function */
911                                         i_ReturnValue = -5;
912                                 }
913                         } else {
914                                 /* Timer selection wrong */
915                                 i_ReturnValue = -3;
916                         }       /*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
917                 } else {
918                         /* The module is not a TIMER module */
919
920                         i_ReturnValue = -4;
921                 }
922         } else {
923                 /* Module number error */
924
925                 i_ReturnValue = -2;
926         }
927
928         return i_ReturnValue;
929 }
930
931 /*
932 +----------------------------------------------------------------------------+
933 | Function Name     : _INT_     i_APCI1710_WriteTimerValue                   |
934 |                                       (unsigned char_   b_BoardHandle,              |
935 |                                        unsigned char_   b_ModulNbr,                 |
936 |                                        unsigned char_   b_TimerNbr,                 |
937 |                                        ULONG_ ul_WriteValue)               |
938 +----------------------------------------------------------------------------+
939 | Task              : Write the value (ul_WriteValue) into the selected timer|
940 |                     (b_TimerNbr) from selected timer module (b_ModulNbr).  |
941 |                     The action in depend of the time mode selection.       |
942 |                     See timer mode description table.                      |
943 +----------------------------------------------------------------------------+
944 | Input Parameters  : unsigned char_   b_BoardHandle     : Handle of board            |
945 |                                                 APCI-1710                  |
946 |                     unsigned char_   b_ModulNbr        : Selected module number     |
947 |                                                 (0 to 3)                   |
948 |                     unsigned char_   b_TimerNbr        : Timer number to write      |
949 |                                                 (0 to 2)                   |
950 |                     ULONG_ ul_WriteValue      : Value to write             |
951 +----------------------------------------------------------------------------+
952 | Output Parameters : -                                                      |
953 +----------------------------------------------------------------------------+
954 | Return Value      : 0: No error                                            |
955 |                    -1: The handle parameter of the board is wrong          |
956 |                    -2: Module selection wrong                              |
957 |                    -3: Timer selection wrong                               |
958 |                    -4: The module is not a TIMER module                    |
959 |                    -5: Timer not initialised see function                  |
960 |                        "i_APCI1710_InitTimer"                              |
961 +----------------------------------------------------------------------------+
962 */
963 static int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
964                                       unsigned char b_ModulNbr,
965                                       unsigned char b_TimerNbr,
966                                       unsigned int ul_WriteValue)
967 {
968         struct addi_private *devpriv = dev->private;
969         int i_ReturnValue = 0;
970
971         /* Test the module number */
972         if (b_ModulNbr < 4) {
973                 /* Test if 82X54 timer */
974                 if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
975                         /* Test the timer number */
976                         if (b_TimerNbr <= 2) {
977                                 /* Test if timer initialised */
978                                 if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
979                                         /* Write the value */
980                                         outl(ul_WriteValue, devpriv->s_BoardInfos.ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr));
981                                 } else {
982                                         /* Timer not initialised see function */
983                                         DPRINTK("Timer not initialised see function\n");
984                                         i_ReturnValue = -5;
985                                 }
986                         } else {
987                                 /* Timer selection wrong */
988                                 DPRINTK("Timer selection wrong\n");
989                                 i_ReturnValue = -3;
990                         }       /*  if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */
991                 } else {
992                         /* The module is not a TIMER module */
993                         DPRINTK("The module is not a TIMER module\n");
994                         i_ReturnValue = -4;
995                 }
996         } else {
997                 /* Module number error */
998                 DPRINTK("Module number error\n");
999                 i_ReturnValue = -2;
1000         }
1001
1002         return i_ReturnValue;
1003 }
1004
1005 /*
1006 +----------------------------------------------------------------------------+
1007 | Function Name     :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
1008 struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                   |
1009 +----------------------------------------------------------------------------+
1010 | Task              : Read write functions for Timer                                          |
1011 +----------------------------------------------------------------------------+
1012 | Input Parameters  :
1013 +----------------------------------------------------------------------------+
1014 | Output Parameters : -                                                      |
1015 +----------------------------------------------------------------------------+
1016 | Return Value      :
1017 +----------------------------------------------------------------------------+
1018 */
1019 static int i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
1020                                     struct comedi_subdevice *s,
1021                                     struct comedi_insn *insn,
1022                                     unsigned int *data)
1023 {
1024         unsigned char b_BitsType;
1025         int i_ReturnValue = 0;
1026         b_BitsType = data[0];
1027
1028         printk("\n82X54");
1029
1030         switch (b_BitsType) {
1031         case APCI1710_TIMER_READVALUE:
1032                 i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
1033                                                           (unsigned char)CR_AREF(insn->chanspec),
1034                                                           (unsigned char)CR_CHAN(insn->chanspec),
1035                                                           (unsigned int *) &data[0]);
1036                 break;
1037
1038         case APCI1710_TIMER_GETOUTPUTLEVEL:
1039                 i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
1040                                                                (unsigned char)CR_AREF(insn->chanspec),
1041                                                                (unsigned char)CR_CHAN(insn->chanspec),
1042                                                                (unsigned char *) &data[0]);
1043                 break;
1044
1045         case APCI1710_TIMER_GETPROGRESSSTATUS:
1046                 i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
1047                                                                   (unsigned char)CR_AREF(insn->chanspec),
1048                                                                   (unsigned char)CR_CHAN(insn->chanspec),
1049                                                                   (unsigned char *)&data[0]);
1050                 break;
1051
1052         case APCI1710_TIMER_WRITEVALUE:
1053                 i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
1054                                                            (unsigned char)CR_AREF(insn->chanspec),
1055                                                            (unsigned char)CR_CHAN(insn->chanspec),
1056                                                            (unsigned int)data[1]);
1057
1058                 break;
1059
1060         default:
1061                 printk("Bits Config Parameter Wrong\n");
1062                 i_ReturnValue = -1;
1063         }
1064
1065         if (i_ReturnValue >= 0)
1066                 i_ReturnValue = insn->n;
1067         return i_ReturnValue;
1068 }