Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / drivers / staging / comedi / drivers / addi-data / APCI1710_Ssi.c
1 /**
2 @verbatim
3
4 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5
6         ADDI-DATA GmbH
7         Dieselstrasse 3
8         D-77833 Ottersweier
9         Tel: +19(0)7223/9493-0
10         Fax: +49(0)7223/9493-92
11         http://www.addi-data-com
12         info@addi-data.com
13
14 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 You should also find the complete GPL in the COPYING file accompanying this source code.
21
22 @endverbatim
23 */
24 /*
25
26   +-----------------------------------------------------------------------+
27   | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
28   +-----------------------------------------------------------------------+
29   | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
30   | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
31   +-----------------------------------------------------------------------+
32   | Project     : API APCI1710    | Compiler : gcc                        |
33   | Module name : SSI.C           | Version  : 2.96                       |
34   +-------------------------------+---------------------------------------+
35   | Project manager: Eric Stolz   | Date     :  02/12/2002                |
36   +-----------------------------------------------------------------------+
37   | Description :   APCI-1710 SSI counter module                          |
38   |                                                                       |
39   |                                                                       |
40   +-----------------------------------------------------------------------+
41   |                             UPDATES                                   |
42   +-----------------------------------------------------------------------+
43   |   Date   |   Author  |          Description of updates                |
44   +----------+-----------+------------------------------------------------+
45   | 13/05/98 | S. Weber  | SSI digital input / output implementation      |
46   |----------|-----------|------------------------------------------------|
47   | 22/03/00 | C.Guinot  | 0100/0226 -> 0200/0227                         |
48   |          |           | Änderung in InitSSI Funktion                   |
49   |          |           | b_SSIProfile >= 2 anstatt b_SSIProfile > 2     |
50   |          |           |                                                |
51   +-----------------------------------------------------------------------+
52   | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
53   |          |           |   available                                    |
54   +-----------------------------------------------------------------------+
55 */
56
57 /*
58 +----------------------------------------------------------------------------+
59 |                               Included files                               |
60 +----------------------------------------------------------------------------+
61 */
62
63 #include "APCI1710_Ssi.h"
64
65 /*
66 +----------------------------------------------------------------------------+
67 | Function Name     : _INT_ i_APCI1710_InitSSI                               |
68 |                               (unsigned char_    b_BoardHandle,                     |
69 |                                unsigned char_    b_ModulNbr,                        |
70 |                                unsigned char_    b_SSIProfile,                      |
71 |                                unsigned char_    b_PositionTurnLength,              |
72 |                                unsigned char_    b_TurnCptLength,                   |
73 |                                unsigned char_    b_PCIInputClock,                   |
74 |                                ULONG_  ul_SSIOutputClock,                  |
75 |                                unsigned char_    b_SSICountingMode)                 |
76 +----------------------------------------------------------------------------+
77 | Task              : Configure the SSI operating mode from selected module  |
78 |                     (b_ModulNbr). You must calling this function be for you|
79 |                     call any other function witch access of SSI.           |
80 +----------------------------------------------------------------------------+
81 | Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
82 |                     unsigned char_ b_ModulNbr            : Module number to         |
83 |                                                   configure (0 to 3)       |
84 |                     unsigned char_  b_SSIProfile         : Selection from SSI       |
85 |                                                   profile length (2 to 32).|
86 |                     unsigned char_  b_PositionTurnLength : Selection from SSI       |
87 |                                                   position data length     |
88 |                                                   (1 to 31).               |
89 |                     unsigned char_  b_TurnCptLength      : Selection from SSI turn  |
90 |                                                   counter data length      |
91 |                                                   (1 to 31).               |
92 |                     unsigned char   b_PCIInputClock      : Selection from PCI bus   |
93 |                                                   clock                    |
94 |                                                 - APCI1710_30MHZ :         |
95 |                                                   The PC have a PCI bus    |
96 |                                                   clock from 30 MHz        |
97 |                                                 - APCI1710_33MHZ :         |
98 |                                                   The PC have a PCI bus    |
99 |                                                   clock from 33 MHz        |
100 |                     ULONG_ ul_SSIOutputClock    : Selection from SSI output|
101 |                                                   clock.                   |
102 |                                                   From  229 to 5 000 000 Hz|
103 |                                                   for 30 MHz selection.    |
104 |                                                   From  252 to 5 000 000 Hz|
105 |                                                   for 33 MHz selection.    |
106 |                     unsigned char   b_SSICountingMode    : SSI counting mode        |
107 |                                                   selection                |
108 |                                                 - APCI1710_BINARY_MODE :   |
109 |                                                    Binary counting mode.   |
110 |                                                 - APCI1710_GRAY_MODE :     |
111 |                                                    Gray counting mode.
112
113         b_ModulNbr                      = CR_AREF(insn->chanspec);
114         b_SSIProfile            = (unsigned char) data[0];
115         b_PositionTurnLength= (unsigned char) data[1];
116         b_TurnCptLength         = (unsigned char) data[2];
117         b_PCIInputClock         = (unsigned char) data[3];
118         ul_SSIOutputClock       = (unsigned int) data[4];
119         b_SSICountingMode       = (unsigned char)  data[5];     |
120 +----------------------------------------------------------------------------+
121 | Output Parameters : -                                                      |
122 +----------------------------------------------------------------------------+
123 | Return Value      : 0: No error                                            |
124 |                    -1: The handle parameter of the board is wrong          |
125 |                    -2: The module parameter is wrong                       |
126 |                    -3: The module is not a SSI module                      |
127 |                    -4: The selected SSI profile length is wrong            |
128 |                    -5: The selected SSI position data length is wrong      |
129 |                    -6: The selected SSI turn counter data length is wrong  |
130 |                    -7: The selected PCI input clock is wrong               |
131 |                    -8: The selected SSI output clock is wrong              |
132 |                    -9: The selected SSI counting mode parameter is wrong   |
133 +----------------------------------------------------------------------------+
134 */
135
136 int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
137         struct comedi_insn *insn, unsigned int *data)
138 {
139         int i_ReturnValue = 0;
140         unsigned int ui_TimerValue;
141         unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
142                 b_PCIInputClock, b_SSICountingMode;
143         unsigned int ul_SSIOutputClock;
144
145         b_ModulNbr = CR_AREF(insn->chanspec);
146         b_SSIProfile = (unsigned char) data[0];
147         b_PositionTurnLength = (unsigned char) data[1];
148         b_TurnCptLength = (unsigned char) data[2];
149         b_PCIInputClock = (unsigned char) data[3];
150         ul_SSIOutputClock = (unsigned int) data[4];
151         b_SSICountingMode = (unsigned char) data[5];
152
153         i_ReturnValue = insn->n;
154         /**************************/
155         /* Test the module number */
156         /**************************/
157
158         if (b_ModulNbr < 4) {
159            /***********************/
160                 /* Test if SSI counter */
161            /***********************/
162
163                 if ((devpriv->s_BoardInfos.
164                                 dw_MolduleConfiguration[b_ModulNbr] &
165                                 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
166               /*******************************/
167                         /* Test the SSI profile length */
168               /*******************************/
169
170                         /*  CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */
171                         if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
172                  /*************************************/
173                                 /* Test the SSI position data length */
174                  /*************************************/
175
176                                 if (b_PositionTurnLength > 0
177                                         && b_PositionTurnLength < 32) {
178                     /*****************************************/
179                                         /* Test the SSI turn counter data length */
180                     /*****************************************/
181
182                                         if (b_TurnCptLength > 0
183                                                 && b_TurnCptLength < 32) {
184                        /***************************/
185                                                 /* Test the profile length */
186                        /***************************/
187
188                                                 if ((b_TurnCptLength +
189                                                                 b_PositionTurnLength)
190                                                         <= b_SSIProfile) {
191                           /****************************/
192                                                         /* Test the PCI input clock */
193                           /****************************/
194
195                                                         if (b_PCIInputClock ==
196                                                                 APCI1710_30MHZ
197                                                                 ||
198                                                                 b_PCIInputClock
199                                                                 ==
200                                                                 APCI1710_33MHZ)
201                                                         {
202                              /*************************/
203                                                                 /* Test the output clock */
204                              /*************************/
205
206                                                                 if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) {
207                                                                         if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) {
208                                    /**********************/
209                                                                                 /* Save configuration */
210                                    /**********************/
211                                                                                 devpriv->
212                                                                                         s_ModuleInfo
213                                                                                         [b_ModulNbr].
214                                                                                         s_SSICounterInfo.
215                                                                                         b_SSIProfile
216                                                                                         =
217                                                                                         b_SSIProfile;
218
219                                                                                 devpriv->
220                                                                                         s_ModuleInfo
221                                                                                         [b_ModulNbr].
222                                                                                         s_SSICounterInfo.
223                                                                                         b_PositionTurnLength
224                                                                                         =
225                                                                                         b_PositionTurnLength;
226
227                                                                                 devpriv->
228                                                                                         s_ModuleInfo
229                                                                                         [b_ModulNbr].
230                                                                                         s_SSICounterInfo.
231                                                                                         b_TurnCptLength
232                                                                                         =
233                                                                                         b_TurnCptLength;
234
235                                    /*********************************/
236                                                                                 /* Initialise the profile length */
237                                    /*********************************/
238
239                                                                                 if (b_SSICountingMode == APCI1710_BINARY_MODE) {
240
241                                                                                         outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
242                                                                                 } else {
243
244                                                                                         outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
245                                                                                 }
246
247                                    /******************************/
248                                                                                 /* Calculate the output clock */
249                                    /******************************/
250
251                                                                                 ui_TimerValue
252                                                                                         =
253                                                                                         (unsigned int)
254                                                                                         (
255                                                                                         ((unsigned int) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
256
257                                    /************************/
258                                                                                 /* Initialise the timer */
259                                    /************************/
260
261                                                                                 outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
262
263                                    /********************************/
264                                                                                 /* Initialise the counting mode */
265                                    /********************************/
266
267                                                                                 outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
268
269                                                                                 devpriv->
270                                                                                         s_ModuleInfo
271                                                                                         [b_ModulNbr].
272                                                                                         s_SSICounterInfo.
273                                                                                         b_SSIInit
274                                                                                         =
275                                                                                         1;
276                                                                         } else {
277                                    /*****************************************************/
278                                                                                 /* The selected SSI counting mode parameter is wrong */
279                                    /*****************************************************/
280
281                                                                                 DPRINTK("The selected SSI counting mode parameter is wrong\n");
282                                                                                 i_ReturnValue
283                                                                                         =
284                                                                                         -9;
285                                                                         }
286                                                                 } else {
287                                 /******************************************/
288                                                                         /* The selected SSI output clock is wrong */
289                                 /******************************************/
290
291                                                                         DPRINTK("The selected SSI output clock is wrong\n");
292                                                                         i_ReturnValue
293                                                                                 =
294                                                                                 -8;
295                                                                 }
296                                                         } else {
297                              /*****************************************/
298                                                                 /* The selected PCI input clock is wrong */
299                              /*****************************************/
300
301                                                                 DPRINTK("The selected PCI input clock is wrong\n");
302                                                                 i_ReturnValue =
303                                                                         -7;
304                                                         }
305                                                 } else {
306                           /********************************************/
307                                                         /* The selected SSI profile length is wrong */
308                           /********************************************/
309
310                                                         DPRINTK("The selected SSI profile length is wrong\n");
311                                                         i_ReturnValue = -4;
312                                                 }
313                                         } else {
314                        /******************************************************/
315                                                 /* The selected SSI turn counter data length is wrong */
316                        /******************************************************/
317
318                                                 DPRINTK("The selected SSI turn counter data length is wrong\n");
319                                                 i_ReturnValue = -6;
320                                         }
321                                 } else {
322                     /**************************************************/
323                                         /* The selected SSI position data length is wrong */
324                     /**************************************************/
325
326                                         DPRINTK("The selected SSI position data length is wrong\n");
327                                         i_ReturnValue = -5;
328                                 }
329                         } else {
330                  /********************************************/
331                                 /* The selected SSI profile length is wrong */
332                  /********************************************/
333
334                                 DPRINTK("The selected SSI profile length is wrong\n");
335                                 i_ReturnValue = -4;
336                         }
337                 } else {
338               /**********************************/
339                         /* The module is not a SSI module */
340               /**********************************/
341
342                         DPRINTK("The module is not a SSI module\n");
343                         i_ReturnValue = -3;
344                 }
345         } else {
346            /***********************/
347                 /* Module number error */
348            /***********************/
349
350                 DPRINTK("Module number error\n");
351                 i_ReturnValue = -2;
352         }
353
354         return i_ReturnValue;
355 }
356
357 /*
358 +----------------------------------------------------------------------------+
359 | Function Name     : _INT_  i_APCI1710_Read1SSIValue                        |
360 |                               (unsigned char_     b_BoardHandle,                    |
361 |                                unsigned char_     b_ModulNbr,                       |
362 |                                unsigned char_     b_SelectedSSI,                    |
363 |                                PULONG_ pul_Position,                       |
364 |                                PULONG_ pul_TurnCpt)
365  int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
366         struct comedi_insn *insn,unsigned int *data)                       |
367 +----------------------------------------------------------------------------+
368 | Task              :
369
370
371                                                 Read the selected SSI counter (b_SelectedSSI) from     |
372 |                     selected module (b_ModulNbr).
373                                                 or Read all SSI counter (b_SelectedSSI) from              |
374 |                     selected module (b_ModulNbr).                            |
375 +----------------------------------------------------------------------------+
376 | Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
377 |                     unsigned char_ b_ModulNbr            : Module number to         |
378 |                                                   configure (0 to 3)       |
379 |                     unsigned char_ b_SelectedSSI         : Selection from SSI       |
380 |                                                   counter (0 to 2)
381
382     b_ModulNbr          =   (unsigned char) CR_AREF(insn->chanspec);
383         b_SelectedSSI   =       (unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi)
384         b_ReadType              =       (unsigned char) CR_RANGE(insn->chanspec);
385 |
386 +----------------------------------------------------------------------------+
387 | Output Parameters : PULONG_  pul_Position       : SSI position in the turn |
388 |                     PULONG_  pul_TurnCpt        : Number of turns
389
390 pul_Position    =       (unsigned int *) &data[0];
391         pul_TurnCpt             =       (unsigned int *) &data[1];         |
392 +----------------------------------------------------------------------------+
393 | Return Value      : 0: No error                                            |
394 |                    -1: The handle parameter of the board is wrong          |
395 |                    -2: The module parameter is wrong                       |
396 |                    -3: The module is not a SSI module                      |
397 |                    -4: SSI not initialised see function                    |
398 |                        "i_APCI1710_InitSSI"                                |
399 |                    -5: The selected SSI is wrong                           |
400 +----------------------------------------------------------------------------+
401 */
402
403 int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
404         struct comedi_insn *insn, unsigned int *data)
405 {
406         int i_ReturnValue = 0;
407         unsigned char b_Cpt;
408         unsigned char b_Length;
409         unsigned char b_Schift;
410         unsigned char b_SSICpt;
411         unsigned int dw_And;
412         unsigned int dw_And1;
413         unsigned int dw_And2;
414         unsigned int dw_StatusReg;
415         unsigned int dw_CounterValue;
416         unsigned char b_ModulNbr;
417         unsigned char b_SelectedSSI;
418         unsigned char b_ReadType;
419         unsigned int *pul_Position;
420         unsigned int *pul_TurnCpt;
421         unsigned int *pul_Position1;
422         unsigned int *pul_TurnCpt1;
423
424         i_ReturnValue = insn->n;
425         pul_Position1 = (unsigned int *) &data[0];
426 /* For Read1 */
427         pul_TurnCpt1 = (unsigned int *) &data[1];
428 /* For Read all */
429         pul_Position = (unsigned int *) &data[0];       /* 0-2 */
430         pul_TurnCpt = (unsigned int *) &data[3];        /* 3-5 */
431         b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
432         b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
433         b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
434
435         /**************************/
436         /* Test the module number */
437         /**************************/
438
439         if (b_ModulNbr < 4) {
440            /***********************/
441                 /* Test if SSI counter */
442            /***********************/
443
444                 if ((devpriv->s_BoardInfos.
445                                 dw_MolduleConfiguration[b_ModulNbr] &
446                                 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
447               /***************************/
448                         /* Test if SSI initialised */
449               /***************************/
450
451                         if (devpriv->s_ModuleInfo[b_ModulNbr].
452                                 s_SSICounterInfo.b_SSIInit == 1) {
453
454                                 switch (b_ReadType) {
455
456                                 case APCI1710_SSI_READ1VALUE:
457                  /****************************************/
458                                         /* Test the selected SSI counter number */
459                  /****************************************/
460
461                                         if (b_SelectedSSI < 3) {
462                     /************************/
463                                                 /* Start the conversion */
464                     /************************/
465
466                                                 outl(0, devpriv->s_BoardInfos.
467                                                         ui_Address + 8 +
468                                                         (64 * b_ModulNbr));
469
470                                                 do {
471                        /*******************/
472                                                         /* Read the status */
473                        /*******************/
474
475                                                         dw_StatusReg =
476                                                                 inl(devpriv->
477                                                                 s_BoardInfos.
478                                                                 ui_Address +
479                                                                 (64 * b_ModulNbr));
480                                                 } while ((dw_StatusReg & 0x1)
481                                                          != 0);
482
483                     /******************************/
484                                                 /* Read the SSI counter value */
485                     /******************************/
486
487                                                 dw_CounterValue =
488                                                         inl(devpriv->
489                                                         s_BoardInfos.
490                                                         ui_Address + 4 +
491                                                         (b_SelectedSSI * 4) +
492                                                         (64 * b_ModulNbr));
493
494                                                 b_Length =
495                                                         devpriv->
496                                                         s_ModuleInfo
497                                                         [b_ModulNbr].
498                                                         s_SSICounterInfo.
499                                                         b_SSIProfile / 2;
500
501                                                 if ((b_Length * 2) !=
502                                                         devpriv->
503                                                         s_ModuleInfo
504                                                         [b_ModulNbr].
505                                                         s_SSICounterInfo.
506                                                         b_SSIProfile) {
507                                                         b_Length++;
508                                                 }
509
510                                                 b_Schift =
511                                                         b_Length -
512                                                         devpriv->
513                                                         s_ModuleInfo
514                                                         [b_ModulNbr].
515                                                         s_SSICounterInfo.
516                                                         b_PositionTurnLength;
517
518                                                 *pul_Position1 =
519                                                         dw_CounterValue >>
520                                                         b_Schift;
521
522                                                 dw_And = 1;
523
524                                                 for (b_Cpt = 0;
525                                                         b_Cpt <
526                                                         devpriv->
527                                                         s_ModuleInfo
528                                                         [b_ModulNbr].
529                                                         s_SSICounterInfo.
530                                                         b_PositionTurnLength;
531                                                         b_Cpt++) {
532                                                         dw_And = dw_And * 2;
533                                                 }
534
535                                                 *pul_Position1 =
536                                                         *pul_Position1 &
537                                                         ((dw_And) - 1);
538
539                                                 *pul_TurnCpt1 =
540                                                         dw_CounterValue >>
541                                                         b_Length;
542
543                                                 dw_And = 1;
544
545                                                 for (b_Cpt = 0;
546                                                         b_Cpt <
547                                                         devpriv->
548                                                         s_ModuleInfo
549                                                         [b_ModulNbr].
550                                                         s_SSICounterInfo.
551                                                         b_TurnCptLength;
552                                                         b_Cpt++) {
553                                                         dw_And = dw_And * 2;
554                                                 }
555
556                                                 *pul_TurnCpt1 =
557                                                         *pul_TurnCpt1 &
558                                                         ((dw_And) - 1);
559                                         } else {
560                     /*****************************/
561                                                 /* The selected SSI is wrong */
562                     /*****************************/
563
564                                                 DPRINTK("The selected SSI is wrong\n");
565                                                 i_ReturnValue = -5;
566                                         }
567                                         break;
568
569                                 case APCI1710_SSI_READALLVALUE:
570                                         dw_And1 = 1;
571
572                                         for (b_Cpt = 0;
573                                                 b_Cpt <
574                                                 devpriv->
575                                                 s_ModuleInfo[b_ModulNbr].
576                                                 s_SSICounterInfo.
577                                                 b_PositionTurnLength; b_Cpt++) {
578                                                 dw_And1 = dw_And1 * 2;
579                                         }
580
581                                         dw_And2 = 1;
582
583                                         for (b_Cpt = 0;
584                                                 b_Cpt <
585                                                 devpriv->
586                                                 s_ModuleInfo[b_ModulNbr].
587                                                 s_SSICounterInfo.
588                                                 b_TurnCptLength; b_Cpt++) {
589                                                 dw_And2 = dw_And2 * 2;
590                                         }
591
592                  /************************/
593                                         /* Start the conversion */
594                  /************************/
595
596                                         outl(0, devpriv->s_BoardInfos.
597                                                 ui_Address + 8 +
598                                                 (64 * b_ModulNbr));
599
600                                         do {
601                     /*******************/
602                                                 /* Read the status */
603                     /*******************/
604
605                                                 dw_StatusReg =
606                                                         inl(devpriv->
607                                                         s_BoardInfos.
608                                                         ui_Address +
609                                                         (64 * b_ModulNbr));
610                                         } while ((dw_StatusReg & 0x1) != 0);
611
612                                         for (b_SSICpt = 0; b_SSICpt < 3;
613                                                 b_SSICpt++) {
614                     /******************************/
615                                                 /* Read the SSI counter value */
616                     /******************************/
617
618                                                 dw_CounterValue =
619                                                         inl(devpriv->
620                                                         s_BoardInfos.
621                                                         ui_Address + 4 +
622                                                         (b_SSICpt * 4) +
623                                                         (64 * b_ModulNbr));
624
625                                                 b_Length =
626                                                         devpriv->
627                                                         s_ModuleInfo
628                                                         [b_ModulNbr].
629                                                         s_SSICounterInfo.
630                                                         b_SSIProfile / 2;
631
632                                                 if ((b_Length * 2) !=
633                                                         devpriv->
634                                                         s_ModuleInfo
635                                                         [b_ModulNbr].
636                                                         s_SSICounterInfo.
637                                                         b_SSIProfile) {
638                                                         b_Length++;
639                                                 }
640
641                                                 b_Schift =
642                                                         b_Length -
643                                                         devpriv->
644                                                         s_ModuleInfo
645                                                         [b_ModulNbr].
646                                                         s_SSICounterInfo.
647                                                         b_PositionTurnLength;
648
649                                                 pul_Position[b_SSICpt] =
650                                                         dw_CounterValue >>
651                                                         b_Schift;
652                                                 pul_Position[b_SSICpt] =
653                                                         pul_Position[b_SSICpt] &
654                                                         ((dw_And1) - 1);
655
656                                                 pul_TurnCpt[b_SSICpt] =
657                                                         dw_CounterValue >>
658                                                         b_Length;
659                                                 pul_TurnCpt[b_SSICpt] =
660                                                         pul_TurnCpt[b_SSICpt] &
661                                                         ((dw_And2) - 1);
662                                         }
663                                         break;
664
665                                 default:
666                                         printk("Read Type Inputs Wrong\n");
667
668                                 }       /*  switch  ending */
669
670                         } else {
671                  /***********************/
672                                 /* SSI not initialised */
673                  /***********************/
674
675                                 DPRINTK("SSI not initialised\n");
676                                 i_ReturnValue = -4;
677                         }
678                 } else {
679               /**********************************/
680                         /* The module is not a SSI module */
681               /**********************************/
682
683                         DPRINTK("The module is not a SSI module\n");
684                         i_ReturnValue = -3;
685
686                 }
687         } else {
688            /***********************/
689                 /* Module number error */
690            /***********************/
691
692                 DPRINTK("Module number error\n");
693                 i_ReturnValue = -2;
694         }
695
696         return i_ReturnValue;
697 }
698
699 /*
700 +----------------------------------------------------------------------------+
701 | Function Name     : _INT_   i_APCI1710_ReadSSI1DigitalInput                |
702 |                                       (unsigned char_     b_BoardHandle,            |
703 |                                        unsigned char_     b_ModulNbr,               |
704 |                                        unsigned char_     b_InputChannel,           |
705 |                                        unsigned char *_   pb_ChannelStatus)          |
706 +----------------------------------------------------------------------------+
707 | Task              :
708                                         (0) Set the digital output from selected SSI moule         |
709 |                     (b_ModuleNbr) ON
710                     (1) Set the digital output from selected SSI moule         |
711 |                     (b_ModuleNbr) OFF
712                                         (2)Read the status from selected SSI digital input        |
713 |                     (b_InputChannel)
714                     (3)Read the status from all SSI digital inputs from       |
715 |                     selected SSI module (b_ModulNbr)                   |
716 +----------------------------------------------------------------------------+
717 | Input Parameters  : unsigned char_ b_BoardHandle         : Handle of board APCI-1710|
718 |                     unsigned char_ b_ModulNbr    CR_AREF        : Module number to         |
719 |                                                   configure (0 to 3)       |
720 |                     unsigned char_ b_InputChannel CR_CHAN       : Selection from digital   |
721 |                        data[0] which IOTYPE                           input ( 0 to 2)          |
722 +----------------------------------------------------------------------------+
723 | Output Parameters : unsigned char *_  pb_ChannelStatus    : Digital input channel    |
724 |                                 data[0]                  status                   |
725 |                                                   0 : Channle is not active|
726 |                                                   1 : Channle is active    |
727 +----------------------------------------------------------------------------+
728 | Return Value      : 0: No error                                            |
729 |                    -1: The handle parameter of the board is wrong          |
730 |                    -2: The module parameter is wrong                       |
731 |                    -3: The module is not a SSI module                      |
732 |                    -4: The selected SSI digital input is wrong             |
733 +----------------------------------------------------------------------------+
734 */
735
736 int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
737         struct comedi_insn *insn, unsigned int *data)
738 {
739         int i_ReturnValue = 0;
740         unsigned int dw_StatusReg;
741         unsigned char b_ModulNbr;
742         unsigned char b_InputChannel;
743         unsigned char *pb_ChannelStatus;
744         unsigned char *pb_InputStatus;
745         unsigned char b_IOType;
746         i_ReturnValue = insn->n;
747         b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
748         b_IOType = (unsigned char) data[0];
749
750         /**************************/
751         /* Test the module number */
752         /**************************/
753
754         if (b_ModulNbr < 4) {
755            /***********************/
756                 /* Test if SSI counter */
757            /***********************/
758
759                 if ((devpriv->s_BoardInfos.
760                                 dw_MolduleConfiguration[b_ModulNbr] &
761                                 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
762                         switch (b_IOType) {
763                         case APCI1710_SSI_SET_CHANNELON:
764                                         /*****************************/
765                                 /* Set the digital output ON */
766                                         /*****************************/
767
768                                 outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
769                                         (64 * b_ModulNbr));
770                                 break;
771
772                         case APCI1710_SSI_SET_CHANNELOFF:
773                                         /******************************/
774                                 /* Set the digital output OFF */
775                                         /******************************/
776
777                                 outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
778                                         (64 * b_ModulNbr));
779                                 break;
780
781                         case APCI1710_SSI_READ_1CHANNEL:
782                                    /******************************************/
783                                 /* Test the digital imnput channel number */
784                                    /******************************************/
785
786                                 b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
787                                 pb_ChannelStatus = (unsigned char *) &data[0];
788
789                                 if (b_InputChannel <= 2) {
790                                         /**************************/
791                                         /* Read all digital input */
792                                         /**************************/
793
794                                         dw_StatusReg =
795                                                 inl(devpriv->s_BoardInfos.
796                                                 ui_Address + (64 * b_ModulNbr));
797                                         *pb_ChannelStatus =
798                                                 (unsigned char) (((~dw_StatusReg) >> (4 +
799                                                                 b_InputChannel))
800                                                 & 1);
801                                 } else {
802                                         /********************************/
803                                         /* Selected digital input error */
804                                         /********************************/
805
806                                         DPRINTK("Selected digital input error\n");
807                                         i_ReturnValue = -4;
808                                 }
809                                 break;
810
811                         case APCI1710_SSI_READ_ALLCHANNEL:
812                                         /**************************/
813                                 /* Read all digital input */
814                                         /**************************/
815                                 pb_InputStatus = (unsigned char *) &data[0];
816
817                                 dw_StatusReg =
818                                         inl(devpriv->s_BoardInfos.ui_Address +
819                                         (64 * b_ModulNbr));
820                                 *pb_InputStatus =
821                                         (unsigned char) (((~dw_StatusReg) >> 4) & 7);
822                                 break;
823
824                         default:
825                                 printk("IO type wrong\n");
826
827                         }       /* switch end */
828                 } else {
829               /**********************************/
830                         /* The module is not a SSI module */
831               /**********************************/
832
833                         DPRINTK("The module is not a SSI module\n");
834                         i_ReturnValue = -3;
835                 }
836         } else {
837            /***********************/
838                 /* Module number error */
839            /***********************/
840
841                 DPRINTK("Module number error\n");
842                 i_ReturnValue = -2;
843         }
844
845         return i_ReturnValue;
846 }