hwdrv_apci3xxx.c revision 39cfb97b0d89a99c8e50782b17e65114b89c2e59
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 should also find the complete GPL in the COPYING file accompanying this source code.
21
22@endverbatim
23*/
24/*
25  +-----------------------------------------------------------------------+
26  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
27  +-----------------------------------------------------------------------+
28  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
29  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
30  +-----------------------------------------------------------------------+
31  | Project     : APCI-3XXX       | Compiler   : GCC                      |
32  | Module name : hwdrv_apci3xxx.c| Version    : 2.96                     |
33  +-------------------------------+---------------------------------------+
34  | Project manager: S. Weber     | Date       :  15/09/2005              |
35  +-----------------------------------------------------------------------+
36  | Description :APCI3XXX Module.  Hardware abstraction Layer for APCI3XXX|
37  +-----------------------------------------------------------------------+
38  |                             UPDATE'S                                  |
39  +-----------------------------------------------------------------------+
40  |   Date   |   Author  |          Description of updates                |
41  +----------+-----------+------------------------------------------------+
42  |          | 		 | 						  |
43  |          |           |						  |
44  +----------+-----------+------------------------------------------------+
45*/
46
47#include "hwdrv_apci3xxx.h"
48
49/*
50+----------------------------------------------------------------------------+
51|                         ANALOG INPUT FUNCTIONS                             |
52+----------------------------------------------------------------------------+
53*/
54
55/*
56+----------------------------------------------------------------------------+
57| Function Name     : int   i_APCI3XXX_TestConversionStarted                 |
58|                          (struct comedi_device    *dev)                           |
59+----------------------------------------------------------------------------+
60| Task                Test if any conversion started                         |
61+----------------------------------------------------------------------------+
62| Input Parameters  : -                                                      |
63+----------------------------------------------------------------------------+
64| Output Parameters : -                                                      |
65+----------------------------------------------------------------------------+
66| Return Value      : 0 : Conversion not started                             |
67|                     1 : Conversion started                                 |
68+----------------------------------------------------------------------------+
69*/
70
71int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
72{
73	if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL)
74		return 1;
75	else
76		return 0;
77
78}
79
80/*
81+----------------------------------------------------------------------------+
82| Function Name     : int   i_APCI3XXX_AnalogInputConfigOperatingMode        |
83|                          (struct comedi_device    *dev,                           |
84|                           struct comedi_subdevice *s,                             |
85|                           struct comedi_insn      *insn,                          |
86|                           unsigned int         *data)                          |
87+----------------------------------------------------------------------------+
88| Task           Converting mode and convert time selection                  |
89+----------------------------------------------------------------------------+
90| Input Parameters  : b_SingleDiff  = (unsigned char)  data[1];                       |
91|                     b_TimeBase    = (unsigned char)  data[2]; (0: ns, 1:micros 2:ms)|
92|                    dw_ReloadValue = (unsigned int) data[3];                       |
93|                     ........                                               |
94+----------------------------------------------------------------------------+
95| Output Parameters : -                                                      |
96+----------------------------------------------------------------------------+
97| Return Value      :>0 : No error                                           |
98|                    -1 : Single/Diff selection error                        |
99|                    -2 : Convert time base unity selection error            |
100|                    -3 : Convert time value selection error                 |
101|                    -10: Any conversion started                             |
102|                    ....                                                    |
103|                    -100 : Config command error                             |
104|                    -101 : Data size error                                  |
105+----------------------------------------------------------------------------+
106*/
107
108int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
109	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
110{
111	int i_ReturnValue = insn->n;
112	unsigned char b_TimeBase = 0;
113	unsigned char b_SingleDiff = 0;
114	unsigned int dw_ReloadValue = 0;
115	unsigned int dw_TestReloadValue = 0;
116
117	/************************/
118	/* Test the buffer size */
119	/************************/
120
121	if (insn->n == 4) {
122	   /****************************/
123		/* Get the Singel/Diff flag */
124	   /****************************/
125
126		b_SingleDiff = (unsigned char) data[1];
127
128	   /****************************/
129		/* Get the time base unitiy */
130	   /****************************/
131
132		b_TimeBase = (unsigned char) data[2];
133
134	   /*************************************/
135		/* Get the convert time reload value */
136	   /*************************************/
137
138		dw_ReloadValue = (unsigned int) data[3];
139
140	   /**********************/
141		/* Test the time base */
142	   /**********************/
143
144		if ((devpriv->ps_BoardInfo->
145				b_AvailableConvertUnit & (1 << b_TimeBase)) !=
146			0) {
147	      /*******************************/
148			/* Test the convert time value */
149	      /*******************************/
150
151			if (dw_ReloadValue <= 65535) {
152				dw_TestReloadValue = dw_ReloadValue;
153
154				if (b_TimeBase == 1) {
155					dw_TestReloadValue =
156						dw_TestReloadValue * 1000UL;
157				}
158				if (b_TimeBase == 2) {
159					dw_TestReloadValue =
160						dw_TestReloadValue * 1000000UL;
161				}
162
163		 /*******************************/
164				/* Test the convert time value */
165		 /*******************************/
166
167				if (dw_TestReloadValue >=
168					devpriv->ps_BoardInfo->
169					ui_MinAcquisitiontimeNs) {
170					if ((b_SingleDiff == APCI3XXX_SINGLE)
171						|| (b_SingleDiff ==
172							APCI3XXX_DIFF)) {
173						if (((b_SingleDiff == APCI3XXX_SINGLE) && (devpriv->ps_BoardInfo->i_NbrAiChannel == 0)) || ((b_SingleDiff == APCI3XXX_DIFF) && (devpriv->ps_BoardInfo->i_NbrAiChannelDiff == 0))) {
174			   /*******************************/
175							/* Single/Diff selection error */
176			   /*******************************/
177
178							printk("Single/Diff selection error\n");
179							i_ReturnValue = -1;
180						} else {
181			   /**********************************/
182							/* Test if conversion not started */
183			   /**********************************/
184
185							if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
186								devpriv->
187									ui_EocEosConversionTime
188									=
189									(unsigned int)
190									dw_ReloadValue;
191								devpriv->
192									b_EocEosConversionTimeBase
193									=
194									b_TimeBase;
195								devpriv->
196									b_SingelDiff
197									=
198									b_SingleDiff;
199								devpriv->
200									b_AiInitialisation
201									= 1;
202
203			      /*******************************/
204								/* Set the convert timing unit */
205			      /*******************************/
206
207								writel((unsigned int)
208									b_TimeBase,
209									(void *)
210									(devpriv->
211										dw_AiBase
212										+
213										36));
214
215			      /**************************/
216								/* Set the convert timing */
217			      /*************************/
218
219								writel(dw_ReloadValue, (void *)(devpriv->dw_AiBase + 32));
220							} else {
221			      /**************************/
222								/* Any conversion started */
223			      /**************************/
224
225								printk("Any conversion started\n");
226								i_ReturnValue =
227									-10;
228							}
229						}
230					} else {
231		       /*******************************/
232						/* Single/Diff selection error */
233		       /*******************************/
234
235						printk("Single/Diff selection error\n");
236						i_ReturnValue = -1;
237					}
238				} else {
239		    /************************/
240					/* Time selection error */
241		    /************************/
242
243					printk("Convert time value selection error\n");
244					i_ReturnValue = -3;
245				}
246			} else {
247		 /************************/
248				/* Time selection error */
249		 /************************/
250
251				printk("Convert time value selection error\n");
252				i_ReturnValue = -3;
253			}
254		} else {
255	      /*****************************/
256			/* Time base selection error */
257	      /*****************************/
258
259			printk("Convert time base unity selection error\n");
260			i_ReturnValue = -2;
261		}
262	} else {
263	   /*******************/
264		/* Data size error */
265	   /*******************/
266
267		printk("Buffer size error\n");
268		i_ReturnValue = -101;
269	}
270
271	return i_ReturnValue;
272}
273
274/*
275+----------------------------------------------------------------------------+
276| Function Name     : int   i_APCI3XXX_InsnConfigAnalogInput                 |
277|                          (struct comedi_device    *dev,                           |
278|                           struct comedi_subdevice *s,                             |
279|                           struct comedi_insn      *insn,                          |
280|                           unsigned int         *data)                          |
281+----------------------------------------------------------------------------+
282| Task           Converting mode and convert time selection                  |
283+----------------------------------------------------------------------------+
284| Input Parameters  : b_ConvertMode = (unsigned char)  data[0];                       |
285|                     b_TimeBase    = (unsigned char)  data[1]; (0: ns, 1:micros 2:ms)|
286|                    dw_ReloadValue = (unsigned int) data[2];                       |
287|                     ........                                               |
288+----------------------------------------------------------------------------+
289| Output Parameters : -                                                      |
290+----------------------------------------------------------------------------+
291| Return Value      :>0: No error                                            |
292|                    ....                                                    |
293|                    -100 : Config command error                             |
294|                    -101 : Data size error                                  |
295+----------------------------------------------------------------------------+
296*/
297
298int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
299	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
300{
301	int i_ReturnValue = insn->n;
302
303	/************************/
304	/* Test the buffer size */
305	/************************/
306
307	if (insn->n >= 1) {
308		switch ((unsigned char) data[0]) {
309		case APCI3XXX_CONFIGURATION:
310			i_ReturnValue =
311				i_APCI3XXX_AnalogInputConfigOperatingMode(dev,
312				s, insn, data);
313			break;
314
315		default:
316			i_ReturnValue = -100;
317			printk("Config command error %d\n", data[0]);
318			break;
319		}
320	} else {
321	   /*******************/
322		/* Data size error */
323	   /*******************/
324
325		printk("Buffer size error\n");
326		i_ReturnValue = -101;
327	}
328
329	return i_ReturnValue;
330}
331
332/*
333+----------------------------------------------------------------------------+
334| Function Name     : int   i_APCI3XXX_InsnReadAnalogInput                   |
335|                          (struct comedi_device    *dev,                           |
336|                           struct comedi_subdevice *s,                             |
337|                           struct comedi_insn      *insn,                          |
338|                           unsigned int         *data)                          |
339+----------------------------------------------------------------------------+
340| Task                Read 1 analog input                                    |
341+----------------------------------------------------------------------------+
342| Input Parameters  : b_Range             = CR_RANGE(insn->chanspec);        |
343|                     b_Channel           = CR_CHAN(insn->chanspec);         |
344|                     dw_NbrOfAcquisition = insn->n;                         |
345+----------------------------------------------------------------------------+
346| Output Parameters : -                                                      |
347+----------------------------------------------------------------------------+
348| Return Value      :>0: No error                                            |
349|                    -3 : Channel selection error                            |
350|                    -4 : Configuration selelection error                    |
351|                    -10: Any conversion started                             |
352|                    ....                                                    |
353|                    -100 : Config command error                             |
354|                    -101 : Data size error                                  |
355+----------------------------------------------------------------------------+
356*/
357
358int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
359	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
360{
361	int i_ReturnValue = insn->n;
362	unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
363	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
364	unsigned int dw_Temp = 0;
365	unsigned int dw_Configuration = 0;
366	unsigned int dw_AcquisitionCpt = 0;
367	unsigned char b_Interrupt = 0;
368
369	/*************************************/
370	/* Test if operating mode configured */
371	/*************************************/
372
373	if (devpriv->b_AiInitialisation) {
374	   /***************************/
375		/* Test the channel number */
376	   /***************************/
377
378		if (((b_Channel < devpriv->ps_BoardInfo->i_NbrAiChannel)
379				&& (devpriv->b_SingelDiff == APCI3XXX_SINGLE))
380			|| ((b_Channel < devpriv->ps_BoardInfo->
381					i_NbrAiChannelDiff)
382				&& (devpriv->b_SingelDiff == APCI3XXX_DIFF))) {
383	      /**********************************/
384			/* Test the channel configuration */
385	      /**********************************/
386
387			if (b_Configuration > 7) {
388		 /***************************/
389				/* Channel not initialised */
390		 /***************************/
391
392				i_ReturnValue = -4;
393				printk("Channel %d range %d selection error\n",
394					b_Channel, b_Configuration);
395			}
396		} else {
397	      /***************************/
398			/* Channel selection error */
399	      /***************************/
400
401			i_ReturnValue = -3;
402			printk("Channel %d selection error\n", b_Channel);
403		}
404
405	   /**************************/
406		/* Test if no error occur */
407	   /**************************/
408
409		if (i_ReturnValue >= 0) {
410	      /************************/
411			/* Test the buffer size */
412	      /************************/
413
414			if ((b_Interrupt != 0) || ((b_Interrupt == 0)
415					&& (insn->n >= 1))) {
416		 /**********************************/
417				/* Test if conversion not started */
418		 /**********************************/
419
420				if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
421		    /******************/
422					/* Clear the FIFO */
423		    /******************/
424
425					writel(0x10000UL,
426						(void *)(devpriv->dw_AiBase +
427							12));
428
429		    /*******************************/
430					/* Get and save the delay mode */
431		    /*******************************/
432
433					dw_Temp =
434						readl((void *)(devpriv->
435							dw_AiBase + 4));
436					dw_Temp = dw_Temp & 0xFFFFFEF0UL;
437
438		    /***********************************/
439					/* Channel configuration selection */
440		    /***********************************/
441
442					writel(dw_Temp,
443						(void *)(devpriv->dw_AiBase +
444							4));
445
446		    /**************************/
447					/* Make the configuration */
448		    /**************************/
449
450					dw_Configuration =
451						(b_Configuration & 3) |
452						((unsigned int) (b_Configuration >> 2)
453						<< 6) | ((unsigned int) devpriv->
454						b_SingelDiff << 7);
455
456		    /***************************/
457					/* Write the configuration */
458		    /***************************/
459
460					writel(dw_Configuration,
461						(void *)(devpriv->dw_AiBase +
462							0));
463
464		    /*********************/
465					/* Channel selection */
466		    /*********************/
467
468					writel(dw_Temp | 0x100UL,
469						(void *)(devpriv->dw_AiBase +
470							4));
471					writel((unsigned int) b_Channel,
472						(void *)(devpriv->dw_AiBase +
473							0));
474
475		    /***********************/
476					/* Restaure delay mode */
477		    /***********************/
478
479					writel(dw_Temp,
480						(void *)(devpriv->dw_AiBase +
481							4));
482
483		    /***********************************/
484					/* Set the number of sequence to 1 */
485		    /***********************************/
486
487					writel(1,
488						(void *)(devpriv->dw_AiBase +
489							48));
490
491		    /***************************/
492					/* Save the interrupt flag */
493		    /***************************/
494
495					devpriv->b_EocEosInterrupt =
496						b_Interrupt;
497
498		    /*******************************/
499					/* Save the number of channels */
500		    /*******************************/
501
502					devpriv->ui_AiNbrofChannels = 1;
503
504		    /******************************/
505					/* Test if interrupt not used */
506		    /******************************/
507
508					if (b_Interrupt == 0) {
509						for (dw_AcquisitionCpt = 0;
510							dw_AcquisitionCpt <
511							insn->n;
512							dw_AcquisitionCpt++) {
513			  /************************/
514							/* Start the conversion */
515			  /************************/
516
517							writel(0x80000UL,
518								(void *)
519								(devpriv->
520									dw_AiBase
521									+ 8));
522
523			  /****************/
524							/* Wait the EOS */
525			  /****************/
526
527							do {
528								dw_Temp =
529									readl(
530									(void *)
531									(devpriv->
532										dw_AiBase
533										+
534										20));
535								dw_Temp =
536									dw_Temp
537									& 1;
538							} while (dw_Temp != 1);
539
540			  /*************************/
541							/* Read the analog value */
542			  /*************************/
543
544							data[dw_AcquisitionCpt]
545								=
546								(unsigned int)
547								readl((void
548									*)
549								(devpriv->
550									dw_AiBase
551									+ 28));
552						}
553					} else {
554		       /************************/
555						/* Start the conversion */
556		       /************************/
557
558						writel(0x180000UL,
559							(void *)(devpriv->
560								dw_AiBase + 8));
561					}
562				} else {
563		    /**************************/
564					/* Any conversion started */
565		    /**************************/
566
567					printk("Any conversion started\n");
568					i_ReturnValue = -10;
569				}
570			} else {
571		 /*******************/
572				/* Data size error */
573		 /*******************/
574
575				printk("Buffer size error\n");
576				i_ReturnValue = -101;
577			}
578		}
579	} else {
580	   /***************************/
581		/* Channel selection error */
582	   /***************************/
583
584		printk("Operating mode not configured\n");
585		i_ReturnValue = -1;
586	}
587	return i_ReturnValue;
588}
589
590/*
591+----------------------------------------------------------------------------+
592| Function name     : void v_APCI3XXX_Interrupt (int            irq,         |
593|                                                void           *d)       |
594+----------------------------------------------------------------------------+
595| Task              :Interrupt handler for APCI3XXX                          |
596|                    When interrupt occurs this gets called.                 |
597|                    First it finds which interrupt has been generated and   |
598|                    handles  corresponding interrupt                        |
599+----------------------------------------------------------------------------+
600| Input Parameters  : -                                                      |
601+----------------------------------------------------------------------------+
602| Return Value      : -                                                      |
603+----------------------------------------------------------------------------+
604*/
605
606void v_APCI3XXX_Interrupt(int irq, void *d)
607{
608	struct comedi_device *dev = d;
609	unsigned char b_CopyCpt = 0;
610	unsigned int dw_Status = 0;
611
612	/***************************/
613	/* Test if interrupt occur */
614	/***************************/
615
616	dw_Status = readl((void *)(devpriv->dw_AiBase + 16));
617	if ( (dw_Status & 0x2UL) == 0x2UL) {
618	   /***********************/
619		/* Reset the interrupt */
620	   /***********************/
621
622		writel(dw_Status, (void *)(devpriv->dw_AiBase + 16));
623
624	   /*****************************/
625		/* Test if interrupt enabled */
626	   /*****************************/
627
628		if (devpriv->b_EocEosInterrupt == 1) {
629	      /********************************/
630			/* Read all analog inputs value */
631	      /********************************/
632
633			for (b_CopyCpt = 0;
634				b_CopyCpt < devpriv->ui_AiNbrofChannels;
635				b_CopyCpt++) {
636				devpriv->ui_AiReadData[b_CopyCpt] =
637					(unsigned int) readl((void *)(devpriv->
638						dw_AiBase + 28));
639			}
640
641	      /**************************/
642			/* Set the interrupt flag */
643	      /**************************/
644
645			devpriv->b_EocEosInterrupt = 2;
646
647	      /**********************************************/
648			/* Send a signal to from kernel to user space */
649	      /**********************************************/
650
651			send_sig(SIGIO, devpriv->tsk_Current, 0);
652		}
653	}
654}
655
656/*
657+----------------------------------------------------------------------------+
658|                            ANALOG OUTPUT SUBDEVICE                         |
659+----------------------------------------------------------------------------+
660*/
661
662/*
663+----------------------------------------------------------------------------+
664| Function Name     : int   i_APCI3XXX_InsnWriteAnalogOutput                 |
665|                          (struct comedi_device    *dev,                           |
666|                           struct comedi_subdevice *s,                             |
667|                           struct comedi_insn      *insn,                          |
668|                           unsigned int         *data)                          |
669+----------------------------------------------------------------------------+
670| Task                Read 1 analog input                                    |
671+----------------------------------------------------------------------------+
672| Input Parameters  : b_Range    = CR_RANGE(insn->chanspec);                 |
673|                     b_Channel  = CR_CHAN(insn->chanspec);                  |
674|                     data[0]    = analog value;                             |
675+----------------------------------------------------------------------------+
676| Output Parameters : -                                                      |
677+----------------------------------------------------------------------------+
678| Return Value      :>0: No error                                            |
679|                    -3 : Channel selection error                            |
680|                    -4 : Configuration selelection error                    |
681|                    ....                                                    |
682|                    -101 : Data size error                                  |
683+----------------------------------------------------------------------------+
684*/
685
686int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
687	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
688{
689	unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
690	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
691	unsigned int dw_Status = 0;
692	int i_ReturnValue = insn->n;
693
694	/************************/
695	/* Test the buffer size */
696	/************************/
697
698	if (insn->n >= 1) {
699	   /***************************/
700		/* Test the channel number */
701	   /***************************/
702
703		if (b_Channel < devpriv->ps_BoardInfo->i_NbrAoChannel) {
704	      /**********************************/
705			/* Test the channel configuration */
706	      /**********************************/
707
708			if (b_Range < 2) {
709		 /***************************/
710				/* Set the range selection */
711		 /***************************/
712
713				writel(b_Range,
714					(void *)(devpriv->dw_AiBase + 96));
715
716		 /**************************************************/
717				/* Write the analog value to the selected channel */
718		 /**************************************************/
719
720				writel((data[0] << 8) | b_Channel,
721					(void *)(devpriv->dw_AiBase + 100));
722
723		 /****************************/
724				/* Wait the end of transfer */
725		 /****************************/
726
727				do {
728					dw_Status =
729						readl((void *)(devpriv->
730							dw_AiBase + 96));
731				} while ((dw_Status & 0x100) != 0x100);
732			} else {
733		 /***************************/
734				/* Channel not initialised */
735		 /***************************/
736
737				i_ReturnValue = -4;
738				printk("Channel %d range %d selection error\n",
739					b_Channel, b_Range);
740			}
741		} else {
742	      /***************************/
743			/* Channel selection error */
744	      /***************************/
745
746			i_ReturnValue = -3;
747			printk("Channel %d selection error\n", b_Channel);
748		}
749	} else {
750	   /*******************/
751		/* Data size error */
752	   /*******************/
753
754		printk("Buffer size error\n");
755		i_ReturnValue = -101;
756	}
757
758	return i_ReturnValue;
759}
760
761/*
762+----------------------------------------------------------------------------+
763|                              TTL FUNCTIONS                                 |
764+----------------------------------------------------------------------------+
765*/
766
767/*
768+----------------------------------------------------------------------------+
769| Function Name     : int   i_APCI3XXX_InsnConfigInitTTLIO                   |
770|                          (struct comedi_device    *dev,                           |
771|                           struct comedi_subdevice *s,                             |
772|                           struct comedi_insn      *insn,                          |
773|                           unsigned int         *data)                          |
774+----------------------------------------------------------------------------+
775| Task           You must calling this function be                           |
776|                for you call any other function witch access of TTL.        |
777|                APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
778+----------------------------------------------------------------------------+
779| Input Parameters  : b_InitType    = (unsigned char) data[0];                        |
780|                     b_Port2Mode   = (unsigned char) data[1];                        |
781+----------------------------------------------------------------------------+
782| Output Parameters : -                                                      |
783+----------------------------------------------------------------------------+
784| Return Value      :>0: No error                                            |
785|                    -1: Port 2 mode selection is wrong                      |
786|                    ....                                                    |
787|                    -100 : Config command error                             |
788|                    -101 : Data size error                                  |
789+----------------------------------------------------------------------------+
790*/
791
792int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
793	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
794{
795	int i_ReturnValue = insn->n;
796	unsigned char b_Command = 0;
797
798	/************************/
799	/* Test the buffer size */
800	/************************/
801
802	if (insn->n >= 1) {
803	   /*******************/
804		/* Get the command */
805		/* **************** */
806
807		b_Command = (unsigned char) data[0];
808
809	   /********************/
810		/* Test the command */
811	   /********************/
812
813		if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
814	      /***************************************/
815			/* Test the initialisation buffer size */
816	      /***************************************/
817
818			if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)
819				&& (insn->n != 2)) {
820		 /*******************/
821				/* Data size error */
822		 /*******************/
823
824				printk("Buffer size error\n");
825				i_ReturnValue = -101;
826			}
827		} else {
828	      /************************/
829			/* Config command error */
830	      /************************/
831
832			printk("Command selection error\n");
833			i_ReturnValue = -100;
834		}
835	} else {
836	   /*******************/
837		/* Data size error */
838	   /*******************/
839
840		printk("Buffer size error\n");
841		i_ReturnValue = -101;
842	}
843
844	/*********************************************************************************/
845	/* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */
846	/*********************************************************************************/
847
848	if ((i_ReturnValue >= 0)
849		&& (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) {
850	   /**********************/
851		/* Test the direction */
852	   /**********************/
853
854		if ((data[1] == 0) || (data[1] == 0xFF)) {
855	      /**************************/
856			/* Save the configuration */
857	      /**************************/
858
859			devpriv->ul_TTLPortConfiguration[0] =
860				devpriv->ul_TTLPortConfiguration[0] | data[1];
861		} else {
862	      /************************/
863			/* Port direction error */
864	      /************************/
865
866			printk("Port 2 direction selection error\n");
867			i_ReturnValue = -1;
868		}
869	}
870
871	/**************************/
872	/* Test if no error occur */
873	/**************************/
874
875	if (i_ReturnValue >= 0) {
876	   /***********************************/
877		/* Test if TTL port initilaisation */
878	   /***********************************/
879
880		if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
881	      /*************************/
882			/* Set the configuration */
883	      /*************************/
884
885			outl(data[1], devpriv->iobase + 224);
886		}
887	}
888
889	return i_ReturnValue;
890}
891
892/*
893+----------------------------------------------------------------------------+
894|                        TTL INPUT FUNCTIONS                                 |
895+----------------------------------------------------------------------------+
896*/
897
898/*
899+----------------------------------------------------------------------------+
900| Function Name     : int     i_APCI3XXX_InsnBitsTTLIO                       |
901|                          (struct comedi_device    *dev,                           |
902|                           struct comedi_subdevice *s,                             |
903|                           struct comedi_insn      *insn,                          |
904|                           unsigned int         *data)                          |
905+----------------------------------------------------------------------------+
906| Task              : Write the selected output mask and read the status from|
907|                     all TTL channles                                       |
908+----------------------------------------------------------------------------+
909| Input Parameters  : dw_ChannelMask = data [0];                             |
910|                     dw_BitMask     = data [1];                             |
911+----------------------------------------------------------------------------+
912| Output Parameters : data[1] : All TTL channles states                      |
913+----------------------------------------------------------------------------+
914| Return Value      : >0  : No error                                         |
915|                    -4   : Channel mask error                               |
916|                    -101 : Data size error                                  |
917+----------------------------------------------------------------------------+
918*/
919
920int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
921	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
922{
923	int i_ReturnValue = insn->n;
924	unsigned char b_ChannelCpt = 0;
925	unsigned int dw_ChannelMask = 0;
926	unsigned int dw_BitMask = 0;
927	unsigned int dw_Status = 0;
928
929	/************************/
930	/* Test the buffer size */
931	/************************/
932
933	if (insn->n >= 2) {
934	   /*******************************/
935		/* Get the channe and bit mask */
936	   /*******************************/
937
938		dw_ChannelMask = data[0];
939		dw_BitMask = data[1];
940
941	   /*************************/
942		/* Test the channel mask */
943	   /*************************/
944
945		if (((dw_ChannelMask & 0XFF00FF00) == 0) &&
946			(((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF)
947				|| (((devpriv->ul_TTLPortConfiguration[0] &
948							0xFF) == 0)
949					&& ((dw_ChannelMask & 0XFF0000) ==
950						0)))) {
951	      /*********************************/
952			/* Test if set/reset any channel */
953	      /*********************************/
954
955			if (dw_ChannelMask) {
956		 /****************************************/
957				/* Test if set/rest any port 0 channels */
958		 /****************************************/
959
960				if (dw_ChannelMask & 0xFF) {
961		    /*******************************************/
962					/* Read port 0 (first digital output port) */
963		    /*******************************************/
964
965					dw_Status = inl(devpriv->iobase + 80);
966
967					for (b_ChannelCpt = 0; b_ChannelCpt < 8;
968						b_ChannelCpt++) {
969						if ((dw_ChannelMask >>
970								b_ChannelCpt) &
971							1) {
972							dw_Status =
973								(dw_Status &
974								(0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
975						}
976					}
977
978					outl(dw_Status, devpriv->iobase + 80);
979				}
980
981		 /****************************************/
982				/* Test if set/rest any port 2 channels */
983		 /****************************************/
984
985				if (dw_ChannelMask & 0xFF0000) {
986					dw_BitMask = dw_BitMask >> 16;
987					dw_ChannelMask = dw_ChannelMask >> 16;
988
989		    /********************************************/
990					/* Read port 2 (second digital output port) */
991		    /********************************************/
992
993					dw_Status = inl(devpriv->iobase + 112);
994
995					for (b_ChannelCpt = 0; b_ChannelCpt < 8;
996						b_ChannelCpt++) {
997						if ((dw_ChannelMask >>
998								b_ChannelCpt) &
999							1) {
1000							dw_Status =
1001								(dw_Status &
1002								(0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
1003						}
1004					}
1005
1006					outl(dw_Status, devpriv->iobase + 112);
1007				}
1008			}
1009
1010	      /*******************************************/
1011			/* Read port 0 (first digital output port) */
1012	      /*******************************************/
1013
1014			data[1] = inl(devpriv->iobase + 80);
1015
1016	      /******************************************/
1017			/* Read port 1 (first digital input port) */
1018	      /******************************************/
1019
1020			data[1] = data[1] | (inl(devpriv->iobase + 64) << 8);
1021
1022	      /************************/
1023			/* Test if port 2 input */
1024	      /************************/
1025
1026			if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) {
1027				data[1] =
1028					data[1] | (inl(devpriv->iobase +
1029						96) << 16);
1030			} else {
1031				data[1] =
1032					data[1] | (inl(devpriv->iobase +
1033						112) << 16);
1034			}
1035		} else {
1036	      /************************/
1037			/* Config command error */
1038	      /************************/
1039
1040			printk("Channel mask error\n");
1041			i_ReturnValue = -4;
1042		}
1043	} else {
1044	   /*******************/
1045		/* Data size error */
1046	   /*******************/
1047
1048		printk("Buffer size error\n");
1049		i_ReturnValue = -101;
1050	}
1051
1052	return i_ReturnValue;
1053}
1054
1055/*
1056+----------------------------------------------------------------------------+
1057| Function Name     : int i_APCI3XXX_InsnReadTTLIO                           |
1058|                          (struct comedi_device    *dev,                           |
1059|                           struct comedi_subdevice *s,                             |
1060|                           struct comedi_insn      *insn,                          |
1061|                           unsigned int         *data)                          |
1062+----------------------------------------------------------------------------+
1063| Task              : Read the status from selected channel                  |
1064+----------------------------------------------------------------------------+
1065| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1066+----------------------------------------------------------------------------+
1067| Output Parameters : data[0] : Selected TTL channel state                   |
1068+----------------------------------------------------------------------------+
1069| Return Value      : 0   : No error                                         |
1070|                    -3   : Channel selection error                          |
1071|                    -101 : Data size error                                  |
1072+----------------------------------------------------------------------------+
1073*/
1074
1075int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
1076	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1077{
1078	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1079	int i_ReturnValue = insn->n;
1080	unsigned int *pls_ReadData = data;
1081
1082	/************************/
1083	/* Test the buffer size */
1084	/************************/
1085
1086	if (insn->n >= 1) {
1087	   /***********************/
1088		/* Test if read port 0 */
1089	   /***********************/
1090
1091		if (b_Channel < 8) {
1092	      /*******************************************/
1093			/* Read port 0 (first digital output port) */
1094	      /*******************************************/
1095
1096			pls_ReadData[0] = inl(devpriv->iobase + 80);
1097			pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1;
1098		} else {
1099	      /***********************/
1100			/* Test if read port 1 */
1101	      /***********************/
1102
1103			if ((b_Channel > 7) && (b_Channel < 16)) {
1104		 /******************************************/
1105				/* Read port 1 (first digital input port) */
1106		 /******************************************/
1107
1108				pls_ReadData[0] = inl(devpriv->iobase + 64);
1109				pls_ReadData[0] =
1110					(pls_ReadData[0] >> (b_Channel -
1111						8)) & 1;
1112			} else {
1113		 /***********************/
1114				/* Test if read port 2 */
1115		 /***********************/
1116
1117				if ((b_Channel > 15) && (b_Channel < 24)) {
1118		    /************************/
1119					/* Test if port 2 input */
1120		    /************************/
1121
1122					if ((devpriv->ul_TTLPortConfiguration[0]
1123							& 0xFF) == 0) {
1124						pls_ReadData[0] =
1125							inl(devpriv->iobase +
1126							96);
1127						pls_ReadData[0] =
1128							(pls_ReadData[0] >>
1129							(b_Channel - 16)) & 1;
1130					} else {
1131						pls_ReadData[0] =
1132							inl(devpriv->iobase +
1133							112);
1134						pls_ReadData[0] =
1135							(pls_ReadData[0] >>
1136							(b_Channel - 16)) & 1;
1137					}
1138				} else {
1139		    /***************************/
1140					/* Channel selection error */
1141		    /***************************/
1142
1143					i_ReturnValue = -3;
1144					printk("Channel %d selection error\n",
1145						b_Channel);
1146				}
1147			}
1148		}
1149	} else {
1150	   /*******************/
1151		/* Data size error */
1152	   /*******************/
1153
1154		printk("Buffer size error\n");
1155		i_ReturnValue = -101;
1156	}
1157
1158	return i_ReturnValue;
1159}
1160
1161/*
1162+----------------------------------------------------------------------------+
1163|                        TTL OUTPUT FUNCTIONS                                |
1164+----------------------------------------------------------------------------+
1165*/
1166
1167/*
1168+----------------------------------------------------------------------------+
1169| Function Name     : int     i_APCI3XXX_InsnWriteTTLIO                      |
1170|                          (struct comedi_device    *dev,                           |
1171|                           struct comedi_subdevice *s,                             |
1172|                           struct comedi_insn      *insn,                          |
1173|                           unsigned int         *data)                          |
1174+----------------------------------------------------------------------------+
1175| Task              : Set the state from TTL output channel                  |
1176+----------------------------------------------------------------------------+
1177| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1178|                     b_State   = data [0]                                   |
1179+----------------------------------------------------------------------------+
1180| Output Parameters : -                                                      |
1181+----------------------------------------------------------------------------+
1182| Return Value      : 0   : No error                                         |
1183|                    -3   : Channel selection error                          |
1184|                    -101 : Data size error                                  |
1185+----------------------------------------------------------------------------+
1186*/
1187
1188int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
1189	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1190{
1191	int i_ReturnValue = insn->n;
1192	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1193	unsigned char b_State = 0;
1194	unsigned int dw_Status = 0;
1195
1196	/************************/
1197	/* Test the buffer size */
1198	/************************/
1199
1200	if (insn->n >= 1) {
1201		b_State = (unsigned char) data[0];
1202
1203	   /***********************/
1204		/* Test if read port 0 */
1205	   /***********************/
1206
1207		if (b_Channel < 8) {
1208	      /*****************************************************************************/
1209			/* Read port 0 (first digital output port) and set/reset the selcted channel */
1210	      /*****************************************************************************/
1211
1212			dw_Status = inl(devpriv->iobase + 80);
1213			dw_Status =
1214				(dw_Status & (0xFF -
1215					(1 << b_Channel))) | ((b_State & 1) <<
1216				b_Channel);
1217			outl(dw_Status, devpriv->iobase + 80);
1218		} else {
1219	      /***********************/
1220			/* Test if read port 2 */
1221	      /***********************/
1222
1223			if ((b_Channel > 15) && (b_Channel < 24)) {
1224		 /*************************/
1225				/* Test if port 2 output */
1226		 /*************************/
1227
1228				if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
1229					== 0xFF) {
1230		    /*****************************************************************************/
1231					/* Read port 2 (first digital output port) and set/reset the selcted channel */
1232		    /*****************************************************************************/
1233
1234					dw_Status = inl(devpriv->iobase + 112);
1235					dw_Status =
1236						(dw_Status & (0xFF -
1237							(1 << (b_Channel -
1238									16)))) |
1239						((b_State & 1) << (b_Channel -
1240							16));
1241					outl(dw_Status, devpriv->iobase + 112);
1242				} else {
1243		    /***************************/
1244					/* Channel selection error */
1245		    /***************************/
1246
1247					i_ReturnValue = -3;
1248					printk("Channel %d selection error\n",
1249						b_Channel);
1250				}
1251			} else {
1252		 /***************************/
1253				/* Channel selection error */
1254		 /***************************/
1255
1256				i_ReturnValue = -3;
1257				printk("Channel %d selection error\n",
1258					b_Channel);
1259			}
1260		}
1261	} else {
1262	   /*******************/
1263		/* Data size error */
1264	   /*******************/
1265
1266		printk("Buffer size error\n");
1267		i_ReturnValue = -101;
1268	}
1269
1270	return i_ReturnValue;
1271}
1272
1273/*
1274+----------------------------------------------------------------------------+
1275|                           DIGITAL INPUT SUBDEVICE                          |
1276+----------------------------------------------------------------------------+
1277*/
1278
1279/*
1280+----------------------------------------------------------------------------+
1281| Function name     :int i_APCI3XXX_InsnReadDigitalInput                     |
1282|                                          (struct comedi_device *dev,              |
1283|                                           struct comedi_subdevice *s,             |
1284|                                           struct comedi_insn *insn,               |
1285|                                           unsigned int *data)                  |
1286+----------------------------------------------------------------------------+
1287| Task              : Reads the value of the specified Digital input channel |
1288+----------------------------------------------------------------------------+
1289| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec) (0 to 3)           |
1290+----------------------------------------------------------------------------+
1291| Output Parameters : data[0] : Channel value                                |
1292+----------------------------------------------------------------------------+
1293| Return Value      : 0   : No error                                         |
1294|                    -3   : Channel selection error                          |
1295|                    -101 : Data size error                                  |
1296+----------------------------------------------------------------------------+
1297*/
1298
1299int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
1300	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1301{
1302	int i_ReturnValue = insn->n;
1303	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
1304	unsigned int dw_Temp = 0;
1305
1306	/***************************/
1307	/* Test the channel number */
1308	/***************************/
1309
1310	if (b_Channel <= devpriv->ps_BoardInfo->i_NbrDiChannel) {
1311	   /************************/
1312		/* Test the buffer size */
1313	   /************************/
1314
1315		if (insn->n >= 1) {
1316			dw_Temp = inl(devpriv->iobase + 32);
1317			*data = (dw_Temp >> b_Channel) & 1;
1318		} else {
1319	      /*******************/
1320			/* Data size error */
1321	      /*******************/
1322
1323			printk("Buffer size error\n");
1324			i_ReturnValue = -101;
1325		}
1326	} else {
1327	   /***************************/
1328		/* Channel selection error */
1329	   /***************************/
1330
1331		printk("Channel selection error\n");
1332		i_ReturnValue = -3;
1333	}
1334
1335	return i_ReturnValue;
1336}
1337
1338/*
1339+----------------------------------------------------------------------------+
1340| Function name     :int i_APCI3XXX_InsnBitsDigitalInput                     |
1341|                                          (struct comedi_device *dev,              |
1342|                                           struct comedi_subdevice *s,             |
1343|                                           struct comedi_insn *insn,               |
1344|                                           unsigned int *data)                  |
1345+----------------------------------------------------------------------------+
1346| Task              : Reads the value of the Digital input Port i.e.4channels|
1347+----------------------------------------------------------------------------+
1348| Input Parameters  : -                                                      |
1349+----------------------------------------------------------------------------+
1350| Output Parameters : data[0] : Port value                                   |
1351+----------------------------------------------------------------------------+
1352| Return Value      :>0: No error                                            |
1353|                    ....                                                    |
1354|                    -101 : Data size error                                  |
1355+----------------------------------------------------------------------------+
1356*/
1357int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
1358	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1359{
1360	int i_ReturnValue = insn->n;
1361	unsigned int dw_Temp = 0;
1362
1363	/************************/
1364	/* Test the buffer size */
1365	/************************/
1366
1367	if (insn->n >= 1) {
1368		dw_Temp = inl(devpriv->iobase + 32);
1369		*data = dw_Temp & 0xf;
1370	} else {
1371	   /*******************/
1372		/* Data size error */
1373	   /*******************/
1374
1375		printk("Buffer size error\n");
1376		i_ReturnValue = -101;
1377	}
1378
1379	return i_ReturnValue;
1380}
1381
1382/*
1383+----------------------------------------------------------------------------+
1384|                           DIGITAL OUTPUT SUBDEVICE                         |
1385+----------------------------------------------------------------------------+
1386
1387*/
1388
1389/*
1390+----------------------------------------------------------------------------+
1391| Function name     :int i_APCI3XXX_InsnBitsDigitalOutput                    |
1392|                                          (struct comedi_device *dev,              |
1393|                                           struct comedi_subdevice *s,             |
1394|                                           struct comedi_insn *insn,               |
1395|                                           unsigned int *data)                  |
1396+----------------------------------------------------------------------------+
1397| Task              : Write the selected output mask and read the status from|
1398|                     all digital output channles                            |
1399+----------------------------------------------------------------------------+
1400| Input Parameters  : dw_ChannelMask = data [0];                             |
1401|                     dw_BitMask     = data [1];                             |
1402+----------------------------------------------------------------------------+
1403| Output Parameters : data[1] : All digital output channles states           |
1404+----------------------------------------------------------------------------+
1405| Return Value      : >0  : No error                                         |
1406|                    -4   : Channel mask error                               |
1407|                    -101 : Data size error                                  |
1408+----------------------------------------------------------------------------+
1409*/
1410int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
1411	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1412{
1413	int i_ReturnValue = insn->n;
1414	unsigned char b_ChannelCpt = 0;
1415	unsigned int dw_ChannelMask = 0;
1416	unsigned int dw_BitMask = 0;
1417	unsigned int dw_Status = 0;
1418
1419	/************************/
1420	/* Test the buffer size */
1421	/************************/
1422
1423	if (insn->n >= 2) {
1424	   /*******************************/
1425		/* Get the channe and bit mask */
1426	   /*******************************/
1427
1428		dw_ChannelMask = data[0];
1429		dw_BitMask = data[1];
1430
1431	   /*************************/
1432		/* Test the channel mask */
1433	   /*************************/
1434
1435		if ((dw_ChannelMask & 0XFFFFFFF0) == 0) {
1436	      /*********************************/
1437			/* Test if set/reset any channel */
1438	      /*********************************/
1439
1440			if (dw_ChannelMask & 0xF) {
1441		 /********************************/
1442				/* Read the digital output port */
1443		 /********************************/
1444
1445				dw_Status = inl(devpriv->iobase + 48);
1446
1447				for (b_ChannelCpt = 0; b_ChannelCpt < 4;
1448					b_ChannelCpt++) {
1449					if ((dw_ChannelMask >> b_ChannelCpt) &
1450						1) {
1451						dw_Status =
1452							(dw_Status & (0xF -
1453								(1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
1454					}
1455				}
1456
1457				outl(dw_Status, devpriv->iobase + 48);
1458			}
1459
1460	      /********************************/
1461			/* Read the digital output port */
1462	      /********************************/
1463
1464			data[1] = inl(devpriv->iobase + 48);
1465		} else {
1466	      /************************/
1467			/* Config command error */
1468	      /************************/
1469
1470			printk("Channel mask error\n");
1471			i_ReturnValue = -4;
1472		}
1473	} else {
1474	   /*******************/
1475		/* Data size error */
1476	   /*******************/
1477
1478		printk("Buffer size error\n");
1479		i_ReturnValue = -101;
1480	}
1481
1482	return i_ReturnValue;
1483}
1484
1485/*
1486+----------------------------------------------------------------------------+
1487| Function name     :int i_APCI3XXX_InsnWriteDigitalOutput                   |
1488|                                          (struct comedi_device *dev,              |
1489|                                           struct comedi_subdevice *s,             |
1490|                                           struct comedi_insn *insn,               |
1491|                                           unsigned int *data)                  |
1492+----------------------------------------------------------------------------+
1493| Task              : Set the state from digital output channel              |
1494+----------------------------------------------------------------------------+
1495| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1496|                     b_State   = data [0]                                   |
1497+----------------------------------------------------------------------------+
1498| Output Parameters : -                                                      |
1499+----------------------------------------------------------------------------+
1500| Return Value      : >0  : No error                                         |
1501|                    -3   : Channel selection error                          |
1502|                    -101 : Data size error                                  |
1503+----------------------------------------------------------------------------+
1504*/
1505
1506int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
1507	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1508{
1509	int i_ReturnValue = insn->n;
1510	unsigned char b_Channel = CR_CHAN(insn->chanspec);
1511	unsigned char b_State = 0;
1512	unsigned int dw_Status = 0;
1513
1514	/************************/
1515	/* Test the buffer size */
1516	/************************/
1517
1518	if (insn->n >= 1) {
1519	   /***************************/
1520		/* Test the channel number */
1521	   /***************************/
1522
1523		if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
1524	      /*******************/
1525			/* Get the command */
1526	      /*******************/
1527
1528			b_State = (unsigned char) data[0];
1529
1530	      /********************************/
1531			/* Read the digital output port */
1532	      /********************************/
1533
1534			dw_Status = inl(devpriv->iobase + 48);
1535
1536			dw_Status =
1537				(dw_Status & (0xF -
1538					(1 << b_Channel))) | ((b_State & 1) <<
1539				b_Channel);
1540			outl(dw_Status, devpriv->iobase + 48);
1541		} else {
1542	      /***************************/
1543			/* Channel selection error */
1544	      /***************************/
1545
1546			printk("Channel selection error\n");
1547			i_ReturnValue = -3;
1548		}
1549	} else {
1550	   /*******************/
1551		/* Data size error */
1552	   /*******************/
1553
1554		printk("Buffer size error\n");
1555		i_ReturnValue = -101;
1556	}
1557
1558	return i_ReturnValue;
1559}
1560
1561/*
1562+----------------------------------------------------------------------------+
1563| Function name     :int i_APCI3XXX_InsnReadDigitalOutput                    |
1564|                                          (struct comedi_device *dev,              |
1565|                                           struct comedi_subdevice *s,             |
1566|                                           struct comedi_insn *insn,               |
1567|                                           unsigned int *data)                  |
1568+----------------------------------------------------------------------------+
1569| Task              : Read the state from digital output channel             |
1570+----------------------------------------------------------------------------+
1571| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1572+----------------------------------------------------------------------------+
1573| Output Parameters : b_State   = data [0]                                   |
1574+----------------------------------------------------------------------------+
1575| Return Value      : >0  : No error                                         |
1576|                    -3   : Channel selection error                          |
1577|                    -101 : Data size error                                  |
1578+----------------------------------------------------------------------------+
1579*/
1580
1581int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
1582	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1583{
1584	int i_ReturnValue = insn->n;
1585	unsigned char b_Channel = CR_CHAN(insn->chanspec);
1586	unsigned int dw_Status = 0;
1587
1588	/************************/
1589	/* Test the buffer size */
1590	/************************/
1591
1592	if (insn->n >= 1) {
1593	   /***************************/
1594		/* Test the channel number */
1595	   /***************************/
1596
1597		if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
1598	      /********************************/
1599			/* Read the digital output port */
1600	      /********************************/
1601
1602			dw_Status = inl(devpriv->iobase + 48);
1603
1604			dw_Status = (dw_Status >> b_Channel) & 1;
1605			*data = dw_Status;
1606		} else {
1607	      /***************************/
1608			/* Channel selection error */
1609	      /***************************/
1610
1611			printk("Channel selection error\n");
1612			i_ReturnValue = -3;
1613		}
1614	} else {
1615	   /*******************/
1616		/* Data size error */
1617	   /*******************/
1618
1619		printk("Buffer size error\n");
1620		i_ReturnValue = -101;
1621	}
1622
1623	return i_ReturnValue;
1624}
1625
1626/*
1627+----------------------------------------------------------------------------+
1628| Function   Name   : int i_APCI3XXX_Reset(struct comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
1629| Task              :resets all the registers                                |
1630+----------------------------------------------------------------------------+
1631| Input Parameters  : struct comedi_device *dev                                     |
1632+----------------------------------------------------------------------------+
1633| Output Parameters : -                                                      |
1634+----------------------------------------------------------------------------+
1635| Return Value      : -                                                      |
1636+----------------------------------------------------------------------------+
1637*/
1638
1639int i_APCI3XXX_Reset(struct comedi_device *dev)
1640{
1641	unsigned char b_Cpt = 0;
1642
1643	/*************************/
1644	/* Disable the interrupt */
1645	/*************************/
1646
1647	disable_irq(dev->irq);
1648
1649	/****************************/
1650	/* Reset the interrupt flag */
1651	/****************************/
1652
1653	devpriv->b_EocEosInterrupt = 0;
1654
1655	/***************************/
1656	/* Clear the start command */
1657	/***************************/
1658
1659	writel(0, (void *)(devpriv->dw_AiBase + 8));
1660
1661	/*****************************/
1662	/* Reset the interrupt flags */
1663	/*****************************/
1664
1665	writel(readl((void *)(devpriv->dw_AiBase + 16)),
1666		(void *)(devpriv->dw_AiBase + 16));
1667
1668	/*****************/
1669	/* clear the EOS */
1670	/*****************/
1671
1672	readl((void *)(devpriv->dw_AiBase + 20));
1673
1674	/******************/
1675	/* Clear the FIFO */
1676	/******************/
1677
1678	for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
1679		readl((void *)(devpriv->dw_AiBase + 28));
1680	}
1681
1682	/************************/
1683	/* Enable the interrupt */
1684	/************************/
1685
1686	enable_irq(dev->irq);
1687
1688	return 0;
1689}
1690