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