hwdrv_apci2016.c revision 356cdbcb838ebcc234a43ec81621a39231fdcb7a
1/**
2@verbatim
3
4Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5
6	ADDI-DATA GmbH
7	Dieselstrasse 3
8	D-77833 Ottersweier
9	Tel: +19(0)7223/9493-0
10	Fax: +49(0)7223/9493-92
11	http://www.addi-data-com
12	info@addi-data.com
13
14This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20You shoud also find the complete GPL in the COPYING file accompanying this source code.
21
22@endverbatim
23*/
24/*
25
26  +-----------------------------------------------------------------------+
27  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
28  +-----------------------------------------------------------------------+
29  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
30  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
31  +-------------------------------+---------------------------------------+
32  | Project     : APCI-2016       | Compiler   : GCC                      |
33  | Module name : hwdrv_apci2016.c| Version    : 2.96                     |
34  +-------------------------------+---------------------------------------+
35  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
36  +-------------------------------+---------------------------------------+
37  | Description :   Hardware Layer Acces For APCI-2016                    |
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_apci2016.h"
55
56/*
57+----------------------------------------------------------------------------+
58| Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |
59|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
60|                      struct comedi_insn *insn,unsigned int *data)                     |
61+----------------------------------------------------------------------------+
62| Task              : Configures The Digital Output Subdevice.               |
63+----------------------------------------------------------------------------+
64| Input Parameters  : struct comedi_device *dev : Driver handle                     |
65|                     unsigned int *data         : Data Pointer contains             |
66|                                          configuration parameters as below |
67|                                                                            |
68|			  data[0]            : 1 Digital Memory On               |
69|				     			   0 Digital Memory Off              |
70+----------------------------------------------------------------------------+
71| Output Parameters :	--													 |
72+----------------------------------------------------------------------------+
73| Return Value      : TRUE  : No error occur                                 |
74|		            : FALSE : Error occur. Return the error          |
75|			                                                         |
76+----------------------------------------------------------------------------+
77*/
78int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
79	struct comedi_insn *insn, unsigned int *data)
80{
81	if ((data[0] != 0) && (data[0] != 1)) {
82		comedi_error(dev,
83			"Not a valid Data !!! ,Data should be 1 or 0\n");
84		return -EINVAL;
85	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
86	if (data[0]) {
87		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
88	}			/*  if  (data[0] */
89	else {
90		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
91	}			/*  else if  (data[0] */
92	return insn->n;
93}
94
95/*
96+----------------------------------------------------------------------------+
97| Function   Name   : int i_APCI2016_WriteDigitalOutput                      |
98|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
99|                      struct comedi_insn *insn,unsigned int *data)                     |
100+----------------------------------------------------------------------------+
101| Task              : Writes port value  To the selected port                |
102+----------------------------------------------------------------------------+
103| Input Parameters  : struct comedi_device *dev      : Driver handle                |
104|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
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*/
114int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
115	struct comedi_insn *insn, unsigned int *data)
116{
117	unsigned int ui_NoOfChannel;
118	unsigned int ui_Temp, ui_Temp1;
119	ui_NoOfChannel = CR_CHAN(insn->chanspec);
120	if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
121		comedi_error(dev,
122			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
123		return -EINVAL;
124	}			/*  if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */
125	if (devpriv->b_OutputMemoryStatus) {
126		ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP);
127	}			/*  if  (devpriv->b_OutputMemoryStatus ) */
128	else {
129		ui_Temp = 0;
130	}			/*  else if  (devpriv->b_OutputMemoryStatus ) */
131	if ((data[1] != 0) && (data[1] != 1)) {
132		comedi_error(dev,
133			"Invalid Data[1] value !!!, Data[1] should be 0 or 1\n");
134		return -EINVAL;
135	}			/*  if  ((data[1]!=0) && (data[1]!=1)) */
136
137	if (data[3] == 0) {
138		if (data[1] == 0) {
139			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
140			outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP);
141		}		/*  if (data[1]==0) */
142		else {
143			if (data[1] == 1) {
144				switch (ui_NoOfChannel) {
145				case 2:
146					data[0] =
147						(data[0] << (2 *
148							data[2])) | ui_Temp;
149					break;
150				case 4:
151					data[0] =
152						(data[0] << (4 *
153							data[2])) | ui_Temp;
154					break;
155				case 8:
156					data[0] =
157						(data[0] << (8 *
158							data[2])) | ui_Temp;
159					break;
160				case 15:
161					data[0] = data[0] | ui_Temp;
162					break;
163				default:
164					comedi_error(dev, " chan spec wrong");
165					return -EINVAL;	/*  "sorry channel spec wrong " */
166				}	/* switch(ui_NoOfChannels) */
167				outw(data[0],
168					devpriv->iobase + APCI2016_DIGITAL_OP);
169			}	/*  if  (data[1]==1) */
170			else {
171				printk("\nSpecified channel not supported\n");
172			}	/*  else if  (data[1]==1) */
173		}		/*  else if (data[1]==0) */
174	}			/*  if (data[3]==0) */
175	else {
176		if (data[3] == 1) {
177			if (data[1] == 0) {
178				data[0] = ~data[0] & 0x1;
179				ui_Temp1 = 1;
180				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
181				ui_Temp = ui_Temp | ui_Temp1;
182				data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
183				data[0] = data[0] & ui_Temp;
184				outw(data[0],
185					devpriv->iobase + APCI2016_DIGITAL_OP);
186			}	/*  if  (data[1]==0) */
187			else {
188				if (data[1] == 1) {
189					switch (ui_NoOfChannel) {
190					case 2:
191						data[0] = ~data[0] & 0x3;
192						ui_Temp1 = 3;
193						ui_Temp1 =
194							ui_Temp1 << 2 * data[2];
195						ui_Temp = ui_Temp | ui_Temp1;
196						data[0] =
197							((data[0] << (2 *
198									data
199									[2])) ^
200							0xffff) & ui_Temp;
201						break;
202					case 4:
203						data[0] = ~data[0] & 0xf;
204						ui_Temp1 = 15;
205						ui_Temp1 =
206							ui_Temp1 << 4 * data[2];
207						ui_Temp = ui_Temp | ui_Temp1;
208						data[0] =
209							((data[0] << (4 *
210									data
211									[2])) ^
212							0xffff) & ui_Temp;
213						break;
214					case 8:
215						data[0] = ~data[0] & 0xff;
216						ui_Temp1 = 255;
217						ui_Temp1 =
218							ui_Temp1 << 8 * data[2];
219						ui_Temp = ui_Temp | ui_Temp1;
220						data[0] =
221							((data[0] << (8 *
222									data
223									[2])) ^
224							0xffff) & ui_Temp;
225						break;
226					case 15:
227						break;
228					default:
229						comedi_error(dev,
230							" chan spec wrong");
231						return -EINVAL;	/*  "sorry channel spec wrong " */
232					}	/* switch(ui_NoOfChannels) */
233					outw(data[0],
234						devpriv->iobase +
235						APCI2016_DIGITAL_OP);
236				}	/*  if(data[1]==1) */
237				else {
238					printk("\nSpecified channel not supported\n");
239				}	/* else if(data[1]==1) */
240			}	/* elseif(data[1]==0) */
241		}		/* if(data[3]==1); */
242		else {
243			printk("\nSpecified functionality does not exist\n");
244			return -EINVAL;
245		}		/* if else data[3]==1) */
246	}			/* if else data[3]==0) */
247	return insn->n;
248}
249
250/*
251+----------------------------------------------------------------------------+
252| Function   Name   : int i_APCI2016_BitsDigitalOutput                       |
253|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
254|                      struct comedi_insn *insn,unsigned int *data)                     |
255+----------------------------------------------------------------------------+
256| Task              : Read  value  of the selected channel or port           |
257+----------------------------------------------------------------------------+
258| Input Parameters  : struct comedi_device *dev      : Driver handle                |
259|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
260|                     unsigned int *data              : Data Pointer to read status  |
261+----------------------------------------------------------------------------+
262| Output Parameters :	--													 |
263+----------------------------------------------------------------------------+
264| Return Value      : TRUE  : No error occur                                 |
265|		            : FALSE : Error occur. Return the error          |
266|			                                                         |
267+----------------------------------------------------------------------------+
268*/
269int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
270	struct comedi_insn *insn, unsigned int *data)
271{
272	unsigned int ui_Temp;
273	unsigned int ui_NoOfChannel;
274	ui_NoOfChannel = CR_CHAN(insn->chanspec);
275	if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
276		comedi_error(dev,
277			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
278		return -EINVAL;
279	}			/*  if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */
280	if ((data[0] != 0) && (data[0] != 1)) {
281		comedi_error(dev,
282			"Invalid Data[0] value !!!, Data[0] should be 0 or 1\n");
283		return -EINVAL;
284	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
285	ui_Temp = data[0];
286	*data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW);
287	if (ui_Temp == 0) {
288		*data = (*data >> ui_NoOfChannel) & 0x1;
289	}			/*  if  (ui_Temp==0) */
290	else {
291		if (ui_Temp == 1) {
292			switch (ui_NoOfChannel) {
293			case 2:
294				*data = (*data >> (2 * data[1])) & 3;
295				break;
296
297			case 4:
298				*data = (*data >> (4 * data[1])) & 15;
299				break;
300
301			case 8:
302				*data = (*data >> (8 * data[1])) & 255;
303				break;
304
305			case 15:
306				break;
307
308			default:
309				comedi_error(dev, " chan spec wrong");
310				return -EINVAL;	/*  "sorry channel spec wrong " */
311			}	/* switch(ui_NoOfChannel) */
312		}		/*  if  (ui_Temp==1) */
313		else {
314			printk("\nSpecified channel not supported \n");
315		}		/*  else if  (ui_Temp==1) */
316	}			/*  if  (ui_Temp==0) */
317	return insn->n;
318}
319
320/*
321+----------------------------------------------------------------------------+
322| Function   Name   : int i_APCI2016_ConfigWatchdog                          |
323|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
324|                      struct comedi_insn *insn,unsigned int *data)                     |
325+----------------------------------------------------------------------------+
326| Task              : Configures The Watchdog                                |
327+----------------------------------------------------------------------------+
328| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
329|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
330|                     struct comedi_insn *insn      :pointer to insn structure      |
331|                     unsigned int *data          : Data Pointer to read status  |
332+----------------------------------------------------------------------------+
333| Output Parameters :	--													 |
334+----------------------------------------------------------------------------+
335| Return Value      : TRUE  : No error occur                                 |
336|		            : FALSE : Error occur. Return the error          |
337|			                                                         |
338+----------------------------------------------------------------------------+
339*/
340int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
341	struct comedi_insn *insn, unsigned int *data)
342{
343
344	if (data[0] == 0) {
345		/* Disable the watchdog */
346		outw(0x0,
347			devpriv->i_IobaseAddon +
348			APCI2016_WATCHDOG_ENABLEDISABLE);
349		/* Loading the Reload value */
350		outw(data[1],
351			devpriv->i_IobaseAddon +
352			APCI2016_WATCHDOG_RELOAD_VALUE);
353		data[1] = data[1] >> 16;
354		outw(data[1],
355			devpriv->i_IobaseAddon +
356			APCI2016_WATCHDOG_RELOAD_VALUE + 2);
357	} else {
358		printk("\nThe input parameters are wrong\n");
359	}
360	return insn->n;
361}
362
363/*
364+----------------------------------------------------------------------------+
365| Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |
366|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
367|                      struct comedi_insn *insn,unsigned int *data)                     |
368+----------------------------------------------------------------------------+
369| Task              : Start / Stop The Watchdog                              |
370+----------------------------------------------------------------------------+
371| Input Parameters  : struct comedi_device *dev      : Driver handle                |
372|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
373|                     struct comedi_insn *insn      :pointer to insn structure      |
374|                     unsigned int *data          : Data Pointer to read status  |
375+----------------------------------------------------------------------------+
376| Output Parameters :	--													 |
377+----------------------------------------------------------------------------+
378| Return Value      : TRUE  : No error occur                                 |
379|		            : FALSE : Error occur. Return the error          |
380|			                                                         |
381+----------------------------------------------------------------------------+
382*/
383int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
384	struct comedi_insn *insn, unsigned int *data)
385{
386
387	switch (data[0]) {
388	case 0:		/* stop the watchdog */
389		outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
390		break;
391	case 1:		/* start the watchdog */
392		outw(0x0001,
393			devpriv->i_IobaseAddon +
394			APCI2016_WATCHDOG_ENABLEDISABLE);
395		break;
396	case 2:		/* Software trigger */
397		outw(0x0201,
398			devpriv->i_IobaseAddon +
399			APCI2016_WATCHDOG_ENABLEDISABLE);
400		break;
401	default:
402		printk("\nSpecified functionality does not exist\n");
403		return -EINVAL;
404	}			/*  switch(data[0]) */
405
406	return insn->n;
407}
408
409/*
410+----------------------------------------------------------------------------+
411| Function   Name   : int i_APCI2016_ReadWatchdog                            |
412|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
413|                      struct comedi_insn *insn,unsigned int *data)                     |
414+----------------------------------------------------------------------------+
415| Task              : Read The Watchdog                                      |
416+----------------------------------------------------------------------------+
417| Input Parameters  : struct comedi_device *dev      : Driver handle                |
418|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
419|                     struct comedi_insn *insn      :pointer to insn structure      |
420|                     unsigned int *data          : Data Pointer to read status  |
421+----------------------------------------------------------------------------+
422| Output Parameters :	--													 |
423+----------------------------------------------------------------------------+
424| Return Value      : TRUE  : No error occur                                 |
425|		            : FALSE : Error occur. Return the error          |
426|			                                                         |
427+----------------------------------------------------------------------------+
428*/
429
430int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
431	struct comedi_insn *insn, unsigned int *data)
432{
433	udelay(5);
434	data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
435	return insn->n;
436}
437
438/*
439+----------------------------------------------------------------------------+
440| Function   Name   : int i_APCI2016_Reset(struct comedi_device *dev)               |                                                       |
441+----------------------------------------------------------------------------+
442| Task              :resets all the registers                                |
443+----------------------------------------------------------------------------+
444| Input Parameters  : struct comedi_device *dev
445+----------------------------------------------------------------------------+
446| Output Parameters :	--													 |
447+----------------------------------------------------------------------------+
448| Return Value      :                                                        |
449|			                                                         |
450+----------------------------------------------------------------------------+
451*/
452
453int i_APCI2016_Reset(struct comedi_device *dev)
454{
455	outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);	/*  Resets the digital output channels */
456	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
457	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE);
458	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2);
459	return 0;
460}
461