hwdrv_apci3xxx.c revision 90035c0886b256d75bced13b3b3cea5234aff136
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  | (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  = (BYTE)  data[1];                       |
91|                     b_TimeBase    = (BYTE)  data[2]; (0: ns, 1:micros 2:ms)|
92|                    dw_ReloadValue = (DWORD) 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	BYTE b_TimeBase = 0;
113	BYTE b_SingleDiff = 0;
114	DWORD dw_ReloadValue = 0;
115	DWORD 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 = (BYTE) data[1];
127
128	   /****************************/
129		/* Get the time base unitiy */
130	   /****************************/
131
132		b_TimeBase = (BYTE) data[2];
133
134	   /*************************************/
135		/* Get the convert time reload value */
136	   /*************************************/
137
138		dw_ReloadValue = (DWORD) 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 >= 0) && (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									(UINT)
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((DWORD)
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 = (BYTE)  data[0];                       |
285|                     b_TimeBase    = (BYTE)  data[1]; (0: ns, 1:micros 2:ms)|
286|                    dw_ReloadValue = (DWORD) 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 ((BYTE) 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	BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec);
363	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
364	DWORD dw_Temp = 0;
365	DWORD dw_Configuration = 0;
366	DWORD dw_AcquisitionCpt = 0;
367	BYTE 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						((DWORD) (b_Configuration >> 2)
453						<< 6) | ((DWORD) 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((DWORD) 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							}
539							while (dw_Temp != 1);
540
541			  /*************************/
542							/* Read the analog value */
543			  /*************************/
544
545							data[dw_AcquisitionCpt]
546								=
547								(unsigned int)
548								readl((void
549									*)
550								(devpriv->
551									dw_AiBase
552									+ 28));
553						}
554					} else {
555		       /************************/
556						/* Start the conversion */
557		       /************************/
558
559						writel(0x180000UL,
560							(void *)(devpriv->
561								dw_AiBase + 8));
562					}
563				} else {
564		    /**************************/
565					/* Any conversion started */
566		    /**************************/
567
568					printk("Any conversion started\n");
569					i_ReturnValue = -10;
570				}
571			} else {
572		 /*******************/
573				/* Data size error */
574		 /*******************/
575
576				printk("Buffer size error\n");
577				i_ReturnValue = -101;
578			}
579		}
580	} else {
581	   /***************************/
582		/* Channel selection error */
583	   /***************************/
584
585		printk("Operating mode not configured\n");
586		i_ReturnValue = -1;
587	}
588	return (i_ReturnValue);
589}
590
591/*
592+----------------------------------------------------------------------------+
593| Function name     : void v_APCI3XXX_Interrupt (int            irq,         |
594|                                                void           *d)       |
595+----------------------------------------------------------------------------+
596| Task              :Interrupt handler for APCI3XXX                          |
597|                    When interrupt occurs this gets called.                 |
598|                    First it finds which interrupt has been generated and   |
599|                    handles  corresponding interrupt                        |
600+----------------------------------------------------------------------------+
601| Input Parameters  : -                                                      |
602+----------------------------------------------------------------------------+
603| Return Value      : -                                                      |
604+----------------------------------------------------------------------------+
605*/
606
607void v_APCI3XXX_Interrupt(int irq, void *d)
608{
609	struct comedi_device *dev = d;
610	BYTE b_CopyCpt = 0;
611	DWORD dw_Status = 0;
612
613	/***************************/
614	/* Test if interrupt occur */
615	/***************************/
616
617	if (((dw_Status = readl((void *)(devpriv->dw_AiBase + 16))) & 0x2UL) ==
618		0x2UL) {
619	   /***********************/
620		/* Reset the interrupt */
621	   /***********************/
622
623		writel(dw_Status, (void *)(devpriv->dw_AiBase + 16));
624
625	   /*****************************/
626		/* Test if interrupt enabled */
627	   /*****************************/
628
629		if (devpriv->b_EocEosInterrupt == 1) {
630	      /********************************/
631			/* Read all analog inputs value */
632	      /********************************/
633
634			for (b_CopyCpt = 0;
635				b_CopyCpt < devpriv->ui_AiNbrofChannels;
636				b_CopyCpt++) {
637				devpriv->ui_AiReadData[b_CopyCpt] =
638					(UINT) readl((void *)(devpriv->
639						dw_AiBase + 28));
640			}
641
642	      /**************************/
643			/* Set the interrupt flag */
644	      /**************************/
645
646			devpriv->b_EocEosInterrupt = 2;
647
648	      /**********************************************/
649			/* Send a signal to from kernel to user space */
650	      /**********************************************/
651
652			send_sig(SIGIO, devpriv->tsk_Current, 0);
653		}
654	}
655}
656
657/*
658+----------------------------------------------------------------------------+
659|                            ANALOG OUTPUT SUBDEVICE                         |
660+----------------------------------------------------------------------------+
661*/
662
663/*
664+----------------------------------------------------------------------------+
665| Function Name     : INT   i_APCI3XXX_InsnWriteAnalogOutput                 |
666|                          (struct comedi_device    *dev,                           |
667|                           struct comedi_subdevice *s,                             |
668|                           struct comedi_insn      *insn,                          |
669|                           unsigned int         *data)                          |
670+----------------------------------------------------------------------------+
671| Task                Read 1 analog input                                    |
672+----------------------------------------------------------------------------+
673| Input Parameters  : b_Range    = CR_RANGE(insn->chanspec);                 |
674|                     b_Channel  = CR_CHAN(insn->chanspec);                  |
675|                     data[0]    = analog value;                             |
676+----------------------------------------------------------------------------+
677| Output Parameters : -                                                      |
678+----------------------------------------------------------------------------+
679| Return Value      :>0: No error                                            |
680|                    -3 : Channel selection error                            |
681|                    -4 : Configuration selelection error                    |
682|                    ....                                                    |
683|                    -101 : Data size error                                  |
684+----------------------------------------------------------------------------+
685*/
686
687int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
688	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
689{
690	BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
691	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
692	DWORD dw_Status = 0;
693	INT i_ReturnValue = insn->n;
694
695	/************************/
696	/* Test the buffer size */
697	/************************/
698
699	if (insn->n >= 1) {
700	   /***************************/
701		/* Test the channel number */
702	   /***************************/
703
704		if (b_Channel < devpriv->ps_BoardInfo->i_NbrAoChannel) {
705	      /**********************************/
706			/* Test the channel configuration */
707	      /**********************************/
708
709			if (b_Range < 2) {
710		 /***************************/
711				/* Set the range selection */
712		 /***************************/
713
714				writel(b_Range,
715					(void *)(devpriv->dw_AiBase + 96));
716
717		 /**************************************************/
718				/* Write the analog value to the selected channel */
719		 /**************************************************/
720
721				writel((data[0] << 8) | b_Channel,
722					(void *)(devpriv->dw_AiBase + 100));
723
724		 /****************************/
725				/* Wait the end of transfer */
726		 /****************************/
727
728				do {
729					dw_Status =
730						readl((void *)(devpriv->
731							dw_AiBase + 96));
732				}
733				while ((dw_Status & 0x100) != 0x100);
734			} else {
735		 /***************************/
736				/* Channel not initialised */
737		 /***************************/
738
739				i_ReturnValue = -4;
740				printk("Channel %d range %d selection error\n",
741					b_Channel, b_Range);
742			}
743		} else {
744	      /***************************/
745			/* Channel selection error */
746	      /***************************/
747
748			i_ReturnValue = -3;
749			printk("Channel %d selection error\n", b_Channel);
750		}
751	} else {
752	   /*******************/
753		/* Data size error */
754	   /*******************/
755
756		printk("Buffer size error\n");
757		i_ReturnValue = -101;
758	}
759
760	return (i_ReturnValue);
761}
762
763/*
764+----------------------------------------------------------------------------+
765|                              TTL FUNCTIONS                                 |
766+----------------------------------------------------------------------------+
767*/
768
769/*
770+----------------------------------------------------------------------------+
771| Function Name     : INT   i_APCI3XXX_InsnConfigInitTTLIO                   |
772|                          (struct comedi_device    *dev,                           |
773|                           struct comedi_subdevice *s,                             |
774|                           struct comedi_insn      *insn,                          |
775|                           unsigned int         *data)                          |
776+----------------------------------------------------------------------------+
777| Task           You must calling this function be                           |
778|                for you call any other function witch access of TTL.        |
779|                APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
780+----------------------------------------------------------------------------+
781| Input Parameters  : b_InitType    = (BYTE) data[0];                        |
782|                     b_Port2Mode   = (BYTE) data[1];                        |
783+----------------------------------------------------------------------------+
784| Output Parameters : -                                                      |
785+----------------------------------------------------------------------------+
786| Return Value      :>0: No error                                            |
787|                    -1: Port 2 mode selection is wrong                      |
788|                    ....                                                    |
789|                    -100 : Config command error                             |
790|                    -101 : Data size error                                  |
791+----------------------------------------------------------------------------+
792*/
793
794int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
795	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
796{
797	INT i_ReturnValue = insn->n;
798	BYTE b_Command = 0;
799
800	/************************/
801	/* Test the buffer size */
802	/************************/
803
804	if (insn->n >= 1) {
805	   /*******************/
806		/* Get the command */
807		/* **************** */
808
809		b_Command = (BYTE) data[0];
810
811	   /********************/
812		/* Test the command */
813	   /********************/
814
815		if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
816	      /***************************************/
817			/* Test the initialisation buffer size */
818	      /***************************************/
819
820			if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)
821				&& (insn->n != 2)) {
822		 /*******************/
823				/* Data size error */
824		 /*******************/
825
826				printk("Buffer size error\n");
827				i_ReturnValue = -101;
828			}
829		} else {
830	      /************************/
831			/* Config command error */
832	      /************************/
833
834			printk("Command selection error\n");
835			i_ReturnValue = -100;
836		}
837	} else {
838	   /*******************/
839		/* Data size error */
840	   /*******************/
841
842		printk("Buffer size error\n");
843		i_ReturnValue = -101;
844	}
845
846	/*********************************************************************************/
847	/* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */
848	/*********************************************************************************/
849
850	if ((i_ReturnValue >= 0)
851		&& (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) {
852	   /**********************/
853		/* Test the direction */
854	   /**********************/
855
856		if ((data[1] == 0) || (data[1] == 0xFF)) {
857	      /**************************/
858			/* Save the configuration */
859	      /**************************/
860
861			devpriv->ul_TTLPortConfiguration[0] =
862				devpriv->ul_TTLPortConfiguration[0] | data[1];
863		} else {
864	      /************************/
865			/* Port direction error */
866	      /************************/
867
868			printk("Port 2 direction selection error\n");
869			i_ReturnValue = -1;
870		}
871	}
872
873	/**************************/
874	/* Test if no error occur */
875	/**************************/
876
877	if (i_ReturnValue >= 0) {
878	   /***********************************/
879		/* Test if TTL port initilaisation */
880	   /***********************************/
881
882		if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
883	      /*************************/
884			/* Set the configuration */
885	      /*************************/
886
887			outl(data[1], devpriv->iobase + 224);
888		}
889	}
890
891	return (i_ReturnValue);
892}
893
894/*
895+----------------------------------------------------------------------------+
896|                        TTL INPUT FUNCTIONS                                 |
897+----------------------------------------------------------------------------+
898*/
899
900/*
901+----------------------------------------------------------------------------+
902| Function Name     : INT     i_APCI3XXX_InsnBitsTTLIO                       |
903|                          (struct comedi_device    *dev,                           |
904|                           struct comedi_subdevice *s,                             |
905|                           struct comedi_insn      *insn,                          |
906|                           unsigned int         *data)                          |
907+----------------------------------------------------------------------------+
908| Task              : Write the selected output mask and read the status from|
909|                     all TTL channles                                       |
910+----------------------------------------------------------------------------+
911| Input Parameters  : dw_ChannelMask = data [0];                             |
912|                     dw_BitMask     = data [1];                             |
913+----------------------------------------------------------------------------+
914| Output Parameters : data[1] : All TTL channles states                      |
915+----------------------------------------------------------------------------+
916| Return Value      : >0  : No error                                         |
917|                    -4   : Channel mask error                               |
918|                    -101 : Data size error                                  |
919+----------------------------------------------------------------------------+
920*/
921
922int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
923	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
924{
925	INT i_ReturnValue = insn->n;
926	BYTE b_ChannelCpt = 0;
927	DWORD dw_ChannelMask = 0;
928	DWORD dw_BitMask = 0;
929	DWORD dw_Status = 0;
930
931	/************************/
932	/* Test the buffer size */
933	/************************/
934
935	if (insn->n >= 2) {
936	   /*******************************/
937		/* Get the channe and bit mask */
938	   /*******************************/
939
940		dw_ChannelMask = data[0];
941		dw_BitMask = data[1];
942
943	   /*************************/
944		/* Test the channel mask */
945	   /*************************/
946
947		if (((dw_ChannelMask & 0XFF00FF00) == 0) &&
948			(((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF)
949				|| (((devpriv->ul_TTLPortConfiguration[0] &
950							0xFF) == 0)
951					&& ((dw_ChannelMask & 0XFF0000) ==
952						0)))) {
953	      /*********************************/
954			/* Test if set/reset any channel */
955	      /*********************************/
956
957			if (dw_ChannelMask) {
958		 /****************************************/
959				/* Test if set/rest any port 0 channels */
960		 /****************************************/
961
962				if (dw_ChannelMask & 0xFF) {
963		    /*******************************************/
964					/* Read port 0 (first digital output port) */
965		    /*******************************************/
966
967					dw_Status = inl(devpriv->iobase + 80);
968
969					for (b_ChannelCpt = 0; b_ChannelCpt < 8;
970						b_ChannelCpt++) {
971						if ((dw_ChannelMask >>
972								b_ChannelCpt) &
973							1) {
974							dw_Status =
975								(dw_Status &
976								(0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
977						}
978					}
979
980					outl(dw_Status, devpriv->iobase + 80);
981				}
982
983		 /****************************************/
984				/* Test if set/rest any port 2 channels */
985		 /****************************************/
986
987				if (dw_ChannelMask & 0xFF0000) {
988					dw_BitMask = dw_BitMask >> 16;
989					dw_ChannelMask = dw_ChannelMask >> 16;
990
991		    /********************************************/
992					/* Read port 2 (second digital output port) */
993		    /********************************************/
994
995					dw_Status = inl(devpriv->iobase + 112);
996
997					for (b_ChannelCpt = 0; b_ChannelCpt < 8;
998						b_ChannelCpt++) {
999						if ((dw_ChannelMask >>
1000								b_ChannelCpt) &
1001							1) {
1002							dw_Status =
1003								(dw_Status &
1004								(0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
1005						}
1006					}
1007
1008					outl(dw_Status, devpriv->iobase + 112);
1009				}
1010			}
1011
1012	      /*******************************************/
1013			/* Read port 0 (first digital output port) */
1014	      /*******************************************/
1015
1016			data[1] = inl(devpriv->iobase + 80);
1017
1018	      /******************************************/
1019			/* Read port 1 (first digital input port) */
1020	      /******************************************/
1021
1022			data[1] = data[1] | (inl(devpriv->iobase + 64) << 8);
1023
1024	      /************************/
1025			/* Test if port 2 input */
1026	      /************************/
1027
1028			if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) {
1029				data[1] =
1030					data[1] | (inl(devpriv->iobase +
1031						96) << 16);
1032			} else {
1033				data[1] =
1034					data[1] | (inl(devpriv->iobase +
1035						112) << 16);
1036			}
1037		} else {
1038	      /************************/
1039			/* Config command error */
1040	      /************************/
1041
1042			printk("Channel mask error\n");
1043			i_ReturnValue = -4;
1044		}
1045	} else {
1046	   /*******************/
1047		/* Data size error */
1048	   /*******************/
1049
1050		printk("Buffer size error\n");
1051		i_ReturnValue = -101;
1052	}
1053
1054	return (i_ReturnValue);
1055}
1056
1057/*
1058+----------------------------------------------------------------------------+
1059| Function Name     : INT i_APCI3XXX_InsnReadTTLIO                           |
1060|                          (struct comedi_device    *dev,                           |
1061|                           struct comedi_subdevice *s,                             |
1062|                           struct comedi_insn      *insn,                          |
1063|                           unsigned int         *data)                          |
1064+----------------------------------------------------------------------------+
1065| Task              : Read the status from selected channel                  |
1066+----------------------------------------------------------------------------+
1067| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1068+----------------------------------------------------------------------------+
1069| Output Parameters : data[0] : Selected TTL channel state                   |
1070+----------------------------------------------------------------------------+
1071| Return Value      : 0   : No error                                         |
1072|                    -3   : Channel selection error                          |
1073|                    -101 : Data size error                                  |
1074+----------------------------------------------------------------------------+
1075*/
1076
1077int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
1078	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1079{
1080	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
1081	INT i_ReturnValue = insn->n;
1082	unsigned int *pls_ReadData = data;
1083
1084	/************************/
1085	/* Test the buffer size */
1086	/************************/
1087
1088	if (insn->n >= 1) {
1089	   /***********************/
1090		/* Test if read port 0 */
1091	   /***********************/
1092
1093		if (b_Channel < 8) {
1094	      /*******************************************/
1095			/* Read port 0 (first digital output port) */
1096	      /*******************************************/
1097
1098			pls_ReadData[0] = inl(devpriv->iobase + 80);
1099			pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1;
1100		} else {
1101	      /***********************/
1102			/* Test if read port 1 */
1103	      /***********************/
1104
1105			if ((b_Channel > 7) && (b_Channel < 16)) {
1106		 /******************************************/
1107				/* Read port 1 (first digital input port) */
1108		 /******************************************/
1109
1110				pls_ReadData[0] = inl(devpriv->iobase + 64);
1111				pls_ReadData[0] =
1112					(pls_ReadData[0] >> (b_Channel -
1113						8)) & 1;
1114			} else {
1115		 /***********************/
1116				/* Test if read port 2 */
1117		 /***********************/
1118
1119				if ((b_Channel > 15) && (b_Channel < 24)) {
1120		    /************************/
1121					/* Test if port 2 input */
1122		    /************************/
1123
1124					if ((devpriv->ul_TTLPortConfiguration[0]
1125							& 0xFF) == 0) {
1126						pls_ReadData[0] =
1127							inl(devpriv->iobase +
1128							96);
1129						pls_ReadData[0] =
1130							(pls_ReadData[0] >>
1131							(b_Channel - 16)) & 1;
1132					} else {
1133						pls_ReadData[0] =
1134							inl(devpriv->iobase +
1135							112);
1136						pls_ReadData[0] =
1137							(pls_ReadData[0] >>
1138							(b_Channel - 16)) & 1;
1139					}
1140				} else {
1141		    /***************************/
1142					/* Channel selection error */
1143		    /***************************/
1144
1145					i_ReturnValue = -3;
1146					printk("Channel %d selection error\n",
1147						b_Channel);
1148				}
1149			}
1150		}
1151	} else {
1152	   /*******************/
1153		/* Data size error */
1154	   /*******************/
1155
1156		printk("Buffer size error\n");
1157		i_ReturnValue = -101;
1158	}
1159
1160	return (i_ReturnValue);
1161}
1162
1163/*
1164+----------------------------------------------------------------------------+
1165|                        TTL OUTPUT FUNCTIONS                                |
1166+----------------------------------------------------------------------------+
1167*/
1168
1169/*
1170+----------------------------------------------------------------------------+
1171| Function Name     : INT     i_APCI3XXX_InsnWriteTTLIO                      |
1172|                          (struct comedi_device    *dev,                           |
1173|                           struct comedi_subdevice *s,                             |
1174|                           struct comedi_insn      *insn,                          |
1175|                           unsigned int         *data)                          |
1176+----------------------------------------------------------------------------+
1177| Task              : Set the state from TTL output channel                  |
1178+----------------------------------------------------------------------------+
1179| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1180|                     b_State   = data [0]                                   |
1181+----------------------------------------------------------------------------+
1182| Output Parameters : -                                                      |
1183+----------------------------------------------------------------------------+
1184| Return Value      : 0   : No error                                         |
1185|                    -3   : Channel selection error                          |
1186|                    -101 : Data size error                                  |
1187+----------------------------------------------------------------------------+
1188*/
1189
1190int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
1191	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1192{
1193	INT i_ReturnValue = insn->n;
1194	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
1195	BYTE b_State = 0;
1196	DWORD dw_Status = 0;
1197
1198	/************************/
1199	/* Test the buffer size */
1200	/************************/
1201
1202	if (insn->n >= 1) {
1203		b_State = (BYTE) data[0];
1204
1205	   /***********************/
1206		/* Test if read port 0 */
1207	   /***********************/
1208
1209		if (b_Channel < 8) {
1210	      /*****************************************************************************/
1211			/* Read port 0 (first digital output port) and set/reset the selcted channel */
1212	      /*****************************************************************************/
1213
1214			dw_Status = inl(devpriv->iobase + 80);
1215			dw_Status =
1216				(dw_Status & (0xFF -
1217					(1 << b_Channel))) | ((b_State & 1) <<
1218				b_Channel);
1219			outl(dw_Status, devpriv->iobase + 80);
1220		} else {
1221	      /***********************/
1222			/* Test if read port 2 */
1223	      /***********************/
1224
1225			if ((b_Channel > 15) && (b_Channel < 24)) {
1226		 /*************************/
1227				/* Test if port 2 output */
1228		 /*************************/
1229
1230				if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
1231					== 0xFF) {
1232		    /*****************************************************************************/
1233					/* Read port 2 (first digital output port) and set/reset the selcted channel */
1234		    /*****************************************************************************/
1235
1236					dw_Status = inl(devpriv->iobase + 112);
1237					dw_Status =
1238						(dw_Status & (0xFF -
1239							(1 << (b_Channel -
1240									16)))) |
1241						((b_State & 1) << (b_Channel -
1242							16));
1243					outl(dw_Status, devpriv->iobase + 112);
1244				} else {
1245		    /***************************/
1246					/* Channel selection error */
1247		    /***************************/
1248
1249					i_ReturnValue = -3;
1250					printk("Channel %d selection error\n",
1251						b_Channel);
1252				}
1253			} else {
1254		 /***************************/
1255				/* Channel selection error */
1256		 /***************************/
1257
1258				i_ReturnValue = -3;
1259				printk("Channel %d selection error\n",
1260					b_Channel);
1261			}
1262		}
1263	} else {
1264	   /*******************/
1265		/* Data size error */
1266	   /*******************/
1267
1268		printk("Buffer size error\n");
1269		i_ReturnValue = -101;
1270	}
1271
1272	return (i_ReturnValue);
1273}
1274
1275/*
1276+----------------------------------------------------------------------------+
1277|                           DIGITAL INPUT SUBDEVICE                          |
1278+----------------------------------------------------------------------------+
1279*/
1280
1281/*
1282+----------------------------------------------------------------------------+
1283| Function name     :int i_APCI3XXX_InsnReadDigitalInput                     |
1284|                                          (struct comedi_device *dev,              |
1285|                                           struct comedi_subdevice *s,             |
1286|                                           struct comedi_insn *insn,               |
1287|                                           unsigned int *data)                  |
1288+----------------------------------------------------------------------------+
1289| Task              : Reads the value of the specified Digital input channel |
1290+----------------------------------------------------------------------------+
1291| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec) (0 to 3)           |
1292+----------------------------------------------------------------------------+
1293| Output Parameters : data[0] : Channel value                                |
1294+----------------------------------------------------------------------------+
1295| Return Value      : 0   : No error                                         |
1296|                    -3   : Channel selection error                          |
1297|                    -101 : Data size error                                  |
1298+----------------------------------------------------------------------------+
1299*/
1300
1301int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
1302	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1303{
1304	INT i_ReturnValue = insn->n;
1305	BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
1306	DWORD dw_Temp = 0;
1307
1308	/***************************/
1309	/* Test the channel number */
1310	/***************************/
1311
1312	if (b_Channel <= devpriv->ps_BoardInfo->i_NbrDiChannel) {
1313	   /************************/
1314		/* Test the buffer size */
1315	   /************************/
1316
1317		if (insn->n >= 1) {
1318			dw_Temp = inl(devpriv->iobase + 32);
1319			*data = (dw_Temp >> b_Channel) & 1;
1320		} else {
1321	      /*******************/
1322			/* Data size error */
1323	      /*******************/
1324
1325			printk("Buffer size error\n");
1326			i_ReturnValue = -101;
1327		}
1328	} else {
1329	   /***************************/
1330		/* Channel selection error */
1331	   /***************************/
1332
1333		printk("Channel selection error\n");
1334		i_ReturnValue = -3;
1335	}
1336
1337	return (i_ReturnValue);
1338}
1339
1340/*
1341+----------------------------------------------------------------------------+
1342| Function name     :int i_APCI3XXX_InsnBitsDigitalInput                     |
1343|                                          (struct comedi_device *dev,              |
1344|                                           struct comedi_subdevice *s,             |
1345|                                           struct comedi_insn *insn,               |
1346|                                           unsigned int *data)                  |
1347+----------------------------------------------------------------------------+
1348| Task              : Reads the value of the Digital input Port i.e.4channels|
1349+----------------------------------------------------------------------------+
1350| Input Parameters  : -                                                      |
1351+----------------------------------------------------------------------------+
1352| Output Parameters : data[0] : Port value                                   |
1353+----------------------------------------------------------------------------+
1354| Return Value      :>0: No error                                            |
1355|                    ....                                                    |
1356|                    -101 : Data size error                                  |
1357+----------------------------------------------------------------------------+
1358*/
1359int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
1360	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1361{
1362	INT i_ReturnValue = insn->n;
1363	DWORD dw_Temp = 0;
1364
1365	/************************/
1366	/* Test the buffer size */
1367	/************************/
1368
1369	if (insn->n >= 1) {
1370		dw_Temp = inl(devpriv->iobase + 32);
1371		*data = dw_Temp & 0xf;
1372	} else {
1373	   /*******************/
1374		/* Data size error */
1375	   /*******************/
1376
1377		printk("Buffer size error\n");
1378		i_ReturnValue = -101;
1379	}
1380
1381	return (i_ReturnValue);
1382}
1383
1384/*
1385+----------------------------------------------------------------------------+
1386|                           DIGITAL OUTPUT SUBDEVICE                         |
1387+----------------------------------------------------------------------------+
1388
1389*/
1390
1391/*
1392+----------------------------------------------------------------------------+
1393| Function name     :int i_APCI3XXX_InsnBitsDigitalOutput                    |
1394|                                          (struct comedi_device *dev,              |
1395|                                           struct comedi_subdevice *s,             |
1396|                                           struct comedi_insn *insn,               |
1397|                                           unsigned int *data)                  |
1398+----------------------------------------------------------------------------+
1399| Task              : Write the selected output mask and read the status from|
1400|                     all digital output channles                            |
1401+----------------------------------------------------------------------------+
1402| Input Parameters  : dw_ChannelMask = data [0];                             |
1403|                     dw_BitMask     = data [1];                             |
1404+----------------------------------------------------------------------------+
1405| Output Parameters : data[1] : All digital output channles states           |
1406+----------------------------------------------------------------------------+
1407| Return Value      : >0  : No error                                         |
1408|                    -4   : Channel mask error                               |
1409|                    -101 : Data size error                                  |
1410+----------------------------------------------------------------------------+
1411*/
1412int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
1413	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1414{
1415	INT i_ReturnValue = insn->n;
1416	BYTE b_ChannelCpt = 0;
1417	DWORD dw_ChannelMask = 0;
1418	DWORD dw_BitMask = 0;
1419	DWORD dw_Status = 0;
1420
1421	/************************/
1422	/* Test the buffer size */
1423	/************************/
1424
1425	if (insn->n >= 2) {
1426	   /*******************************/
1427		/* Get the channe and bit mask */
1428	   /*******************************/
1429
1430		dw_ChannelMask = data[0];
1431		dw_BitMask = data[1];
1432
1433	   /*************************/
1434		/* Test the channel mask */
1435	   /*************************/
1436
1437		if ((dw_ChannelMask & 0XFFFFFFF0) == 0) {
1438	      /*********************************/
1439			/* Test if set/reset any channel */
1440	      /*********************************/
1441
1442			if (dw_ChannelMask & 0xF) {
1443		 /********************************/
1444				/* Read the digital output port */
1445		 /********************************/
1446
1447				dw_Status = inl(devpriv->iobase + 48);
1448
1449				for (b_ChannelCpt = 0; b_ChannelCpt < 4;
1450					b_ChannelCpt++) {
1451					if ((dw_ChannelMask >> b_ChannelCpt) &
1452						1) {
1453						dw_Status =
1454							(dw_Status & (0xF -
1455								(1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
1456					}
1457				}
1458
1459				outl(dw_Status, devpriv->iobase + 48);
1460			}
1461
1462	      /********************************/
1463			/* Read the digital output port */
1464	      /********************************/
1465
1466			data[1] = inl(devpriv->iobase + 48);
1467		} else {
1468	      /************************/
1469			/* Config command error */
1470	      /************************/
1471
1472			printk("Channel mask error\n");
1473			i_ReturnValue = -4;
1474		}
1475	} else {
1476	   /*******************/
1477		/* Data size error */
1478	   /*******************/
1479
1480		printk("Buffer size error\n");
1481		i_ReturnValue = -101;
1482	}
1483
1484	return (i_ReturnValue);
1485}
1486
1487/*
1488+----------------------------------------------------------------------------+
1489| Function name     :int i_APCI3XXX_InsnWriteDigitalOutput                   |
1490|                                          (struct comedi_device *dev,              |
1491|                                           struct comedi_subdevice *s,             |
1492|                                           struct comedi_insn *insn,               |
1493|                                           unsigned int *data)                  |
1494+----------------------------------------------------------------------------+
1495| Task              : Set the state from digital output channel              |
1496+----------------------------------------------------------------------------+
1497| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1498|                     b_State   = data [0]                                   |
1499+----------------------------------------------------------------------------+
1500| Output Parameters : -                                                      |
1501+----------------------------------------------------------------------------+
1502| Return Value      : >0  : No error                                         |
1503|                    -3   : Channel selection error                          |
1504|                    -101 : Data size error                                  |
1505+----------------------------------------------------------------------------+
1506*/
1507
1508int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
1509	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1510{
1511	INT i_ReturnValue = insn->n;
1512	BYTE b_Channel = CR_CHAN(insn->chanspec);
1513	BYTE b_State = 0;
1514	DWORD dw_Status = 0;
1515
1516	/************************/
1517	/* Test the buffer size */
1518	/************************/
1519
1520	if (insn->n >= 1) {
1521	   /***************************/
1522		/* Test the channel number */
1523	   /***************************/
1524
1525		if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
1526	      /*******************/
1527			/* Get the command */
1528	      /*******************/
1529
1530			b_State = (BYTE) data[0];
1531
1532	      /********************************/
1533			/* Read the digital output port */
1534	      /********************************/
1535
1536			dw_Status = inl(devpriv->iobase + 48);
1537
1538			dw_Status =
1539				(dw_Status & (0xF -
1540					(1 << b_Channel))) | ((b_State & 1) <<
1541				b_Channel);
1542			outl(dw_Status, devpriv->iobase + 48);
1543		} else {
1544	      /***************************/
1545			/* Channel selection error */
1546	      /***************************/
1547
1548			printk("Channel selection error\n");
1549			i_ReturnValue = -3;
1550		}
1551	} else {
1552	   /*******************/
1553		/* Data size error */
1554	   /*******************/
1555
1556		printk("Buffer size error\n");
1557		i_ReturnValue = -101;
1558	}
1559
1560	return (i_ReturnValue);
1561}
1562
1563/*
1564+----------------------------------------------------------------------------+
1565| Function name     :int i_APCI3XXX_InsnReadDigitalOutput                    |
1566|                                          (struct comedi_device *dev,              |
1567|                                           struct comedi_subdevice *s,             |
1568|                                           struct comedi_insn *insn,               |
1569|                                           unsigned int *data)                  |
1570+----------------------------------------------------------------------------+
1571| Task              : Read the state from digital output channel             |
1572+----------------------------------------------------------------------------+
1573| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
1574+----------------------------------------------------------------------------+
1575| Output Parameters : b_State   = data [0]                                   |
1576+----------------------------------------------------------------------------+
1577| Return Value      : >0  : No error                                         |
1578|                    -3   : Channel selection error                          |
1579|                    -101 : Data size error                                  |
1580+----------------------------------------------------------------------------+
1581*/
1582
1583int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
1584	struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
1585{
1586	INT i_ReturnValue = insn->n;
1587	BYTE b_Channel = CR_CHAN(insn->chanspec);
1588	DWORD dw_Status = 0;
1589
1590	/************************/
1591	/* Test the buffer size */
1592	/************************/
1593
1594	if (insn->n >= 1) {
1595	   /***************************/
1596		/* Test the channel number */
1597	   /***************************/
1598
1599		if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
1600	      /********************************/
1601			/* Read the digital output port */
1602	      /********************************/
1603
1604			dw_Status = inl(devpriv->iobase + 48);
1605
1606			dw_Status = (dw_Status >> b_Channel) & 1;
1607			*data = dw_Status;
1608		} else {
1609	      /***************************/
1610			/* Channel selection error */
1611	      /***************************/
1612
1613			printk("Channel selection error\n");
1614			i_ReturnValue = -3;
1615		}
1616	} else {
1617	   /*******************/
1618		/* Data size error */
1619	   /*******************/
1620
1621		printk("Buffer size error\n");
1622		i_ReturnValue = -101;
1623	}
1624
1625	return (i_ReturnValue);
1626}
1627
1628/*
1629+----------------------------------------------------------------------------+
1630| Function   Name   : int i_APCI3XXX_Reset(struct comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
1631| Task              :resets all the registers                                |
1632+----------------------------------------------------------------------------+
1633| Input Parameters  : struct comedi_device *dev                                     |
1634+----------------------------------------------------------------------------+
1635| Output Parameters : -                                                      |
1636+----------------------------------------------------------------------------+
1637| Return Value      : -                                                      |
1638+----------------------------------------------------------------------------+
1639*/
1640
1641int i_APCI3XXX_Reset(struct comedi_device * dev)
1642{
1643	unsigned char b_Cpt = 0;
1644
1645	/*************************/
1646	/* Disable the interrupt */
1647	/*************************/
1648
1649	disable_irq(dev->irq);
1650
1651	/****************************/
1652	/* Reset the interrupt flag */
1653	/****************************/
1654
1655	devpriv->b_EocEosInterrupt = 0;
1656
1657	/***************************/
1658	/* Clear the start command */
1659	/***************************/
1660
1661	writel(0, (void *)(devpriv->dw_AiBase + 8));
1662
1663	/*****************************/
1664	/* Reset the interrupt flags */
1665	/*****************************/
1666
1667	writel(readl((void *)(devpriv->dw_AiBase + 16)),
1668		(void *)(devpriv->dw_AiBase + 16));
1669
1670	/*****************/
1671	/* clear the EOS */
1672	/*****************/
1673
1674	readl((void *)(devpriv->dw_AiBase + 20));
1675
1676	/******************/
1677	/* Clear the FIFO */
1678	/******************/
1679
1680	for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
1681		readl((void *)(devpriv->dw_AiBase + 28));
1682	}
1683
1684	/************************/
1685	/* Enable the interrupt */
1686	/************************/
1687
1688	enable_irq(dev->irq);
1689
1690	return 0;
1691}
1692