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