hwdrv_apci2200.c revision 39cfb97b0d89a99c8e50782b17e65114b89c2e59
1/**
2@verbatim
3
4Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5
6	ADDI-DATA GmbH
7	Dieselstrasse 3
8	D-77833 Ottersweier
9	Tel: +19(0)7223/9493-0
10	Fax: +49(0)7223/9493-92
11	http://www.addi-data-com
12	info@addi-data.com
13
14This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20You should also find the complete GPL in the COPYING file accompanying this source code.
21
22@endverbatim
23*/
24/*
25
26  +-----------------------------------------------------------------------+
27  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
28  +-----------------------------------------------------------------------+
29  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
30  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
31  +-------------------------------+---------------------------------------+
32  | Project     : APCI-2200       | Compiler   : GCC                      |
33  | Module name : hwdrv_apci2200.c| Version    : 2.96                     |
34  +-------------------------------+---------------------------------------+
35  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
36  +-------------------------------+---------------------------------------+
37  | Description :   Hardware Layer Acces For APCI-2200                    |
38  +-----------------------------------------------------------------------+
39  |                             UPDATES                                   |
40  +----------+-----------+------------------------------------------------+
41  |   Date   |   Author  |          Description of updates                |
42  +----------+-----------+------------------------------------------------+
43  |          |           |                                                |
44  |          |           |                                                |
45  |          |           |                                                |
46  +----------+-----------+------------------------------------------------+
47*/
48
49/*
50+----------------------------------------------------------------------------+
51|                               Included files                               |
52+----------------------------------------------------------------------------+
53*/
54#include "hwdrv_apci2200.h"
55
56/*
57+----------------------------------------------------------------------------+
58| Function   Name   : int i_APCI2200_Read1DigitalInput                       |
59|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
60|                      struct comedi_insn *insn,unsigned int *data)                     |
61+----------------------------------------------------------------------------+
62| Task              : Return the status of the digital input                 |
63+----------------------------------------------------------------------------+
64| Input Parameters  : struct comedi_device *dev      : Driver handle                |
65|		       struct comedi_subdevice *s,   :pointer to subdevice structure
66|                       struct comedi_insn *insn      :pointer to insn structure     |
67|                     unsigned int *data          : Data Pointer to read status  |
68+----------------------------------------------------------------------------+
69| Output Parameters :	--													 |
70+----------------------------------------------------------------------------+
71| Return Value      : TRUE  : No error occur                                 |
72|		            : FALSE : Error occur. Return the error          |
73|			                                                         |
74+----------------------------------------------------------------------------+
75*/
76int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
77	struct comedi_insn *insn, unsigned int *data)
78{
79	unsigned int ui_TmpValue = 0;
80	unsigned int ui_Channel;
81	ui_Channel = CR_CHAN(insn->chanspec);
82	if (ui_Channel <= 7) {
83		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
84		*data = (ui_TmpValue >> ui_Channel) & 0x1;
85	}			/* if(ui_Channel >= 0 && ui_Channel <=7) */
86	else {
87		printk("\nThe specified channel does not exist\n");
88		return -EINVAL;	/*  "sorry channel spec wrong " */
89	}			/* else if(ui_Channel >= 0 && ui_Channel <=7) */
90
91	return insn->n;
92}
93
94/*
95+----------------------------------------------------------------------------+
96| Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
97|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
98|                     struct comedi_insn *insn,unsigned int *data)                      |
99+----------------------------------------------------------------------------+
100| Task              : Return the status of the Requested digital inputs      |
101+----------------------------------------------------------------------------+
102| Input Parameters  : struct comedi_device *dev      : Driver handle                |
103|                      struct comedi_subdevice *s,   :pointer to subdevice structure
104|                       struct comedi_insn *insn      :pointer to insn structure     |
105|                      unsigned int *data         : Data Pointer to read status  |
106+----------------------------------------------------------------------------+
107| Output Parameters :	--													 |
108+----------------------------------------------------------------------------+
109| Return Value      : TRUE  : No error occur                                 |
110|		            : FALSE : Error occur. Return the error          |
111|			                                                         |
112+----------------------------------------------------------------------------+
113*/
114
115int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
116	struct comedi_insn *insn, unsigned int *data)
117{
118
119	unsigned int ui_PortValue = data[0];
120	unsigned int ui_Mask = 0;
121	unsigned int ui_NoOfChannels;
122
123	ui_NoOfChannels = CR_CHAN(insn->chanspec);
124
125	*data = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
126	switch (ui_NoOfChannels) {
127	case 2:
128		ui_Mask = 3;
129		*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
130		break;
131	case 4:
132		ui_Mask = 15;
133		*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
134		break;
135	case 7:
136		break;
137
138	default:
139		printk("\nWrong parameters\n");
140		return -EINVAL;	/*  "sorry channel spec wrong " */
141		break;
142	}			/* switch(ui_NoOfChannels) */
143
144	return insn->n;
145}
146
147/*
148+----------------------------------------------------------------------------+
149| Function   Name   : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
150|                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
151|				                                                     |
152+----------------------------------------------------------------------------+
153| Task              : Configures The Digital Output Subdevice.               |
154+----------------------------------------------------------------------------+
155| Input Parameters  : struct comedi_device *dev : Driver handle                     |
156|                     unsigned int *data         : Data Pointer contains         |
157|                                          configuration parameters as below |
158|                      struct comedi_subdevice *s,   :pointer to subdevice structure
159|                       struct comedi_insn *insn      :pointer to insn structure                                                           |
160|					  data[0]  :1:Memory on                          |
161|					            0:Memory off                         |
162|										                             |
163|																	 |
164+----------------------------------------------------------------------------+
165| Output Parameters :	--													 |
166+----------------------------------------------------------------------------+
167| Return Value      : TRUE  : No error occur                                 |
168|		            : FALSE : Error occur. Return the error          |
169|			                                                         |
170+----------------------------------------------------------------------------+
171*/
172int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
173	struct comedi_insn *insn, unsigned int *data)
174{
175	devpriv->b_OutputMemoryStatus = data[0];
176	return insn->n;
177}
178
179/*
180+----------------------------------------------------------------------------+
181| Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
182|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
183|                     unsigned int *data)                                         |
184+----------------------------------------------------------------------------+
185| Task              : Writes port value  To the selected port                |
186+----------------------------------------------------------------------------+
187| Input Parameters  : struct comedi_device *dev      : Driver handle                |
188|                     struct comedi_subdevice *s,   :pointer to subdevice structure
189|                      struct comedi_insn *insn      :pointer to insn structure      |
190|                    unsigned int *data           : Data Pointer to read status  |
191+----------------------------------------------------------------------------+
192| Output Parameters :	--													 |
193+----------------------------------------------------------------------------+
194| Return Value      : TRUE  : No error occur                                 |
195|		            : FALSE : Error occur. Return the error          |
196|			                                                         |
197+----------------------------------------------------------------------------+
198*/
199
200int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
201	struct comedi_insn *insn, unsigned int *data)
202{
203	unsigned int ui_Temp, ui_Temp1;
204	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
205	if (devpriv->b_OutputMemoryStatus) {
206		ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
207
208	}			/* if(devpriv->b_OutputMemoryStatus ) */
209	else {
210		ui_Temp = 0;
211	}			/* if(devpriv->b_OutputMemoryStatus ) */
212	if (data[3] == 0) {
213		if (data[1] == 0) {
214			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
215			outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP);
216		}		/* if(data[1]==0) */
217		else {
218			if (data[1] == 1) {
219				switch (ui_NoOfChannel) {
220
221				case 2:
222					data[0] =
223						(data[0] << (2 *
224							data[2])) | ui_Temp;
225					break;
226
227				case 4:
228					data[0] =
229						(data[0] << (4 *
230							data[2])) | ui_Temp;
231					break;
232
233				case 8:
234					data[0] =
235						(data[0] << (8 *
236							data[2])) | ui_Temp;
237					break;
238				case 15:
239					data[0] = data[0] | ui_Temp;
240					break;
241				default:
242					comedi_error(dev, " chan spec wrong");
243					return -EINVAL;	/*  "sorry channel spec wrong " */
244
245				}	/* switch(ui_NoOfChannels) */
246
247				outw(data[0],
248					devpriv->iobase + APCI2200_DIGITAL_OP);
249			}	/*  if(data[1]==1) */
250			else {
251				printk("\nSpecified channel not supported\n");
252			}	/* else if(data[1]==1) */
253		}		/* elseif(data[1]==0) */
254	}			/* if(data[3]==0) */
255	else {
256		if (data[3] == 1) {
257			if (data[1] == 0) {
258				data[0] = ~data[0] & 0x1;
259				ui_Temp1 = 1;
260				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
261				ui_Temp = ui_Temp | ui_Temp1;
262				data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
263				data[0] = data[0] & ui_Temp;
264				outw(data[0],
265					devpriv->iobase + APCI2200_DIGITAL_OP);
266			}	/* if(data[1]==0) */
267			else {
268				if (data[1] == 1) {
269					switch (ui_NoOfChannel) {
270
271					case 2:
272						data[0] = ~data[0] & 0x3;
273						ui_Temp1 = 3;
274						ui_Temp1 =
275							ui_Temp1 << 2 * data[2];
276						ui_Temp = ui_Temp | ui_Temp1;
277						data[0] =
278							((data[0] << (2 *
279									data
280									[2])) ^
281							0xffff) & ui_Temp;
282						break;
283
284					case 4:
285						data[0] = ~data[0] & 0xf;
286						ui_Temp1 = 15;
287						ui_Temp1 =
288							ui_Temp1 << 4 * data[2];
289						ui_Temp = ui_Temp | ui_Temp1;
290						data[0] =
291							((data[0] << (4 *
292									data
293									[2])) ^
294							0xffff) & ui_Temp;
295						break;
296
297					case 8:
298						data[0] = ~data[0] & 0xff;
299						ui_Temp1 = 255;
300						ui_Temp1 =
301							ui_Temp1 << 8 * data[2];
302						ui_Temp = ui_Temp | ui_Temp1;
303						data[0] =
304							((data[0] << (8 *
305									data
306									[2])) ^
307							0xffff) & ui_Temp;
308						break;
309					case 15:
310						break;
311
312					default:
313						comedi_error(dev,
314							" chan spec wrong");
315						return -EINVAL;	/*  "sorry channel spec wrong " */
316
317					}	/* switch(ui_NoOfChannels) */
318
319					outw(data[0],
320						devpriv->iobase +
321						APCI2200_DIGITAL_OP);
322				}	/*  if(data[1]==1) */
323				else {
324					printk("\nSpecified channel not supported\n");
325				}	/* else if(data[1]==1) */
326			}	/* elseif(data[1]==0) */
327		}		/* if(data[3]==1); */
328		else {
329			printk("\nSpecified functionality does not exist\n");
330			return -EINVAL;
331		}		/* if else data[3]==1) */
332	}			/* if else data[3]==0) */
333	return insn->n;
334}
335
336/*
337+----------------------------------------------------------------------------+
338| Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
339|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
340|                    unsigned int *data) 	                                     |
341+----------------------------------------------------------------------------+
342| Task              : Read  value  of the selected channel or port           |
343+----------------------------------------------------------------------------+
344| Input Parameters  : struct comedi_device *dev      : Driver handle                |
345|                     struct comedi_subdevice *s,   :pointer to subdevice structure
346|                     struct comedi_insn *insn      :pointer to insn structure      |
347|                     unsigned int *data          : Data Pointer to read status  |
348+----------------------------------------------------------------------------+
349| Output Parameters :	--													 |
350+----------------------------------------------------------------------------+
351| Return Value      : TRUE  : No error occur                                 |
352|		            : FALSE : Error occur. Return the error          |
353|			                                                         |
354+----------------------------------------------------------------------------+
355*/
356
357int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
358	struct comedi_insn *insn, unsigned int *data)
359{
360
361	unsigned int ui_Temp;
362	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
363	ui_Temp = data[0];
364	*data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
365	if (ui_Temp == 0) {
366		*data = (*data >> ui_NoOfChannel) & 0x1;
367	}			/* if(ui_Temp==0) */
368	else {
369		if (ui_Temp == 1) {
370			switch (ui_NoOfChannel) {
371
372			case 2:
373				*data = (*data >> (2 * data[1])) & 3;
374				break;
375
376			case 4:
377				*data = (*data >> (4 * data[1])) & 15;
378				break;
379
380			case 8:
381				*data = (*data >> (8 * data[1])) & 255;
382				break;
383
384			case 15:
385				break;
386
387			default:
388				comedi_error(dev, " chan spec wrong");
389				return -EINVAL;	/*  "sorry channel spec wrong " */
390
391			}	/* switch(ui_NoOfChannels) */
392		}		/* if(ui_Temp==1) */
393		else {
394			printk("\nSpecified channel not supported \n");
395		}		/* elseif(ui_Temp==1) */
396	}			/* elseif(ui_Temp==0) */
397	return insn->n;
398}
399
400/*
401+----------------------------------------------------------------------------+
402| Function   Name   : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
403|                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
404|				                                                     |
405+----------------------------------------------------------------------------+
406| Task              : Configures The Watchdog                                |
407+----------------------------------------------------------------------------+
408| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
409|                     struct comedi_subdevice *s,   :pointer to subdevice structure
410|                      struct comedi_insn *insn      :pointer to insn structure      |
411|                     unsigned int *data          : Data Pointer to read status                                                                                                             |
412+----------------------------------------------------------------------------+
413| Output Parameters :	--													 |
414+----------------------------------------------------------------------------+
415| Return Value      : TRUE  : No error occur                                 |
416|		            : FALSE : Error occur. Return the error          |
417|			                                                         |
418+----------------------------------------------------------------------------+
419*/
420
421int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
422	struct comedi_insn *insn, unsigned int *data)
423{
424	if (data[0] == 0) {
425		/* Disable the watchdog */
426		outw(0x0,
427			devpriv->iobase + APCI2200_WATCHDOG +
428			APCI2200_WATCHDOG_ENABLEDISABLE);
429		/* Loading the Reload value */
430		outw(data[1],
431			devpriv->iobase + APCI2200_WATCHDOG +
432			APCI2200_WATCHDOG_RELOAD_VALUE);
433		data[1] = data[1] >> 16;
434		outw(data[1],
435			devpriv->iobase + APCI2200_WATCHDOG +
436			APCI2200_WATCHDOG_RELOAD_VALUE + 2);
437	}			/* if(data[0]==0) */
438	else {
439		printk("\nThe input parameters are wrong\n");
440		return -EINVAL;
441	}			/* elseif(data[0]==0) */
442
443	return insn->n;
444}
445
446 /*
447    +----------------------------------------------------------------------------+
448    | Function   Name   : int i_APCI2200_StartStopWriteWatchdog                  |
449    |                           (struct comedi_device *dev,struct comedi_subdevice *s,
450    struct comedi_insn *insn,unsigned int *data);                      |
451    +----------------------------------------------------------------------------+
452    | Task              : Start / Stop The Watchdog                              |
453    +----------------------------------------------------------------------------+
454    | Input Parameters  : struct comedi_device *dev      : Driver handle                |
455    |                     struct comedi_subdevice *s,   :pointer to subdevice structure
456    struct comedi_insn *insn      :pointer to insn structure      |
457    |                     unsigned int *data          : Data Pointer to read status  |
458    +----------------------------------------------------------------------------+
459    | Output Parameters :       --                                                                                                       |
460    +----------------------------------------------------------------------------+
461    | Return Value      : TRUE  : No error occur                                 |
462    |                       : FALSE : Error occur. Return the error          |
463    |                                                                            |
464    +----------------------------------------------------------------------------+
465  */
466
467int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
468	struct comedi_insn *insn, unsigned int *data)
469{
470	switch (data[0]) {
471	case 0:		/* stop the watchdog */
472		outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
473		break;
474	case 1:		/* start the watchdog */
475		outw(0x0001,
476			devpriv->iobase + APCI2200_WATCHDOG +
477			APCI2200_WATCHDOG_ENABLEDISABLE);
478		break;
479	case 2:		/* Software trigger */
480		outw(0x0201,
481			devpriv->iobase + APCI2200_WATCHDOG +
482			APCI2200_WATCHDOG_ENABLEDISABLE);
483		break;
484	default:
485		printk("\nSpecified functionality does not exist\n");
486		return -EINVAL;
487	}			/*  switch(data[0]) */
488	return insn->n;
489}
490
491/*
492+----------------------------------------------------------------------------+
493| Function   Name   : int i_APCI2200_ReadWatchdog                            |
494|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
495|                    unsigned int *data); 	                                     |
496+----------------------------------------------------------------------------+
497| Task              : Read The Watchdog                                      |
498+----------------------------------------------------------------------------+
499| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
500|                     struct comedi_subdevice *s,   :pointer to subdevice structure
501|                      struct comedi_insn *insn      :pointer to insn structure      |
502|                     unsigned int *data          : Data Pointer to read status  |
503+----------------------------------------------------------------------------+
504| Output Parameters :	--													 |
505+----------------------------------------------------------------------------+
506| Return Value      : TRUE  : No error occur                                 |
507|		            : FALSE : Error occur. Return the error          |
508|			                                                         |
509+----------------------------------------------------------------------------+
510*/
511
512int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
513	struct comedi_insn *insn, unsigned int *data)
514{
515	data[0] =
516		inw(devpriv->iobase + APCI2200_WATCHDOG +
517		APCI2200_WATCHDOG_STATUS) & 0x1;
518	return insn->n;
519}
520
521/*
522+----------------------------------------------------------------------------+
523| Function   Name   : int i_APCI2200_Reset(struct comedi_device *dev)               |                                                                                                          |
524+----------------------------------------------------------------------------+
525| Task              :resets all the registers                                |
526+----------------------------------------------------------------------------+
527| Input Parameters  : struct comedi_device *dev
528+----------------------------------------------------------------------------+
529| Output Parameters :	--													 |
530+----------------------------------------------------------------------------+
531| Return Value      :                                                        |
532|			                                                         |
533+----------------------------------------------------------------------------+
534*/
535
536int i_APCI2200_Reset(struct comedi_device *dev)
537{
538	outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);	/* RESETS THE DIGITAL OUTPUTS */
539	outw(0x0,
540		devpriv->iobase + APCI2200_WATCHDOG +
541		APCI2200_WATCHDOG_ENABLEDISABLE);
542	outw(0x0,
543		devpriv->iobase + APCI2200_WATCHDOG +
544		APCI2200_WATCHDOG_RELOAD_VALUE);
545	outw(0x0,
546		devpriv->iobase + APCI2200_WATCHDOG +
547		APCI2200_WATCHDOG_RELOAD_VALUE + 2);
548	return 0;
549}
550