APCI1710_Ssi.c revision 34c43922e62708d45e9660eee4b4f1fb7b4bf2c7
1/**
2@verbatim
3
4Copyright (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
14This 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
16This 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
18You 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
20You shoud 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|                               (BYTE_    b_BoardHandle,                     |
69|                                BYTE_    b_ModulNbr,                        |
70|                                BYTE_    b_SSIProfile,                      |
71|                                BYTE_    b_PositionTurnLength,              |
72|                                BYTE_    b_TurnCptLength,                   |
73|                                BYTE_    b_PCIInputClock,                   |
74|                                ULONG_  ul_SSIOutputClock,                  |
75|                                BYTE_    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  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
82|                     BYTE_ b_ModulNbr            : Module number to         |
83|                                                   configure (0 to 3)       |
84|                     BYTE_  b_SSIProfile         : Selection from SSI       |
85|                                                   profile length (2 to 32).|
86|                     BYTE_  b_PositionTurnLength : Selection from SSI       |
87|                                                   position data length     |
88|                                                   (1 to 31).               |
89|                     BYTE_  b_TurnCptLength      : Selection from SSI turn  |
90|                                                   counter data length      |
91|                                                   (1 to 31).               |
92|                     BYTE   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|                     BYTE   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		= (BYTE) data[0];
115	b_PositionTurnLength= (BYTE) data[1];
116	b_TurnCptLength		= (BYTE) data[2];
117	b_PCIInputClock		= (BYTE) data[3];
118	ul_SSIOutputClock	= (ULONG) data[4];
119	b_SSICountingMode	= (BYTE)  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
136INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
137	comedi_insn * insn, unsigned int * data)
138{
139	INT i_ReturnValue = 0;
140	UINT ui_TimerValue;
141	BYTE b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
142		b_PCIInputClock, b_SSICountingMode;
143	ULONG ul_SSIOutputClock;
144
145	b_ModulNbr = CR_AREF(insn->chanspec);
146	b_SSIProfile = (BYTE) data[0];
147	b_PositionTurnLength = (BYTE) data[1];
148	b_TurnCptLength = (BYTE) data[2];
149	b_PCIInputClock = (BYTE) data[3];
150	ul_SSIOutputClock = (ULONG) data[4];
151	b_SSICountingMode = (BYTE) 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											(UINT)
254											(
255											((ULONG) (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|                               (BYTE_     b_BoardHandle,                    |
361|                                BYTE_     b_ModulNbr,                       |
362|                                BYTE_     b_SelectedSSI,                    |
363|                                PULONG_ pul_Position,                       |
364|                                PULONG_ pul_TurnCpt)
365 INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
366	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  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
377|                     BYTE_ b_ModulNbr            : Module number to         |
378|                                                   configure (0 to 3)       |
379|                     BYTE_ b_SelectedSSI         : Selection from SSI       |
380|                                                   counter (0 to 2)
381
382    b_ModulNbr		=   (BYTE) CR_AREF(insn->chanspec);
383	b_SelectedSSI	=	(BYTE) CR_CHAN(insn->chanspec); (in case of single ssi)
384	b_ReadType		=	(BYTE) 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
390pul_Position	=	(PULONG) &data[0];
391	pul_TurnCpt		=	(PULONG) &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
403INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
404	comedi_insn * insn, unsigned int * data)
405{
406	INT i_ReturnValue = 0;
407	BYTE b_Cpt;
408	BYTE b_Length;
409	BYTE b_Schift;
410	BYTE b_SSICpt;
411	DWORD dw_And;
412	DWORD dw_And1;
413	DWORD dw_And2;
414	DWORD dw_StatusReg;
415	DWORD dw_CounterValue;
416	BYTE b_ModulNbr;
417	BYTE b_SelectedSSI;
418	BYTE b_ReadType;
419	PULONG pul_Position;
420	PULONG pul_TurnCpt;
421	PULONG pul_Position1;
422	PULONG pul_TurnCpt1;
423
424	i_ReturnValue = insn->n;
425	pul_Position1 = (PULONG) & data[0];
426// For Read1
427	pul_TurnCpt1 = (PULONG) & data[1];
428// For Read all
429	pul_Position = (PULONG) & data[0];	//0-2
430	pul_TurnCpt = (PULONG) & data[3];	//3-5
431	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
432	b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec);
433	b_ReadType = (BYTE) 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						}
481						while ((dw_StatusReg & 0x1) !=
482							0);
483
484		    /******************************/
485						/* Read the SSI counter value */
486		    /******************************/
487
488						dw_CounterValue =
489							inl(devpriv->
490							s_BoardInfos.
491							ui_Address + 4 +
492							(b_SelectedSSI * 4) +
493							(64 * b_ModulNbr));
494
495						b_Length =
496							devpriv->
497							s_ModuleInfo
498							[b_ModulNbr].
499							s_SSICounterInfo.
500							b_SSIProfile / 2;
501
502						if ((b_Length * 2) !=
503							devpriv->
504							s_ModuleInfo
505							[b_ModulNbr].
506							s_SSICounterInfo.
507							b_SSIProfile) {
508							b_Length++;
509						}
510
511						b_Schift =
512							b_Length -
513							devpriv->
514							s_ModuleInfo
515							[b_ModulNbr].
516							s_SSICounterInfo.
517							b_PositionTurnLength;
518
519						*pul_Position1 =
520							dw_CounterValue >>
521							b_Schift;
522
523						dw_And = 1;
524
525						for (b_Cpt = 0;
526							b_Cpt <
527							devpriv->
528							s_ModuleInfo
529							[b_ModulNbr].
530							s_SSICounterInfo.
531							b_PositionTurnLength;
532							b_Cpt++) {
533							dw_And = dw_And * 2;
534						}
535
536						*pul_Position1 =
537							*pul_Position1 &
538							((dw_And) - 1);
539
540						*pul_TurnCpt1 =
541							dw_CounterValue >>
542							b_Length;
543
544						dw_And = 1;
545
546						for (b_Cpt = 0;
547							b_Cpt <
548							devpriv->
549							s_ModuleInfo
550							[b_ModulNbr].
551							s_SSICounterInfo.
552							b_TurnCptLength;
553							b_Cpt++) {
554							dw_And = dw_And * 2;
555						}
556
557						*pul_TurnCpt1 =
558							*pul_TurnCpt1 &
559							((dw_And) - 1);
560					} else {
561		    /*****************************/
562						/* The selected SSI is wrong */
563		    /*****************************/
564
565						DPRINTK("The selected SSI is wrong\n");
566						i_ReturnValue = -5;
567					}
568					break;
569
570				case APCI1710_SSI_READALLVALUE:
571					dw_And1 = 1;
572
573					for (b_Cpt = 0;
574						b_Cpt <
575						devpriv->
576						s_ModuleInfo[b_ModulNbr].
577						s_SSICounterInfo.
578						b_PositionTurnLength; b_Cpt++) {
579						dw_And1 = dw_And1 * 2;
580					}
581
582					dw_And2 = 1;
583
584					for (b_Cpt = 0;
585						b_Cpt <
586						devpriv->
587						s_ModuleInfo[b_ModulNbr].
588						s_SSICounterInfo.
589						b_TurnCptLength; b_Cpt++) {
590						dw_And2 = dw_And2 * 2;
591					}
592
593		 /************************/
594					/* Start the conversion */
595		 /************************/
596
597					outl(0, devpriv->s_BoardInfos.
598						ui_Address + 8 +
599						(64 * b_ModulNbr));
600
601					do {
602		    /*******************/
603						/* Read the status */
604		    /*******************/
605
606						dw_StatusReg =
607							inl(devpriv->
608							s_BoardInfos.
609							ui_Address +
610							(64 * b_ModulNbr));
611					}
612					while ((dw_StatusReg & 0x1) != 0);
613
614					for (b_SSICpt = 0; b_SSICpt < 3;
615						b_SSICpt++) {
616		    /******************************/
617						/* Read the SSI counter value */
618		    /******************************/
619
620						dw_CounterValue =
621							inl(devpriv->
622							s_BoardInfos.
623							ui_Address + 4 +
624							(b_SSICpt * 4) +
625							(64 * b_ModulNbr));
626
627						b_Length =
628							devpriv->
629							s_ModuleInfo
630							[b_ModulNbr].
631							s_SSICounterInfo.
632							b_SSIProfile / 2;
633
634						if ((b_Length * 2) !=
635							devpriv->
636							s_ModuleInfo
637							[b_ModulNbr].
638							s_SSICounterInfo.
639							b_SSIProfile) {
640							b_Length++;
641						}
642
643						b_Schift =
644							b_Length -
645							devpriv->
646							s_ModuleInfo
647							[b_ModulNbr].
648							s_SSICounterInfo.
649							b_PositionTurnLength;
650
651						pul_Position[b_SSICpt] =
652							dw_CounterValue >>
653							b_Schift;
654						pul_Position[b_SSICpt] =
655							pul_Position[b_SSICpt] &
656							((dw_And1) - 1);
657
658						pul_TurnCpt[b_SSICpt] =
659							dw_CounterValue >>
660							b_Length;
661						pul_TurnCpt[b_SSICpt] =
662							pul_TurnCpt[b_SSICpt] &
663							((dw_And2) - 1);
664					}
665					break;
666
667				default:
668					printk("Read Type Inputs Wrong\n");
669
670				}	// switch  ending
671
672			} else {
673		 /***********************/
674				/* SSI not initialised */
675		 /***********************/
676
677				DPRINTK("SSI not initialised\n");
678				i_ReturnValue = -4;
679			}
680		} else {
681	      /**********************************/
682			/* The module is not a SSI module */
683	      /**********************************/
684
685			DPRINTK("The module is not a SSI module\n");
686			i_ReturnValue = -3;
687
688		}
689	} else {
690	   /***********************/
691		/* Module number error */
692	   /***********************/
693
694		DPRINTK("Module number error\n");
695		i_ReturnValue = -2;
696	}
697
698	return (i_ReturnValue);
699}
700
701/*
702+----------------------------------------------------------------------------+
703| Function Name     : _INT_   i_APCI1710_ReadSSI1DigitalInput                |
704|                                       (BYTE_     b_BoardHandle,            |
705|                                        BYTE_     b_ModulNbr,               |
706|                                        BYTE_     b_InputChannel,           |
707|                                        PBYTE_   pb_ChannelStatus)          |
708+----------------------------------------------------------------------------+
709| Task              :
710					(0) Set the digital output from selected SSI moule         |
711|                     (b_ModuleNbr) ON
712                    (1) Set the digital output from selected SSI moule         |
713|                     (b_ModuleNbr) OFF
714					(2)Read the status from selected SSI digital input        |
715|                     (b_InputChannel)
716                    (3)Read the status from all SSI digital inputs from       |
717|                     selected SSI module (b_ModulNbr)                   |
718+----------------------------------------------------------------------------+
719| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
720|                     BYTE_ b_ModulNbr    CR_AREF        : Module number to         |
721|                                                   configure (0 to 3)       |
722|                     BYTE_ b_InputChannel CR_CHAN       : Selection from digital   |
723|                        data[0] which IOTYPE                           input ( 0 to 2)          |
724+----------------------------------------------------------------------------+
725| Output Parameters : PBYTE_  pb_ChannelStatus    : Digital input channel    |
726|                                 data[0]                  status                   |
727|                                                   0 : Channle is not active|
728|                                                   1 : Channle is active    |
729+----------------------------------------------------------------------------+
730| Return Value      : 0: No error                                            |
731|                    -1: The handle parameter of the board is wrong          |
732|                    -2: The module parameter is wrong                       |
733|                    -3: The module is not a SSI module                      |
734|                    -4: The selected SSI digital input is wrong             |
735+----------------------------------------------------------------------------+
736*/
737
738INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
739	comedi_insn * insn, unsigned int * data)
740{
741	INT i_ReturnValue = 0;
742	DWORD dw_StatusReg;
743	BYTE b_ModulNbr;
744	BYTE b_InputChannel;
745	PBYTE pb_ChannelStatus;
746	PBYTE pb_InputStatus;
747	BYTE b_IOType;
748	i_ReturnValue = insn->n;
749	b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
750	b_IOType = (BYTE) data[0];
751
752	/**************************/
753	/* Test the module number */
754	/**************************/
755
756	if (b_ModulNbr < 4) {
757	   /***********************/
758		/* Test if SSI counter */
759	   /***********************/
760
761		if ((devpriv->s_BoardInfos.
762				dw_MolduleConfiguration[b_ModulNbr] &
763				0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
764			switch (b_IOType) {
765			case APCI1710_SSI_SET_CHANNELON:
766					/*****************************/
767				/* Set the digital output ON */
768					/*****************************/
769
770				outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
771					(64 * b_ModulNbr));
772				break;
773
774			case APCI1710_SSI_SET_CHANNELOFF:
775					/******************************/
776				/* Set the digital output OFF */
777					/******************************/
778
779				outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
780					(64 * b_ModulNbr));
781				break;
782
783			case APCI1710_SSI_READ_1CHANNEL:
784				   /******************************************/
785				/* Test the digital imnput channel number */
786				   /******************************************/
787
788				b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
789				pb_ChannelStatus = (PBYTE) & data[0];
790
791				if (b_InputChannel <= 2) {
792					/**************************/
793					/* Read all digital input */
794					/**************************/
795
796					dw_StatusReg =
797						inl(devpriv->s_BoardInfos.
798						ui_Address + (64 * b_ModulNbr));
799					*pb_ChannelStatus =
800						(BYTE) (((~dw_StatusReg) >> (4 +
801								b_InputChannel))
802						& 1);
803				} else {
804					/********************************/
805					/* Selected digital input error */
806					/********************************/
807
808					DPRINTK("Selected digital input error\n");
809					i_ReturnValue = -4;
810				}
811				break;
812
813			case APCI1710_SSI_READ_ALLCHANNEL:
814					/**************************/
815				/* Read all digital input */
816					/**************************/
817				pb_InputStatus = (PBYTE) & data[0];
818
819				dw_StatusReg =
820					inl(devpriv->s_BoardInfos.ui_Address +
821					(64 * b_ModulNbr));
822				*pb_InputStatus =
823					(BYTE) (((~dw_StatusReg) >> 4) & 7);
824				break;
825
826			default:
827				printk("IO type wrong\n");
828
829			}	//switch end
830		} else {
831	      /**********************************/
832			/* The module is not a SSI module */
833	      /**********************************/
834
835			DPRINTK("The module is not a SSI module\n");
836			i_ReturnValue = -3;
837		}
838	} else {
839	   /***********************/
840		/* Module number error */
841	   /***********************/
842
843		DPRINTK("Module number error\n");
844		i_ReturnValue = -2;
845	}
846
847	return (i_ReturnValue);
848}
849