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 should 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-035 | Compiler : GCC |
33 | Module name : hwdrv_apci035.c | Version : 2.96 |
34 +-------------------------------+---------------------------------------+
35 | Project manager: Eric Stolz | Date : 02/12/2002 |
36 +-------------------------------+---------------------------------------+
37 | Description : Hardware Layer Access For APCI-035 |
38 +-----------------------------------------------------------------------+
40 +----------+-----------+------------------------------------------------+
41 | Date | Author | Description of updates |
42 +----------+-----------+------------------------------------------------+
46 +----------+-----------+------------------------------------------------+
49 /* Card Specific information */
50 #define APCI035_ADDRESS_RANGE 255
52 /* Timer / Watchdog Related Defines */
53 #define APCI035_TCW_SYNC_ENABLEDISABLE 0
54 #define APCI035_TCW_RELOAD_VALUE 4
55 #define APCI035_TCW_TIMEBASE 8
56 #define APCI035_TCW_PROG 12
57 #define APCI035_TCW_TRIG_STATUS 16
58 #define APCI035_TCW_IRQ 20
59 #define APCI035_TCW_WARN_TIMEVAL 24
60 #define APCI035_TCW_WARN_TIMEBASE 28
62 #define ADDIDATA_TIMER 0
63 /* #define ADDIDATA_WATCHDOG 1 */
66 #define APCI035_TW2 32
67 #define APCI035_TW3 64
68 #define APCI035_TW4 96
70 #define APCI035_AI_OFFSET 0
71 #define APCI035_TEMP 128
72 #define APCI035_ALR_SEQ 4
73 #define APCI035_START_STOP_INDEX 8
74 #define APCI035_ALR_START_STOP 12
75 #define APCI035_ALR_IRQ 16
76 #define APCI035_EOS 20
77 #define APCI035_CHAN_NO 24
78 #define APCI035_CHAN_VAL 28
79 #define APCI035_CONV_TIME_TIME_BASE 36
80 #define APCI035_RELOAD_CONV_TIME_VAL 32
81 #define APCI035_DELAY_TIME_TIME_BASE 44
82 #define APCI035_RELOAD_DELAY_TIME_VAL 40
83 #define ENABLE_EXT_TRIG 1
84 #define ENABLE_EXT_GATE 2
85 #define ENABLE_EXT_TRIG_GATE 3
87 #define ANALOG_INPUT 0
91 #define ADDIDATA_GREATER_THAN_TEST 0
92 #define ADDIDATA_LESS_THAN_TEST 1
94 #define APCI035_MAXVOLT 2.5
96 #define ADDIDATA_UNIPOLAR 1
97 #define ADDIDATA_BIPOLAR 2
99 /* ANALOG INPUT RANGE */
100 static struct comedi_lrange range_apci035_ai = {
113 static int i_WatchdogNbr = 0;
114 static int i_Temp = 0;
115 static int i_Flag = 1;
117 +----------------------------------------------------------------------------+
118 | Function Name : int i_APCI035_ConfigTimerWatchdog |
119 | (struct comedi_device *dev,struct comedi_subdevice *s, |
120 | struct comedi_insn *insn,unsigned int *data) |
121 +----------------------------------------------------------------------------+
122 | Task : Configures The Timer , Counter or Watchdog |
123 +----------------------------------------------------------------------------+
124 | Input Parameters : struct comedi_device *dev : Driver handle |
125 | unsigned int *data : Data Pointer contains |
126 | configuration parameters as below |
128 | data[0] : 0 Configure As Timer |
129 | 1 Configure As Watchdog |
130 | data[1] : Watchdog number
131 | data[2] : Time base Unit |
132 | data[3] : Reload Value |
133 | data[4] : External Trigger |
136 | data[5] :External Trigger Level
137 | 00 Trigger Disabled
138 | 01 Trigger Enabled (Low level)
139 | 10 Trigger Enabled (High Level)
140 | 11 Trigger Enabled (High/Low level)
141 | data[6] : External Gate |
144 | data[7] : External Gate level
146 | 01 Gate Enabled (Low level)
147 | 10 Gate Enabled (High Level)
148 | data[8] :Warning Relay
151 | data[9] :Warning Delay available
152 | data[10] :Warning Relay Time unit
153 | data[11] :Warning Relay Time Reload value
154 | data[12] :Reset Relay
157 | data[13] :Interrupt
162 +----------------------------------------------------------------------------+
163 | Output Parameters : -- |
164 +----------------------------------------------------------------------------+
165 | Return Value : TRUE : No error occur |
166 | : FALSE : Error occur. Return the error |
168 +----------------------------------------------------------------------------+
170 static int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev,
171 struct comedi_subdevice *s,
172 struct comedi_insn *insn,
175 struct addi_private *devpriv = dev->private;
176 unsigned int ui_Status = 0;
177 unsigned int ui_Command = 0;
178 unsigned int ui_Mode = 0;
181 devpriv->tsk_Current = current;
182 devpriv->b_TimerSelectMode = data[0];
183 i_WatchdogNbr = data[1];
189 /* ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); */
191 /* ui_Command = ui_Command & 0xFFFFF9FEUL; */
192 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
194 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
195 /************************/
196 /* Set the reload value */
197 /************************/
198 outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
199 /*********************/
200 /* Set the time unit */
201 /*********************/
202 outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
203 if (data[0] == ADDIDATA_TIMER) {
205 /******************************/
207 /* - Disable the hardware */
208 /* - Disable the counter mode */
209 /* - Disable the warning */
210 /* - Disable the reset */
211 /* - Enable the timer mode */
212 /* - Set the timer mode */
213 /******************************/
216 (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
218 } /* if (data[0] == ADDIDATA_TIMER) */
220 if (data[0] == ADDIDATA_WATCHDOG) {
222 /******************************/
224 /* - Disable the hardware */
225 /* - Disable the counter mode */
226 /* - Disable the warning */
227 /* - Disable the reset */
228 /* - Disable the timer mode */
229 /******************************/
231 ui_Command = ui_Command & 0xFFF819E2UL;
234 printk("\n The parameter for Timer/watchdog selection is in error\n");
238 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
240 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
241 /********************************/
242 /* Disable the hardware trigger */
243 /********************************/
244 ui_Command = ui_Command & 0xFFFFF89FUL;
245 if (data[4] == ADDIDATA_ENABLE) {
246 /**********************************/
247 /* Set the hardware trigger level */
248 /**********************************/
249 ui_Command = ui_Command | (data[5] << 5);
251 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
253 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
254 /*****************************/
255 /* Disable the hardware gate */
256 /*****************************/
257 ui_Command = ui_Command & 0xFFFFF87FUL;
258 if (data[6] == ADDIDATA_ENABLE) {
259 /*******************************/
260 /* Set the hardware gate level */
261 /*******************************/
262 ui_Command = ui_Command | (data[7] << 7);
264 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
266 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
267 /*******************************/
268 /* Disable the hardware output */
269 /*******************************/
270 ui_Command = ui_Command & 0xFFFFF9FBUL;
271 /*********************************/
272 /* Set the hardware output level */
273 /*********************************/
274 ui_Command = ui_Command | (data[8] << 2);
275 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
276 if (data[9] == ADDIDATA_ENABLE) {
277 /************************/
278 /* Set the reload value */
279 /************************/
281 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
282 /**********************/
283 /* Set the time unite */
284 /**********************/
286 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
290 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
291 /*******************************/
292 /* Disable the hardware output */
293 /*******************************/
294 ui_Command = ui_Command & 0xFFFFF9F7UL;
295 /*********************************/
296 /* Set the hardware output level */
297 /*********************************/
298 ui_Command = ui_Command | (data[12] << 3);
299 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
300 /*************************************/
301 /** Enable the watchdog interrupt **/
302 /*************************************/
304 ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
305 /*******************************/
306 /* Set the interrupt selection */
307 /*******************************/
308 ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
310 ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
311 outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
317 +----------------------------------------------------------------------------+
318 | Function Name : int i_APCI035_StartStopWriteTimerWatchdog |
319 | (struct comedi_device *dev,struct comedi_subdevice *s, |
320 | struct comedi_insn *insn,unsigned int *data) |
321 +----------------------------------------------------------------------------+
322 | Task : Start / Stop The Selected Timer , or Watchdog |
323 +----------------------------------------------------------------------------+
324 | Input Parameters : struct comedi_device *dev : Driver handle |
325 | unsigned int *data : Data Pointer contains |
326 | configuration parameters as below |
328 | data[0] : 0 - Stop Selected Timer/Watchdog |
329 | 1 - Start Selected Timer/Watchdog |
330 | 2 - Trigger Selected Timer/Watchdog |
331 | 3 - Stop All Timer/Watchdog |
332 | 4 - Start All Timer/Watchdog |
333 | 5 - Trigger All Timer/Watchdog |
335 +----------------------------------------------------------------------------+
336 | Output Parameters : -- |
337 +----------------------------------------------------------------------------+
338 | Return Value : TRUE : No error occur |
339 | : FALSE : Error occur. Return the error |
341 +----------------------------------------------------------------------------+
343 static int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
344 struct comedi_subdevice *s,
345 struct comedi_insn *insn,
348 struct addi_private *devpriv = dev->private;
349 unsigned int ui_Command = 0;
354 inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
355 /**********************/
356 /* Start the hardware */
357 /**********************/
358 ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
360 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
361 } /* if (data[0]==1) */
364 inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
365 /***************************/
366 /* Set the trigger command */
367 /***************************/
368 ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
370 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
373 if (data[0] == 0) /* Stop The Watchdog */
375 /* Stop The Watchdog */
378 * ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
379 * ui_Command = ui_Command & 0xFFFFF9FEUL;
382 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
383 } /* if (data[1]==0) */
384 if (data[0] == 3) /* stop all Watchdogs */
387 for (i_Count = 1; i_Count <= 4; i_Count++) {
388 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
393 i_WatchdogNbr = i_Count;
395 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
400 if (data[0] == 4) /* start all Watchdogs */
403 for (i_Count = 1; i_Count <= 4; i_Count++) {
404 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
409 i_WatchdogNbr = i_Count;
411 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
415 if (data[0] == 5) /* trigger all Watchdogs */
418 for (i_Count = 1; i_Count <= 4; i_Count++) {
419 if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
425 i_WatchdogNbr = i_Count;
427 devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
436 +----------------------------------------------------------------------------+
437 | Function Name : int i_APCI035_ReadTimerWatchdog |
438 | (struct comedi_device *dev,struct comedi_subdevice *s, |
439 | struct comedi_insn *insn,unsigned int *data) |
440 +----------------------------------------------------------------------------+
441 | Task : Read The Selected Timer , Counter or Watchdog |
442 +----------------------------------------------------------------------------+
443 | Input Parameters : struct comedi_device *dev : Driver handle |
444 | unsigned int *data : Data Pointer contains |
445 | configuration parameters as below |
448 +----------------------------------------------------------------------------+
449 | Output Parameters : data[0] : software trigger status
450 | data[1] : hardware trigger status
451 | data[2] : Software clear status
452 | data[3] : Overflow status
453 | data[4] : Timer actual value
456 +----------------------------------------------------------------------------+
457 | Return Value : TRUE : No error occur |
458 | : FALSE : Error occur. Return the error |
460 +----------------------------------------------------------------------------+
462 static int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev,
463 struct comedi_subdevice *s,
464 struct comedi_insn *insn,
467 struct addi_private *devpriv = dev->private;
468 unsigned int ui_Status = 0; /* Status register */
470 i_WatchdogNbr = insn->unused[0];
476 ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
478 /***********************************/
479 /* Get the software trigger status */
480 /***********************************/
482 data[0] = ((ui_Status >> 1) & 1);
483 /***********************************/
484 /* Get the hardware trigger status */
485 /***********************************/
486 data[1] = ((ui_Status >> 2) & 1);
487 /*********************************/
488 /* Get the software clear status */
489 /*********************************/
490 data[2] = ((ui_Status >> 3) & 1);
491 /***************************/
492 /* Get the overflow status */
493 /***************************/
494 data[3] = ((ui_Status >> 0) & 1);
495 if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
496 data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
498 } /* if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) */
504 +----------------------------------------------------------------------------+
505 | Function Name : int i_APCI035_ConfigAnalogInput |
506 | (struct comedi_device *dev,struct comedi_subdevice *s, |
507 | struct comedi_insn *insn,unsigned int *data) |
508 +----------------------------------------------------------------------------+
509 | Task : Configures The Analog Input Subdevice |
510 +----------------------------------------------------------------------------+
511 | Input Parameters : struct comedi_device *dev : Driver handle |
512 | struct comedi_subdevice *s : Subdevice Pointer |
513 | struct comedi_insn *insn : Insn Structure Pointer |
514 | unsigned int *data : Data Pointer contains |
515 | configuration parameters as below |
516 | data[0] : Warning delay value
518 +----------------------------------------------------------------------------+
519 | Output Parameters : -- |
520 +----------------------------------------------------------------------------+
521 | Return Value : TRUE : No error occur |
522 | : FALSE : Error occur. Return the error |
524 +----------------------------------------------------------------------------+
526 static int i_APCI035_ConfigAnalogInput(struct comedi_device *dev,
527 struct comedi_subdevice *s,
528 struct comedi_insn *insn,
531 struct addi_private *devpriv = dev->private;
533 devpriv->tsk_Current = current;
534 outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
535 outl(0, devpriv->iobase + 128 + 0);
536 /********************************/
537 /* Initialise the warning value */
538 /********************************/
539 outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
540 outl((data[0] << 8), devpriv->iobase + 128 + 0);
541 outl(0x200000UL, devpriv->iobase + 128 + 12);
547 +----------------------------------------------------------------------------+
548 | Function Name : int i_APCI035_ReadAnalogInput |
549 | (struct comedi_device *dev,struct comedi_subdevice *s, |
550 | struct comedi_insn *insn,unsigned int *data) |
551 +----------------------------------------------------------------------------+
552 | Task : Read value of the selected channel |
553 +----------------------------------------------------------------------------+
554 | Input Parameters : struct comedi_device *dev : Driver handle |
555 | unsigned int ui_NoOfChannels : No Of Channels To read |
556 | unsigned int *data : Data Pointer to read status |
557 +----------------------------------------------------------------------------+
558 | Output Parameters : -- |
559 | data[0] : Digital Value Of Input |
561 +----------------------------------------------------------------------------+
562 | Return Value : TRUE : No error occur |
563 | : FALSE : Error occur. Return the error |
565 +----------------------------------------------------------------------------+
567 static int i_APCI035_ReadAnalogInput(struct comedi_device *dev,
568 struct comedi_subdevice *s,
569 struct comedi_insn *insn,
572 struct addi_private *devpriv = dev->private;
573 unsigned int ui_CommandRegister = 0;
578 ui_CommandRegister = 0x80000;
579 /******************************/
580 /* Write the command register */
581 /******************************/
582 outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
584 /***************************************/
585 /* Read the digital value of the input */
586 /***************************************/
587 data[0] = inl(devpriv->iobase + 128 + 28);
592 +----------------------------------------------------------------------------+
593 | Function Name : int i_APCI035_Reset(struct comedi_device *dev) |
595 +----------------------------------------------------------------------------+
596 | Task :Resets the registers of the card |
597 +----------------------------------------------------------------------------+
598 | Input Parameters : |
599 +----------------------------------------------------------------------------+
600 | Output Parameters : -- |
601 +----------------------------------------------------------------------------+
604 +----------------------------------------------------------------------------+
606 static int i_APCI035_Reset(struct comedi_device *dev)
608 struct addi_private *devpriv = dev->private;
611 for (i_Count = 1; i_Count <= 4; i_Count++) {
612 i_WatchdogNbr = i_Count;
613 outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); /* stop all timers */
615 outl(0x0, devpriv->iobase + 128 + 12); /* Disable the warning delay */
621 +----------------------------------------------------------------------------+
622 | Function Name : static void v_APCI035_Interrupt |
623 | (int irq , void *d) |
624 +----------------------------------------------------------------------------+
625 | Task : Interrupt processing Routine |
626 +----------------------------------------------------------------------------+
627 | Input Parameters : int irq : irq number |
628 | void *d : void pointer |
629 +----------------------------------------------------------------------------+
630 | Output Parameters : -- |
631 +----------------------------------------------------------------------------+
632 | Return Value : TRUE : No error occur |
633 | : FALSE : Error occur. Return the error |
635 +----------------------------------------------------------------------------+
637 static void v_APCI035_Interrupt(int irq, void *d)
639 struct comedi_device *dev = d;
640 struct addi_private *devpriv = dev->private;
641 unsigned int ui_StatusRegister1 = 0;
642 unsigned int ui_StatusRegister2 = 0;
643 unsigned int ui_ReadCommand = 0;
644 unsigned int ui_ChannelNumber = 0;
645 unsigned int ui_DigitalTemperature = 0;
648 i_WatchdogNbr = i_Flag;
651 /**************************************/
652 /* Read the interrupt status register of temperature Warning */
653 /**************************************/
654 ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
655 /**************************************/
656 /* Read the interrupt status register for Watchdog/timer */
657 /**************************************/
660 inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
662 if ((((ui_StatusRegister1) & 0x8) == 0x8)) /* Test if warning relay interrupt */
664 /**********************************/
665 /* Disable the temperature warning */
666 /**********************************/
667 ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
668 ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
669 outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
670 /***************************/
671 /* Read the channel number */
672 /***************************/
673 ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
674 /**************************************/
675 /* Read the digital temperature value */
676 /**************************************/
677 ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
678 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
679 } /* if (((ui_StatusRegister1 & 0x8) == 0x8)) */
682 if ((ui_StatusRegister2 & 0x1) == 0x1) {
683 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */
685 } /* else if (((ui_StatusRegister1 & 0x8) == 0x8)) */