4 Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
10 Fax: +49(0)7223/9493-92
11 http://www.addi-data-com
14 This 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.
16 This 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.
18 You 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
20 You shoud also find the complete GPL in the COPYING file accompanying this source code.
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-2032 | Compiler : GCC |
33 | Module name : hwdrv_apci2032.c| Version : 2.96 |
34 +-------------------------------+---------------------------------------+
35 | Project manager: Eric Stolz | Date : 02/12/2002 |
36 +-------------------------------+---------------------------------------+
37 | Description : Hardware Layer Acces For APCI-2032 |
38 +-----------------------------------------------------------------------+
40 +----------+-----------+------------------------------------------------+
41 | Date | Author | Description of updates |
42 +----------+-----------+------------------------------------------------+
46 +----------+-----------+------------------------------------------------+
50 +----------------------------------------------------------------------------+
52 +----------------------------------------------------------------------------+
55 #include "hwdrv_apci2032.h"
56 unsigned int ui_InterruptData, ui_Type;
58 +----------------------------------------------------------------------------+
59 | Function Name : int i_APCI2032_ConfigDigitalOutput |
60 | (struct comedi_device *dev,struct comedi_subdevice *s, |
61 | struct comedi_insn *insn,unsigned int *data) |
62 +----------------------------------------------------------------------------+
63 | Task : Configures The Digital Output Subdevice. |
64 +----------------------------------------------------------------------------+
65 | Input Parameters : struct comedi_device *dev : Driver handle |
66 | unsigned int *data : Data Pointer contains |
67 | configuration parameters as below |
69 | data[1] : 1 Enable VCC Interrupt |
70 | 0 Disable VCC Interrupt |
71 | data[2] : 1 Enable CC Interrupt |
72 | 0 Disable CC Interrupt |
74 +----------------------------------------------------------------------------+
75 | Output Parameters : -- |
76 +----------------------------------------------------------------------------+
77 | Return Value : TRUE : No error occur |
78 | : FALSE : Error occur. Return the error |
80 +----------------------------------------------------------------------------+
82 int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
83 struct comedi_insn *insn, unsigned int *data)
85 unsigned int ul_Command = 0;
86 devpriv->tsk_Current = current;
88 if ((data[0] != 0) && (data[0] != 1)) {
90 "Not a valid Data !!! ,Data should be 1 or 0\n");
92 } /* if ( (data[0]!=0) && (data[0]!=1) ) */
94 devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
97 devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
98 } /* else if (data[0]) */
100 if (data[1] == ADDIDATA_ENABLE) {
101 ul_Command = ul_Command | 0x1;
102 } /* if (data[1] == ADDIDATA_ENABLE) */
104 ul_Command = ul_Command & 0xFFFFFFFE;
105 } /* elseif (data[1] == ADDIDATA_ENABLE) */
106 if (data[2] == ADDIDATA_ENABLE) {
107 ul_Command = ul_Command | 0x2;
108 } /* if (data[2] == ADDIDATA_ENABLE) */
110 ul_Command = ul_Command & 0xFFFFFFFD;
111 } /* elseif (data[2] == ADDIDATA_ENABLE) */
112 outl(ul_Command, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
113 ui_InterruptData = inl(devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
118 +----------------------------------------------------------------------------+
119 | Function Name : int i_APCI2032_WriteDigitalOutput |
120 | (struct comedi_device *dev,struct comedi_subdevice *s, |
121 | struct comedi_insn *insn,unsigned int *data) |
122 +----------------------------------------------------------------------------+
123 | Task : Writes port value To the selected port |
124 +----------------------------------------------------------------------------+
125 | Input Parameters : struct comedi_device *dev : Driver handle |
126 | unsigned int ui_NoOfChannels : No Of Channels To Write |
127 | unsigned int *data : Data Pointer to read status |
128 +----------------------------------------------------------------------------+
129 | Output Parameters : -- |
130 +----------------------------------------------------------------------------+
131 | Return Value : TRUE : No error occur |
132 | : FALSE : Error occur. Return the error |
134 +----------------------------------------------------------------------------+
137 int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
138 struct comedi_insn *insn, unsigned int *data)
140 unsigned int ui_Temp, ui_Temp1;
141 unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */
142 if (devpriv->b_OutputMemoryStatus) {
143 ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
145 } /* if(devpriv->b_OutputMemoryStatus ) */
148 } /* if(devpriv->b_OutputMemoryStatus ) */
151 data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
152 outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP);
153 } /* if(data[1]==0) */
156 switch (ui_NoOfChannel) {
182 data[0] = data[0] | ui_Temp;
186 comedi_error(dev, " chan spec wrong");
187 return -EINVAL; /* "sorry channel spec wrong " */
189 } /* switch(ui_NoOfChannels) */
192 devpriv->iobase + APCI2032_DIGITAL_OP);
193 } /* if(data[1]==1) */
195 printk("\nSpecified channel not supported\n");
196 } /* else if(data[1]==1) */
197 } /* elseif(data[1]==0) */
198 } /* if(data[3]==0) */
202 data[0] = ~data[0] & 0x1;
204 ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
205 ui_Temp = ui_Temp | ui_Temp1;
207 (data[0] << ui_NoOfChannel) ^
209 data[0] = data[0] & ui_Temp;
211 devpriv->iobase + APCI2032_DIGITAL_OP);
212 } /* if(data[1]==0) */
215 switch (ui_NoOfChannel) {
218 data[0] = ~data[0] & 0x3;
221 ui_Temp1 << 2 * data[2];
222 ui_Temp = ui_Temp | ui_Temp1;
227 0xffffffff) & ui_Temp;
231 data[0] = ~data[0] & 0xf;
234 ui_Temp1 << 4 * data[2];
235 ui_Temp = ui_Temp | ui_Temp1;
240 0xffffffff) & ui_Temp;
244 data[0] = ~data[0] & 0xff;
247 ui_Temp1 << 8 * data[2];
248 ui_Temp = ui_Temp | ui_Temp1;
253 0xffffffff) & ui_Temp;
257 data[0] = ~data[0] & 0xffff;
262 ui_Temp = ui_Temp | ui_Temp1;
267 0xffffffff) & ui_Temp;
275 return -EINVAL; /* "sorry channel spec wrong " */
277 } /* switch(ui_NoOfChannels) */
281 APCI2032_DIGITAL_OP);
282 } /* if(data[1]==1) */
284 printk("\nSpecified channel not supported\n");
285 } /* else if(data[1]==1) */
286 } /* elseif(data[1]==0) */
287 } /* if(data[3]==1); */
289 printk("\nSpecified functionality does not exist\n");
291 } /* if else data[3]==1) */
292 } /* if else data[3]==0) */
297 +----------------------------------------------------------------------------+
298 | Function Name : int i_APCI2032_ReadDigitalOutput |
299 | (struct comedi_device *dev,struct comedi_subdevice *s, |
300 | struct comedi_insn *insn,unsigned int *data) |
301 +----------------------------------------------------------------------------+
302 | Task : Read value of the selected channel or port |
303 +----------------------------------------------------------------------------+
304 | Input Parameters : struct comedi_device *dev : Driver handle |
305 | unsigned int ui_NoOfChannels : No Of Channels To read |
306 | unsigned int *data : Data Pointer to read status |
307 +----------------------------------------------------------------------------+
308 | Output Parameters : -- |
309 +----------------------------------------------------------------------------+
310 | Return Value : TRUE : No error occur |
311 | : FALSE : Error occur. Return the error |
313 +----------------------------------------------------------------------------+
316 int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
317 struct comedi_insn *insn, unsigned int *data)
319 unsigned int ui_Temp;
320 unsigned int ui_NoOfChannel;
321 ui_NoOfChannel = CR_CHAN(insn->chanspec);
323 *data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
325 *data = (*data >> ui_NoOfChannel) & 0x1;
326 } /* if (ui_Temp==0) */
329 switch (ui_NoOfChannel) {
332 *data = (*data >> (2 * data[1])) & 3;
336 *data = (*data >> (4 * data[1])) & 15;
340 *data = (*data >> (8 * data[1])) & 255;
344 *data = (*data >> (16 * data[1])) & 65535;
351 comedi_error(dev, " chan spec wrong");
352 return -EINVAL; /* "sorry channel spec wrong " */
354 } /* switch(ui_NoOfChannels) */
355 } /* if (ui_Temp==1) */
357 printk("\nSpecified channel not supported \n");
358 } /* elseif (ui_Temp==1) */
364 +----------------------------------------------------------------------------+
365 | Function Name : int i_APCI2032_ConfigWatchdog(comedi_device
366 | *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
368 +----------------------------------------------------------------------------+
369 | Task : Configures 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 |
381 +----------------------------------------------------------------------------+
383 int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
384 struct comedi_insn *insn, unsigned int *data)
387 /* Disable the watchdog */
389 devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
391 /* Loading the Reload value */
393 devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
394 APCI2032_TCW_RELOAD_VALUE);
396 printk("\nThe input parameters are wrong\n");
404 +----------------------------------------------------------------------------+
405 | Function Name : int i_APCI2032_StartStopWriteWatchdog |
406 | (struct comedi_device *dev,struct comedi_subdevice *s,
407 struct comedi_insn *insn,unsigned int *data); |
408 +----------------------------------------------------------------------------+
409 | Task : Start / Stop The Watchdog |
410 +----------------------------------------------------------------------------+
411 | Input Parameters : struct comedi_device *dev : Driver handle |
412 | struct comedi_subdevice *s, :pointer to subdevice structure
413 struct comedi_insn *insn :pointer to insn structure |
414 | unsigned int *data : Data Pointer to read status |
415 +----------------------------------------------------------------------------+
416 | Output Parameters : -- |
417 +----------------------------------------------------------------------------+
418 | Return Value : TRUE : No error occur |
419 | : FALSE : Error occur. Return the error |
421 +----------------------------------------------------------------------------+
424 int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
425 struct comedi_insn *insn, unsigned int *data)
428 case 0: /* stop the watchdog */
429 outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); /* disable the watchdog */
431 case 1: /* start the watchdog */
433 devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
436 case 2: /* Software trigger */
438 devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
442 printk("\nSpecified functionality does not exist\n");
449 +----------------------------------------------------------------------------+
450 | Function Name : int i_APCI2032_ReadWatchdog |
451 | (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
452 | unsigned int *data); |
453 +----------------------------------------------------------------------------+
454 | Task : Read The Watchdog |
455 +----------------------------------------------------------------------------+
456 | Input Parameters : struct comedi_device *dev : Driver handle |
457 | struct comedi_subdevice *s, :pointer to subdevice structure
458 | struct comedi_insn *insn :pointer to insn structure |
459 | unsigned int *data : Data Pointer to read status |
460 +----------------------------------------------------------------------------+
461 | Output Parameters : -- |
462 +----------------------------------------------------------------------------+
463 | Return Value : TRUE : No error occur |
464 | : FALSE : Error occur. Return the error |
466 +----------------------------------------------------------------------------+
469 int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
470 struct comedi_insn *insn, unsigned int *data)
474 inl(devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
475 APCI2032_TCW_TRIG_STATUS) & 0x1;
480 +----------------------------------------------------------------------------+
481 | Function Name : void v_APCI2032_Interrupt |
482 | (int irq , void *d) |
483 +----------------------------------------------------------------------------+
484 | Task : Writes port value To the selected port |
485 +----------------------------------------------------------------------------+
486 | Input Parameters : int irq : irq number |
487 | void *d : void pointer |
488 +----------------------------------------------------------------------------+
489 | Output Parameters : -- |
490 +----------------------------------------------------------------------------+
491 | Return Value : TRUE : No error occur |
492 | : FALSE : Error occur. Return the error |
494 +----------------------------------------------------------------------------+
496 void v_APCI2032_Interrupt(int irq, void *d)
498 struct comedi_device *dev = d;
501 ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1; /* Check if VCC OR CC interrupt has occured. */
504 printk("\nInterrupt from unKnown source\n");
507 /* Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
509 inl(devpriv->iobase +
510 APCI2032_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
512 devpriv->iobase + APCI2032_DIGITAL_OP +
513 APCI2032_DIGITAL_OP_INTERRUPT);
515 /* Sends signal to user space */
516 send_sig(SIGIO, devpriv->tsk_Current, 0);
517 } /* if (ui_Type==1) */
520 /* Sends signal to user space */
521 send_sig(SIGIO, devpriv->tsk_Current, 0);
522 } /* if (ui_Type==2) */
523 } /* else if (ui_Type==1) */
531 +----------------------------------------------------------------------------+
532 | Function Name : int i_APCI2032_ReadInterruptStatus |
533 | (struct comedi_device *dev,struct comedi_subdevice *s, |
534 | struct comedi_insn *insn,unsigned int *data) |
535 +----------------------------------------------------------------------------+
536 | Task :Reads the interrupt status register |
537 +----------------------------------------------------------------------------+
538 | Input Parameters : |
539 +----------------------------------------------------------------------------+
540 | Output Parameters : -- |
541 +----------------------------------------------------------------------------+
544 +----------------------------------------------------------------------------+
547 int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
548 struct comedi_insn *insn, unsigned int *data)
555 +----------------------------------------------------------------------------+
556 | Function Name : int i_APCI2032_Reset(struct comedi_device *dev) |
558 +----------------------------------------------------------------------------+
559 | Task :Resets the registers of the card |
560 +----------------------------------------------------------------------------+
561 | Input Parameters : |
562 +----------------------------------------------------------------------------+
563 | Output Parameters : -- |
564 +----------------------------------------------------------------------------+
567 +----------------------------------------------------------------------------+
570 int i_APCI2032_Reset(struct comedi_device *dev)
572 devpriv->b_DigitalOutputRegister = 0;
574 outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP); /* Resets the output channels */
575 outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT); /* Disables the interrupt. */
576 outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); /* disable the watchdog */
577 outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE); /* reload=0 */