Staging: comedi: add addi-data drivers
authorADDI-DATA GmbH <info@addi-data.com>
Thu, 12 Feb 2009 23:14:18 +0000 (15:14 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 3 Apr 2009 21:53:41 +0000 (14:53 -0700)
This adds the addi-data family of comedi drivers to the staging tree

From: ADDI-DATA GmbH <info@addi-data.com>
Cc: David Schleef <ds@schleef.org>
Cc: Frank Mori Hess <fmhess@users.sourceforge.net>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
70 files changed:
drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/addi_common.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/addi_common.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/addi_eeprom.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_035.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_1032.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_1500.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_1516.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_1564.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_16xx.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_1710.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_2016.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_2032.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_2200.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_3001.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_3120.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_3200.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_3300.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_3501.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_3xxx.c [new file with mode: 0644]
drivers/staging/comedi/drivers/addi_apci_all.c [new file with mode: 0644]

diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
new file mode 100644 (file)
index 0000000..0c91a24
--- /dev/null
@@ -0,0 +1,1690 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : 82X54.C         | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 82X54 timer module                          |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 29/06/98 | S. Weber  | Digital input / output implementation          |
+  |----------|-----------|------------------------------------------------|
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+  | 27.10.03 | J. Krauth |  Add the possibility to use a 40 Mhz quartz    |
+  |          |           |                                                |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_82x54.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_InitTimer                         |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr,                         |
+|                                BYTE_   b_TimerNbr,                         |
+|                                BYTE_   b_TimerMode,                        |
+|                                ULONG_ ul_ReloadValue,                      |
+|                                BYTE_   b_InputClockSelection,              |
+|                                BYTE_   b_InputClockLevel,                  |
+|                                BYTE_   b_OutputLevel,                      |
+|                                BYTE_   b_HardwareGateLevel)
+INT i_InsnConfig_InitTimer(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)
+|
++----------------------------------------------------------------------------+
+| Task              : Configure the Timer (b_TimerNbr) operating mode        |
+|                     (b_TimerMode) from selected module (b_ModulNbr).       |
+|                     You must calling this function be for you call any     |
+|                     other function witch access of the timer.              |
+|                                                                            |
+|                                                                            |
+|                       Timer mode description table                         |
+|                                                                            |
+|+--------+-----------------------------+--------------+--------------------+|
+||Selected+      Mode description       +u_ReloadValue | Hardware gate input||
+||  mode  |                             |  description |      action        ||
+|+--------+-----------------------------+--------------+--------------------+|
+||        |Mode 0 is typically used     |              |                    ||
+||        |for event counting. After    |              |                    ||
+||        |the initialisation, OUT      |              |                    ||
+||        |is initially low, and        |              |                    ||
+||   0    |will remain low until the    |Start counting|   Hardware gate    ||
+||        |counter reaches zero.        |   value      |                    ||
+||        |OUT then goes high and       |              |                    ||
+||        |remains high until a new     |              |                    ||
+||        |count is written. See        |              |                    ||
+||        |"i_APCI1710_WriteTimerValue" |              |                    ||
+||        |function.                    |              |                    ||
+|+--------+-----------------------------+--------------+--------------------+|
+||        |Mode 1 is similar to mode 0  |              |                    ||
+||        |except for the gate input    |              |                    ||
+||   1    |action. The gate input is not|Start counting|  Hardware trigger  ||
+||        |used for enabled or disabled |   value      |                    ||
+||        |the timer.                   |              |                    ||
+||        |The gate input is used for   |              |                    ||
+||        |triggered the timer.         |              |                    ||
+|+--------+-----------------------------+--------------+--------------------+|
+||        |This mode functions like a   |              |                    ||
+||        |divide-by-ul_ReloadValue     |              |                    ||
+||        |counter. It is typically used|              |                    ||
+||        |to generate a real time clock|              |                    ||
+||        |interrupt. OUT will initially|              |                    ||
+||   2    |be high after the            |   Division   |  Hardware gate     ||
+||        |initialisation. When the     |    factor    |                    ||
+||        |initial count has decremented|              |                    ||
+||        |to 1, OUT goes low for one   |              |                    ||
+||        |CLK pule. OUT then goes high |              |                    ||
+||        |again, the counter reloads   |              |                    ||
+||        |the initial count            |              |                    ||
+||        |(ul_ReloadValue) and the     |              |                    ||
+||        |process is repeated.         |              |                    ||
+||        |This action can generated a  |              |                    ||
+||        |interrupt. See function      |              |                    ||
+||        |"i_APCI1710_SetBoardInt-     |              |                    ||
+||        |RoutineX"                    |              |                    ||
+||        |and "i_APCI1710_EnableTimer" |              |                    ||
+|+--------+-----------------------------+--------------+--------------------+|
+||        |Mode 3 is typically used for |              |                    ||
+||        |baud rate generation. This   |              |                    ||
+||        |mode is similar to mode 2    |              |                    ||
+||        |except for the duty cycle of |              |                    ||
+||   3    |OUT. OUT will initially be   |  Division    |   Hardware gate    ||
+||        |high after the initialisation|   factor     |                    ||
+||        |When half the initial count  |              |                    ||
+||        |(ul_ReloadValue) has expired,|              |                    ||
+||        |OUT goes low for the         |              |                    ||
+||        |remainder of the count. The  |              |                    ||
+||        |mode is periodic; the        |              |                    ||
+||        |sequence above is repeated   |              |                    ||
+||        |indefinitely.                |              |                    ||
+|+--------+-----------------------------+--------------+--------------------+|
+||        |OUT will be initially high   |              |                    ||
+||        |after the initialisation.    |              |                    ||
+||        |When the initial count       |              |                    ||
+||   4    |expires OUT will go low for  |Start counting|  Hardware gate     ||
+||        |one CLK pulse and then go    |    value     |                    ||
+||        |high again.                  |              |                    ||
+||        |The counting sequences is    |              |                    ||
+||        |triggered by writing a new   |              |                    ||
+||        |value. See                   |              |                    ||
+||        |"i_APCI1710_WriteTimerValue" |              |                    ||
+||        |function. If a new count is  |              |                    ||
+||        |written during counting,     |              |                    ||
+||        |it will be loaded on the     |              |                    ||
+||        |next CLK pulse               |              |                    ||
+|+--------+-----------------------------+--------------+--------------------+|
+||        |Mode 5 is similar to mode 4  |              |                    ||
+||        |except for the gate input    |              |                    ||
+||        |action. The gate input is not|              |                    ||
+||   5    |used for enabled or disabled |Start counting|  Hardware trigger  ||
+||        |the timer. The gate input is |    value     |                    ||
+||        |used for triggered the timer.|              |                    ||
+|+--------+-----------------------------+--------------+--------------------+|
+|                                                                            |
+|                                                                            |
+|                                                                            |
+|                      Input clock selection table                           |
+|                                                                            |
+|  +--------------------------------+------------------------------------+   |
+|  |       b_InputClockSelection    |           Description              |   |
+|  |           parameter            |                                    |   |
+|  +--------------------------------+------------------------------------+   |
+|  |    APCI1710_PCI_BUS_CLOCK      | For the timer input clock, the PCI |   |
+|  |                                | bus clock / 4 is used. This PCI bus|   |
+|  |                                | clock can be 30MHz or 33MHz. For   |   |
+|  |                                | Timer 0 only this selection are    |   |
+|  |                                | available.                         |   |
+|  +--------------------------------+------------------------------------+   |
+|  | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the|   |
+|  |                                | possibility to inject a input clock|   |
+|  |                                | for Timer 1 or Timer 2. The source |   |
+|  |                                | from this clock can eat the output |   |
+|  |                                | clock from Timer 0 or any other    |   |
+|  |                                | clock source.                      |   |
+|  +--------------------------------+------------------------------------+   |
+|                                                                            |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle        : Handle of board         |
+|                                                    APCI-1710               |
+|                     BYTE_   b_ModulNbr           : Module number to        |
+|                                                    configure (0 to 3)      |
+|                     BYTE_   b_TimerNbr           : Timer number to         |
+|                                                    configure (0 to 2)      |
+|                     BYTE_   b_TimerMode          : Timer mode selection    |
+|                                                    (0 to 5)                |
+|                                                    0: Interrupt on terminal|
+|                                                       count                |
+|                                                    1: Hardware             |
+|                                                       retriggerable one-   |
+|                                                       shot                 |
+|                                                    2: Rate generator       |
+|                                                    3: Square wave mode     |
+|                                                    4: Software triggered   |
+|                                                       strobe               |
+|                                                    5: Hardware triggered   |
+|                                                       strobe               |
+|                                                       See timer mode       |
+|                                                       description table.   |
+|                     ULONG_ ul_ReloadValue         : Start counting value   |
+|                                                     or division factor     |
+|                                                     See timer mode         |
+|                                                     description table.     |
+|                     BYTE_   b_InputClockSelection : Selection from input   |
+|                                                     timer clock.           |
+|                                                     See input clock        |
+|                                                     selection table.       |
+|                     BYTE_   b_InputClockLevel     : Selection from input   |
+|                                                     clock level.           |
+|                                                     0 : Low active         |
+|                                                         (Input inverted)   |
+|                                                     1 : High active        |
+|                     BYTE_   b_OutputLevel,        : Selection from output  |
+|                                                     clock level.           |
+|                                                     0 : Low active         |
+|                                                     1 : High active        |
+|                                                         (Output inverted)  |
+|                     BYTE_   b_HardwareGateLevel   : Selection from         |
+|                                                     hardware gate level.   |
+|                                                     0 : Low active         |
+|                                                         (Input inverted)   |
+|                                                     1 : High active        |
+|                                                     If you will not used   |
+|                                                     the hardware gate set  |
+|                                                     this value to 0.
+|b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);
+       b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);
+       b_TimerMode               = (BYTE) data[0];
+       ul_ReloadValue    = (ULONG) data[1];
+       b_InputClockSelection   =(BYTE) data[2];
+       b_InputClockLevel               =(BYTE) data[3];
+       b_OutputLevel                   =(BYTE) data[4];
+       b_HardwareGateLevel             =(BYTE) data[5];
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: Timer selection wrong                               |
+|                    -4: The module is not a TIMER module                    |
+|                    -5: Timer mode selection is wrong                       |
+|                    -6: Input timer clock selection is wrong                |
+|                    -7: Selection from input clock level is wrong           |
+|                    -8: Selection from output clock level is wrong          |
+|                    -9: Selection from hardware gate level is wrong         |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       INT i_ReturnValue = 0;
+       BYTE b_ModulNbr;
+       BYTE b_TimerNbr;
+       BYTE b_TimerMode;
+       ULONG ul_ReloadValue;
+       BYTE b_InputClockSelection;
+       BYTE b_InputClockLevel;
+       BYTE b_OutputLevel;
+       BYTE b_HardwareGateLevel;
+
+       //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+       DWORD dw_Test = 0;
+       //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+       b_TimerMode = (BYTE) data[0];
+       ul_ReloadValue = (ULONG) data[1];
+       b_InputClockSelection = (BYTE) data[2];
+       b_InputClockLevel = (BYTE) data[3];
+       b_OutputLevel = (BYTE) data[4];
+       b_HardwareGateLevel = (BYTE) data[5];
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if 82X54 timer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+             /*************************/
+                       /* Test the timer number */
+             /*************************/
+
+                       if (b_TimerNbr <= 2) {
+                /***********************/
+                               /* Test the timer mode */
+                /***********************/
+
+                               if (b_TimerMode <= 5) {
+                                       //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+                   /*********************************/
+                                       /* Test te imput clock selection */
+                   /*********************************/
+                                       /*
+                                          if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||
+                                          ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1))))
+                                        */
+
+                                       if (((b_TimerNbr == 0)
+                                                       &&
+                                                       (b_InputClockSelection
+                                                               ==
+                                                               APCI1710_PCI_BUS_CLOCK))
+                                               || ((b_TimerNbr == 0)
+                                                       &&
+                                                       (b_InputClockSelection
+                                                               ==
+                                                               APCI1710_10MHZ))
+                                               || ((b_TimerNbr != 0)
+                                                       &&
+                                                       ((b_InputClockSelection
+                                                                       ==
+                                                                       APCI1710_PCI_BUS_CLOCK)
+                                                               ||
+                                                               (b_InputClockSelection
+                                                                       ==
+                                                                       APCI1710_FRONT_CONNECTOR_INPUT)
+                                                               ||
+                                                               (b_InputClockSelection
+                                                                       ==
+                                                                       APCI1710_10MHZ))))
+                                               //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+                                       {
+                                               //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+                                               if (((b_InputClockSelection ==
+                                                                       APCI1710_10MHZ)
+                                                               && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) || (b_InputClockSelection != APCI1710_10MHZ)) {
+                                                       //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+                         /****************************************/
+                                                       /* Test the input clock level selection */
+                         /****************************************/
+
+                                                       if ((b_InputClockLevel
+                                                                       == 0)
+                                                               ||
+                                                               (b_InputClockLevel
+                                                                       == 1)) {
+                            /*****************************************/
+                                                               /* Test the output clock level selection */
+                            /*****************************************/
+
+                                                               if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) {
+                               /******************************************/
+                                                                       /* Test the hardware gate level selection */
+                               /******************************************/
+
+                                                                       if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) {
+                                                                               //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+                                  /*****************************************************/
+                                                                               /* Test if version > 1.1 and clock selection = 10MHz */
+                                  /*****************************************************/
+
+                                                                               if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) {
+                                     /*********************************/
+                                                                                       /* Test if 40MHz quartz on board */
+                                     /*********************************/
+
+                                                                                       dw_Test = inl(devpriv->s_BoardInfos.ui_Address + (16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)));
+
+                                                                                       dw_Test = (dw_Test >> 16) & 1;
+                                                                               } else {
+                                                                                       dw_Test = 1;
+                                                                               }
+
+                                  /************************/
+                                                                               /* Test if detection OK */
+                                  /************************/
+
+                                                                               if (dw_Test == 1) {
+                                                                                       //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+                                     /*********************/
+                                                                                       /* Initialisation OK */
+                                     /*********************/
+
+                                                                                       devpriv->
+                                                                                               s_ModuleInfo
+                                                                                               [b_ModulNbr].
+                                                                                               s_82X54ModuleInfo.
+                                                                                               s_82X54TimerInfo
+                                                                                               [b_TimerNbr].
+                                                                                               b_82X54Init
+                                                                                               =
+                                                                                               1;
+
+                                     /**********************************/
+                                                                                       /* Save the input clock selection */
+                                     /**********************************/
+                                                                                       devpriv->
+                                                                                               s_ModuleInfo
+                                                                                               [b_ModulNbr].
+                                                                                               s_82X54ModuleInfo.
+                                                                                               s_82X54TimerInfo
+                                                                                               [b_TimerNbr].
+                                                                                               b_InputClockSelection
+                                                                                               =
+                                                                                               b_InputClockSelection;
+
+                                     /******************************/
+                                                                                       /* Save the input clock level */
+                                     /******************************/
+                                                                                       devpriv->
+                                                                                               s_ModuleInfo
+                                                                                               [b_ModulNbr].
+                                                                                               s_82X54ModuleInfo.
+                                                                                               s_82X54TimerInfo
+                                                                                               [b_TimerNbr].
+                                                                                               b_InputClockLevel
+                                                                                               =
+                                                                                               ~b_InputClockLevel
+                                                                                               &
+                                                                                               1;
+
+                                     /*************************/
+                                                                                       /* Save the output level */
+                                     /*************************/
+
+                                                                                       devpriv->
+                                                                                               s_ModuleInfo
+                                                                                               [b_ModulNbr].
+                                                                                               s_82X54ModuleInfo.
+                                                                                               s_82X54TimerInfo
+                                                                                               [b_TimerNbr].
+                                                                                               b_OutputLevel
+                                                                                               =
+                                                                                               ~b_OutputLevel
+                                                                                               &
+                                                                                               1;
+
+                                     /***********************/
+                                                                                       /* Save the gate level */
+                                     /***********************/
+
+                                                                                       devpriv->
+                                                                                               s_ModuleInfo
+                                                                                               [b_ModulNbr].
+                                                                                               s_82X54ModuleInfo.
+                                                                                               s_82X54TimerInfo
+                                                                                               [b_TimerNbr].
+                                                                                               b_HardwareGateLevel
+                                                                                               =
+                                                                                               b_HardwareGateLevel;
+
+                                     /****************************************************/
+                                                                                       /* Set the configuration word and disable the timer */
+                                     /****************************************************/
+                                                                                       //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+                                                                                       /*
+                                                                                          devpriv->s_ModuleInfo [b_ModulNbr].
+                                                                                          s_82X54ModuleInfo.
+                                                                                          s_82X54TimerInfo  [b_TimerNbr].
+                                                                                          dw_ConfigurationWord = (DWORD) (((b_HardwareGateLevel         << 0) & 0x1) |
+                                                                                          ((b_InputClockLevel           << 1) & 0x2) |
+                                                                                          (((~b_OutputLevel       & 1)  << 2) & 0x4) |
+                                                                                          ((b_InputClockSelection       << 4) & 0x10));
+                                                                                        */
+                                     /**************************/
+                                                                                       /* Test if 10MHz selected */
+                                     /**************************/
+
+                                                                                       if (b_InputClockSelection == APCI1710_10MHZ) {
+                                                                                               b_InputClockSelection
+                                                                                                       =
+                                                                                                       2;
+                                                                                       }
+
+                                                                                       devpriv->
+                                                                                               s_ModuleInfo
+                                                                                               [b_ModulNbr].
+                                                                                               s_82X54ModuleInfo.
+                                                                                               s_82X54TimerInfo
+                                                                                               [b_TimerNbr].
+                                                                                               dw_ConfigurationWord
+                                                                                               =
+                                                                                               (DWORD)
+                                                                                               (
+                                                                                               ((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30));
+                                                                                       //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+                                                                                       outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+                                     /******************************/
+                                                                                       /* Initialise the 82X54 Timer */
+                                     /******************************/
+
+                                                                                       outl((DWORD) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+                                     /**************************/
+                                                                                       /* Write the reload value */
+                                     /**************************/
+
+                                                                                       outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+                                                                                       //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+                                                                               }       // if (dw_Test == 1)
+                                                                               else {
+                                     /****************************************/
+                                                                                       /* Input timer clock selection is wrong */
+                                     /****************************************/
+
+                                                                                       i_ReturnValue
+                                                                                               =
+                                                                                               -6;
+                                                                               }       // if (dw_Test == 1)
+                                                                               //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+                                                                       }       // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))
+                                                                       else {
+                               /***********************************************/
+                                                                               /* Selection from hardware gate level is wrong */
+                               /***********************************************/
+
+                                                                               DPRINTK("Selection from hardware gate level is wrong\n");
+                                                                               i_ReturnValue
+                                                                                       =
+                                                                                       -9;
+                                                                       }       // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))
+                                                               }       // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
+                                                               else {
+                            /**********************************************/
+                                                                       /* Selection from output clock level is wrong */
+                            /**********************************************/
+
+                                                                       DPRINTK("Selection from output clock level is wrong\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -8;
+                                                               }       // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
+                                                       }       // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
+                                                       else {
+                         /*********************************************/
+                                                               /* Selection from input clock level is wrong */
+                         /*********************************************/
+
+                                                               DPRINTK("Selection from input clock level is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }       // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
+                                               } else {
+                      /****************************************/
+                                                       /* Input timer clock selection is wrong */
+                      /****************************************/
+
+                                                       DPRINTK("Input timer clock selection is wrong\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       } else {
+                   /****************************************/
+                                               /* Input timer clock selection is wrong */
+                   /****************************************/
+
+                                               DPRINTK("Input timer clock selection is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }
+                               }       // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
+                               else {
+                /*********************************/
+                                       /* Timer mode selection is wrong */
+                /*********************************/
+
+                                       DPRINTK("Timer mode selection is wrong\n");
+                                       i_ReturnValue = -5;
+                               }       // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
+                       }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+                       else {
+             /*************************/
+                               /* Timer selection wrong */
+             /*************************/
+
+                               DPRINTK("Timer selection wrong\n");
+                               i_ReturnValue = -3;
+                       }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+               } else {
+          /************************************/
+                       /* The module is not a TIMER module */
+          /************************************/
+
+                       DPRINTK("The module is not a TIMER module\n");
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_EnableTimer                       |
+|                               (BYTE_ b_BoardHandle,                        |
+|                                BYTE_ b_ModulNbr,                           |
+|                                BYTE_ b_TimerNbr,                           |
+|                                BYTE_ b_InterruptEnable)
+INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)                |
++----------------------------------------------------------------------------+
+| Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |
+|                     (b_ModulNbr). You must calling the                     |
+|                     "i_APCI1710_InitTimer" function be for you call this   |
+|                     function. If you enable the timer interrupt, the timer |
+|                     generate a interrupt after the timer value reach       |
+|                     the zero. See function "i_APCI1710_SetBoardIntRoutineX"|
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
+|                                                 APCI-1710                  |
+|                     BYTE_   b_ModulNbr        : Selected module number     |
+|                                                 (0 to 3)                   |
+|                     BYTE_   b_TimerNbr        : Timer number to enable     |
+|                                                 (0 to 2)                   |
+|                     BYTE_   b_InterruptEnable : Enable or disable the      |
+|                                                 timer interrupt.           |
+|                                                 APCI1710_ENABLE :          |
+|                                                 Enable the timer interrupt |
+|                                                 APCI1710_DISABLE :         |
+|                                                 Disable the timer interrupt|
+i_ReturnValue=insn->n;
+       b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);
+       b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);
+       b_ActionType      = (BYTE) data[0]; // enable disable
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: Timer selection wrong                               |
+|                    -4: The module is not a TIMER module                    |
+|                    -5: Timer not initialised see function                  |
+|                        "i_APCI1710_InitTimer"                              |
+|                    -6: Interrupt parameter is wrong                        |
+|                    -7: Interrupt function not initialised.                 |
+|                        See function "i_APCI1710_SetBoardIntRoutineX"       |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_DummyRead;
+       BYTE b_ModulNbr;
+       BYTE b_TimerNbr;
+       BYTE b_ActionType;
+       BYTE b_InterruptEnable;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+       b_ActionType = (BYTE) data[0];  // enable disable
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if 82X54 timer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+             /*************************/
+                       /* Test the timer number */
+             /*************************/
+
+                       if (b_TimerNbr <= 2) {
+                /*****************************/
+                               /* Test if timer initialised */
+                /*****************************/
+
+                               if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_82X54ModuleInfo.
+                                       s_82X54TimerInfo[b_TimerNbr].
+                                       b_82X54Init == 1) {
+
+                                       switch (b_ActionType) {
+                                       case APCI1710_ENABLE:
+
+                                               b_InterruptEnable =
+                                                       (BYTE) data[1];
+                   /********************************/
+                                               /* Test the interrupt selection */
+                   /********************************/
+
+                                               if ((b_InterruptEnable ==
+                                                               APCI1710_ENABLE)
+                                                       || (b_InterruptEnable ==
+                                                               APCI1710_DISABLE))
+                                               {
+                                                       if (b_InterruptEnable ==
+                                                               APCI1710_ENABLE)
+                                                       {
+
+                                                               dw_DummyRead =
+                                                                       inl
+                                                                       (devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 12 +
+                                                                       (b_TimerNbr
+                                                                               *
+                                                                               4)
+                                                                       +
+                                                                       (64 * b_ModulNbr));
+
+                            /************************/
+                                                               /* Enable the interrupt */
+                            /************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       s_82X54TimerInfo
+                                                                       [b_TimerNbr].
+                                                                       dw_ConfigurationWord
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       s_82X54TimerInfo
+                                                                       [b_TimerNbr].
+                                                                       dw_ConfigurationWord
+                                                                       | 0x8;
+
+                                                               outl(devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       s_82X54TimerInfo
+                                                                       [b_TimerNbr].
+                                                                       dw_ConfigurationWord,
+                                                                       devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 32 +
+                                                                       (b_TimerNbr
+                                                                               *
+                                                                               4)
+                                                                       +
+                                                                       (64 * b_ModulNbr));
+                                                               devpriv->tsk_Current = current; // Save the current process task structure
+
+                                                       }       // if (b_InterruptEnable == APCI1710_ENABLE)
+                                                       else {
+                         /*************************/
+                                                               /* Disable the interrupt */
+                         /*************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       s_82X54TimerInfo
+                                                                       [b_TimerNbr].
+                                                                       dw_ConfigurationWord
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       s_82X54TimerInfo
+                                                                       [b_TimerNbr].
+                                                                       dw_ConfigurationWord
+                                                                       & 0xF7;
+
+                                                               outl(devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       s_82X54TimerInfo
+                                                                       [b_TimerNbr].
+                                                                       dw_ConfigurationWord,
+                                                                       devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 32 +
+                                                                       (b_TimerNbr
+                                                                               *
+                                                                               4)
+                                                                       +
+                                                                       (64 * b_ModulNbr));
+
+                         /***************************/
+                                                               /* Save the interrupt flag */
+                         /***************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       b_InterruptMask
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       b_InterruptMask
+                                                                       & (0xFF
+                                                                       -
+                                                                       (1 << b_TimerNbr));
+                                                       }       // if (b_InterruptEnable == APCI1710_ENABLE)
+
+                      /***********************/
+                                                       /* Test if error occur */
+                      /***********************/
+
+                                                       if (i_ReturnValue >= 0) {
+                         /***************************/
+                                                               /* Save the interrupt flag */
+                         /***************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       b_InterruptMask
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       b_InterruptMask
+                                                                       | ((1 & b_InterruptEnable) << b_TimerNbr);
+
+                         /********************/
+                                                               /* Enable the timer */
+                         /********************/
+
+                                                               outl(1, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+                                                       }
+                                               } else {
+                      /********************************/
+                                                       /* Interrupt parameter is wrong */
+                      /********************************/
+
+                                                       DPRINTK("\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                               break;
+                                       case APCI1710_DISABLE:
+                       /***************************/
+                                               /* Test the interrupt flag */
+                   /***************************/
+
+                                               if (((devpriv->s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_82X54ModuleInfo.
+                                                                       b_InterruptMask
+                                                                       >>
+                                                                       b_TimerNbr)
+                                                               & 1) == 1) {
+                      /*************************/
+                                                       /* Disable the interrupt */
+                      /*************************/
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_82X54ModuleInfo.
+                                                               s_82X54TimerInfo
+                                                               [b_TimerNbr].
+                                                               dw_ConfigurationWord
+                                                               =
+                                                               devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_82X54ModuleInfo.
+                                                               s_82X54TimerInfo
+                                                               [b_TimerNbr].
+                                                               dw_ConfigurationWord
+                                                               & 0xF7;
+
+                                                       outl(devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_82X54ModuleInfo.
+                                                               s_82X54TimerInfo
+                                                               [b_TimerNbr].
+                                                               dw_ConfigurationWord,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               32 +
+                                                               (b_TimerNbr *
+                                                                       4) +
+                                                               (64 * b_ModulNbr));
+
+                      /***************************/
+                                                       /* Save the interrupt flag */
+                      /***************************/
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_82X54ModuleInfo.
+                                                               b_InterruptMask
+                                                               =
+                                                               devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_82X54ModuleInfo.
+                                                               b_InterruptMask
+                                                               & (0xFF -
+                                                               (1 << b_TimerNbr));
+                                               }
+
+                   /*********************/
+                                               /* Disable the timer */
+                   /*********************/
+
+                                               outl(0, devpriv->s_BoardInfos.
+                                                       ui_Address + 44 +
+                                                       (b_TimerNbr * 4) +
+                                                       (64 * b_ModulNbr));
+                                               break;
+                                       }       // Switch end
+                               } else {
+                   /**************************************/
+                                       /* Timer not initialised see function */
+                   /**************************************/
+
+                                       DPRINTK("Timer not initialised see function\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*************************/
+                               /* Timer selection wrong */
+                /*************************/
+
+                               DPRINTK("Timer selection wrong\n");
+                               i_ReturnValue = -3;
+                       }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+               } else {
+             /************************************/
+                       /* The module is not a TIMER module */
+             /************************************/
+
+                       DPRINTK("The module is not a TIMER module\n");
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_ReadAllTimerValue                 |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        PULONG_ pul_TimerValueArray)
+INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)        |
++----------------------------------------------------------------------------+
+| Task              : Return the all timer values from selected timer        |
+|                     module (b_ModulNbr).                                   |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
+|                                                 APCI-1710                  |
+|                     BYTE_   b_ModulNbr        : Selected module number     |
+|                                                 (0 to 3)                   |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_TimerValueArray : Timer value array.       |
+|                           Element 0 contain the timer 0 value.             |
+|                           Element 1 contain the timer 1 value.             |
+|                           Element 2 contain the timer 2 value.             |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: The module is not a TIMER module                    |
+|                    -4: Timer 0 not initialised see function                |
+|                        "i_APCI1710_InitTimer"                              |
+|                    -5: Timer 1 not initialised see function                |
+|                        "i_APCI1710_InitTimer"                              |
+|                    -6: Timer 2 not initialised see function                |
+|                        "i_APCI1710_InitTimer"                              |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadAllTimerValue(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       BYTE b_ModulNbr, b_ReadType;
+       PULONG pul_TimerValueArray;
+
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_ReadType = CR_CHAN(insn->chanspec);
+       pul_TimerValueArray = (PULONG) data;
+       i_ReturnValue = insn->n;
+
+       switch (b_ReadType) {
+       case APCI1710_TIMER_READINTERRUPT:
+
+               data[0] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].b_OldModuleMask;
+               data[1] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+               data[2] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+                            /**************************/
+               /* Increment the read FIFO */
+                            /***************************/
+
+               devpriv->
+                       s_InterruptParameters.
+                       ui_Read = (devpriv->
+                       s_InterruptParameters.
+                       ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+               break;
+
+       case APCI1710_TIMER_READALLTIMER:
+       /**************************/
+               /* Test the module number */
+       /**************************/
+
+               if (b_ModulNbr < 4) {
+          /***********************/
+                       /* Test if 82X54 timer */
+          /***********************/
+
+                       if ((devpriv->s_BoardInfos.
+                                       dw_MolduleConfiguration[b_ModulNbr] &
+                                       0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+             /********************************/
+                               /* Test if timer 0 iniutialised */
+             /********************************/
+
+                               if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_82X54ModuleInfo.
+                                       s_82X54TimerInfo[0].b_82X54Init == 1) {
+                /********************************/
+                                       /* Test if timer 1 iniutialised */
+                /********************************/
+
+                                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_82X54ModuleInfo.
+                                               s_82X54TimerInfo[1].
+                                               b_82X54Init == 1) {
+                   /********************************/
+                                               /* Test if timer 2 iniutialised */
+                   /********************************/
+
+                                               if (devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_82X54ModuleInfo.
+                                                       s_82X54TimerInfo[2].
+                                                       b_82X54Init == 1) {
+                      /*********************/
+                                                       /* Latch all counter */
+                      /*********************/
+
+                                                       outl(0x17,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               12 +
+                                                               (64 * b_ModulNbr));
+
+                      /**************************/
+                                                       /* Read the timer 0 value */
+                      /**************************/
+
+                                                       pul_TimerValueArray[0] =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address + 0 +
+                                                               (64 * b_ModulNbr));
+
+                      /**************************/
+                                                       /* Read the timer 1 value */
+                      /**************************/
+
+                                                       pul_TimerValueArray[1] =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address + 4 +
+                                                               (64 * b_ModulNbr));
+
+                      /**************************/
+                                                       /* Read the timer 2 value */
+                      /**************************/
+
+                                                       pul_TimerValueArray[2] =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address + 8 +
+                                                               (64 * b_ModulNbr));
+                                               } else {
+                      /****************************************/
+                                                       /* Timer 2 not initialised see function */
+                      /****************************************/
+
+                                                       DPRINTK("Timer 2 not initialised see function\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       } else {
+                   /****************************************/
+                                               /* Timer 1 not initialised see function */
+                   /****************************************/
+
+                                               DPRINTK("Timer 1 not initialised see function\n");
+                                               i_ReturnValue = -5;
+                                       }
+                               } else {
+                /****************************************/
+                                       /* Timer 0 not initialised see function */
+                /****************************************/
+
+                                       DPRINTK("Timer 0 not initialised see function\n");
+                                       i_ReturnValue = -4;
+                               }
+                       } else {
+             /************************************/
+                               /* The module is not a TIMER module */
+             /************************************/
+
+                               DPRINTK("The module is not a TIMER module\n");
+                               i_ReturnValue = -3;
+                       }
+               } else {
+          /***********************/
+                       /* Module number error */
+          /***********************/
+
+                       DPRINTK("Module number error\n");
+                       i_ReturnValue = -2;
+               }
+
+       }                       // End of Switch
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT i_APCI1710_InsnBitsTimer(comedi_device *dev,
+comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                   |
++----------------------------------------------------------------------------+
+| Task              : Read write functions for Timer                                          |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_BitsType;
+       INT i_ReturnValue = 0;
+       b_BitsType = data[0];
+
+       printk("\n82X54");
+
+       switch (b_BitsType) {
+       case APCI1710_TIMER_READVALUE:
+               i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) CR_CHAN(insn->chanspec), (PULONG) & data[0]);
+               break;
+
+       case APCI1710_TIMER_GETOUTPUTLEVEL:
+               i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) CR_CHAN(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_TIMER_GETPROGRESSSTATUS:
+               i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) CR_CHAN(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_TIMER_WRITEVALUE:
+               i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) CR_CHAN(insn->chanspec), (ULONG) data[1]);
+
+               break;
+
+       default:
+               printk("Bits Config Parameter Wrong\n");
+               i_ReturnValue = -1;
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_ReadTimerValue                    |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_TimerNbr,               |
+|                                        PULONG_ pul_TimerValue)             |
++----------------------------------------------------------------------------+
+| Task              : Return the timer value from selected digital timer     |
+|                     (b_TimerNbr) from selected timer  module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
+|                                                 APCI-1710                  |
+|                     BYTE_   b_ModulNbr        : Selected module number     |
+|                                                 (0 to 3)                   |
+|                     BYTE_   b_TimerNbr        : Timer number to read       |
+|                                                 (0 to 2)                   |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_TimerValue    : Timer value                |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: Timer selection wrong                               |
+|                    -4: The module is not a TIMER module                    |
+|                    -5: Timer not initialised see function                  |
+|                        "i_APCI1710_InitTimer"                              |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadTimerValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, PULONG pul_TimerValue)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if 82X54 timer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+             /*************************/
+                       /* Test the timer number */
+             /*************************/
+
+                       if (b_TimerNbr <= 2) {
+                /*****************************/
+                               /* Test if timer initialised */
+                /*****************************/
+
+                               if (devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_82X54ModuleInfo.
+                                       s_82X54TimerInfo[b_TimerNbr].
+                                       b_82X54Init == 1) {
+                   /*************************/
+                                       /* Latch the timer value */
+                   /*************************/
+
+                                       outl((2 << b_TimerNbr) | 0xD0,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 12 +
+                                               (64 * b_ModulNbr));
+
+                   /**************************/
+                                       /* Read the counter value */
+                   /**************************/
+
+                                       *pul_TimerValue =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + (b_TimerNbr * 4) +
+                                               (64 * b_ModulNbr));
+                               } else {
+                   /**************************************/
+                                       /* Timer not initialised see function */
+                   /**************************************/
+                                       DPRINTK("Timer not initialised see function\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*************************/
+                               /* Timer selection wrong */
+                /*************************/
+                               DPRINTK("Timer selection wrong\n");
+                               i_ReturnValue = -3;
+                       }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+               } else {
+             /************************************/
+                       /* The module is not a TIMER module */
+             /************************************/
+                       DPRINTK("The module is not a TIMER module\n");
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+       /*
+          +----------------------------------------------------------------------------+
+          | Function Name     : _INT_     i_APCI1710_GetTimerOutputLevel               |
+          |                                       (BYTE_     b_BoardHandle,            |
+          |                                        BYTE_     b_ModulNbr,               |
+          |                                        BYTE_     b_TimerNbr,               |
+          |                                        PBYTE_   pb_OutputLevel)            |
+          +----------------------------------------------------------------------------+
+          | Task              : Return the output signal level (pb_OutputLevel) from   |
+          |                     selected digital timer (b_TimerNbr) from selected timer|
+          |                     module (b_ModulNbr).                                   |
+          +----------------------------------------------------------------------------+
+          | Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
+          |                                                 APCI-1710                  |
+          |                     BYTE_   b_ModulNbr        : Selected module number     |
+          |                                                 (0 to 3)                   |
+          |                     BYTE_   b_TimerNbr        : Timer number to test       |
+          |                                                 (0 to 2)                   |
+          +----------------------------------------------------------------------------+
+          | Output Parameters : PBYTE_ pb_OutputLevel     : Output signal level        |
+          |                                                 0 : The output is low      |
+          |                                                 1 : The output is high     |
+          +----------------------------------------------------------------------------+
+          | Return Value      : 0: No error                                            |
+          |                    -1: The handle parameter of the board is wrong          |
+          |                    -2: Module selection wrong                              |
+          |                    -3: Timer selection wrong                               |
+          |                    -4: The module is not a TIMER module                    |
+          |                    -5: Timer not initialised see function                  |
+          |                        "i_APCI1710_InitTimer"                              |
+          +----------------------------------------------------------------------------+
+        */
+
+INT i_APCI1710_GetTimerOutputLevel(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, PBYTE pb_OutputLevel)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_TimerStatus;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if 82X54 timer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+             /*************************/
+                       /* Test the timer number */
+             /*************************/
+
+                       if (b_TimerNbr <= 2) {
+                /*****************************/
+                               /* Test if timer initialised */
+                /*****************************/
+
+                               if (devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_82X54ModuleInfo.
+                                       s_82X54TimerInfo[b_TimerNbr].
+                                       b_82X54Init == 1) {
+                   /*************************/
+                                       /* Latch the timer value */
+                   /*************************/
+
+                                       outl((2 << b_TimerNbr) | 0xE0,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 12 +
+                                               (64 * b_ModulNbr));
+
+                   /*************************/
+                                       /* Read the timer status */
+                   /*************************/
+
+                                       dw_TimerStatus =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 16 +
+                                               (b_TimerNbr * 4) +
+                                               (64 * b_ModulNbr));
+
+                                       *pb_OutputLevel =
+                                               (BYTE) (((dw_TimerStatus >> 7) &
+                                                       1) ^ devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_82X54ModuleInfo.
+                                               s_82X54TimerInfo[b_TimerNbr].
+                                               b_OutputLevel);
+                               } else {
+                   /**************************************/
+                                       /* Timer not initialised see function */
+                   /**************************************/
+                                       DPRINTK("Timer not initialised see function\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*************************/
+                               /* Timer selection wrong */
+                /*************************/
+                               DPRINTK("Timer selection wrong\n");
+                               i_ReturnValue = -3;
+                       }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+               } else {
+             /************************************/
+                       /* The module is not a TIMER module */
+             /************************************/
+                       DPRINTK("The module is not a TIMER module\n");
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_GetTimerProgressStatus            |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_TimerNbr,               |
+|                                        PBYTE_   pb_TimerStatus)            |
++----------------------------------------------------------------------------+
+| Task              : Return the progress status (pb_TimerStatus) from       |
+|                     selected digital timer (b_TimerNbr) from selected timer|
+|                     module (b_ModulNbr).                                   |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
+|                                                 APCI-1710                  |
+|                     BYTE_   b_ModulNbr        : Selected module number     |
+|                                                 (0 to 3)                   |
+|                     BYTE_   b_TimerNbr        : Timer number to test       |
+|                                                 (0 to 2)                   |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_TimerStatus     : Output signal level        |
+|                                                 0 : Timer not in progress  |
+|                                                 1 : Timer in progress      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: Timer selection wrong                               |
+|                    -4: The module is not a TIMER module                    |
+|                    -5: Timer not initialised see function                  |
+|                        "i_APCI1710_InitTimer"                              |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetTimerProgressStatus(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, PBYTE pb_TimerStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_TimerStatus;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if 82X54 timer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+             /*************************/
+                       /* Test the timer number */
+             /*************************/
+
+                       if (b_TimerNbr <= 2) {
+                /*****************************/
+                               /* Test if timer initialised */
+                /*****************************/
+
+                               if (devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_82X54ModuleInfo.
+                                       s_82X54TimerInfo[b_TimerNbr].
+                                       b_82X54Init == 1) {
+                   /*************************/
+                                       /* Latch the timer value */
+                   /*************************/
+
+                                       outl((2 << b_TimerNbr) | 0xE0,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 12 +
+                                               (64 * b_ModulNbr));
+
+                   /*************************/
+                                       /* Read the timer status */
+                   /*************************/
+
+                                       dw_TimerStatus =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 16 +
+                                               (b_TimerNbr * 4) +
+                                               (64 * b_ModulNbr));
+
+                                       *pb_TimerStatus =
+                                               (BYTE) ((dw_TimerStatus) >> 8) &
+                                               1;
+                                       printk("ProgressStatus : %d",
+                                               *pb_TimerStatus);
+                               } else {
+                   /**************************************/
+                                       /* Timer not initialised see function */
+                   /**************************************/
+
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*************************/
+                               /* Timer selection wrong */
+                /*************************/
+
+                               i_ReturnValue = -3;
+                       }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+               } else {
+             /************************************/
+                       /* The module is not a TIMER module */
+             /************************************/
+
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_WriteTimerValue                   |
+|                                       (BYTE_   b_BoardHandle,              |
+|                                        BYTE_   b_ModulNbr,                 |
+|                                        BYTE_   b_TimerNbr,                 |
+|                                        ULONG_ ul_WriteValue)               |
++----------------------------------------------------------------------------+
+| Task              : Write the value (ul_WriteValue) into the selected timer|
+|                     (b_TimerNbr) from selected timer module (b_ModulNbr).  |
+|                     The action in depend of the time mode selection.       |
+|                     See timer mode description table.                      |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |
+|                                                 APCI-1710                  |
+|                     BYTE_   b_ModulNbr        : Selected module number     |
+|                                                 (0 to 3)                   |
+|                     BYTE_   b_TimerNbr        : Timer number to write      |
+|                                                 (0 to 2)                   |
+|                     ULONG_ ul_WriteValue      : Value to write             |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: Timer selection wrong                               |
+|                    -4: The module is not a TIMER module                    |
+|                    -5: Timer not initialised see function                  |
+|                        "i_APCI1710_InitTimer"                              |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_WriteTimerValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, ULONG ul_WriteValue)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if 82X54 timer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+             /*************************/
+                       /* Test the timer number */
+             /*************************/
+
+                       if (b_TimerNbr <= 2) {
+                /*****************************/
+                               /* Test if timer initialised */
+                /*****************************/
+
+                               if (devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_82X54ModuleInfo.
+                                       s_82X54TimerInfo[b_TimerNbr].
+                                       b_82X54Init == 1) {
+                   /*******************/
+                                       /* Write the value */
+                   /*******************/
+
+                                       outl(ul_WriteValue,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + (b_TimerNbr * 4) +
+                                               (64 * b_ModulNbr));
+                               } else {
+                   /**************************************/
+                                       /* Timer not initialised see function */
+                   /**************************************/
+                                       DPRINTK("Timer not initialised see function\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*************************/
+                               /* Timer selection wrong */
+                /*************************/
+                               DPRINTK("Timer selection wrong\n");
+                               i_ReturnValue = -3;
+                       }       // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+               } else {
+             /************************************/
+                       /* The module is not a TIMER module */
+             /************************************/
+                       DPRINTK("The module is not a TIMER module\n");
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
new file mode 100644 (file)
index 0000000..18609f4
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_PCI_BUS_CLOCK                                         0
+#define APCI1710_FRONT_CONNECTOR_INPUT                         1
+#define APCI1710_TIMER_READVALUE                               0
+#define APCI1710_TIMER_GETOUTPUTLEVEL                  1
+#define APCI1710_TIMER_GETPROGRESSSTATUS               2
+#define APCI1710_TIMER_WRITEVALUE                              3
+
+#define APCI1710_TIMER_READINTERRUPT            1
+#define APCI1710_TIMER_READALLTIMER             2
+
+// BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+#ifndef APCI1710_10MHZ
+#define APCI1710_10MHZ           10
+#endif
+// END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+
+/*
++----------------------------------------------------------------------------+
+|                       82X54 TIMER INISIALISATION FUNCTION                  |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+/*
++----------------------------------------------------------------------------+
+|                       82X54 READ FUNCTION                                  |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadAllTimerValue(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnBitsTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+/*
++----------------------------------------------------------------------------+
+|                       82X54 READ & WRITE FUNCTION                          |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_ReadTimerValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, PULONG pul_TimerValue);
+
+INT i_APCI1710_GetTimerOutputLevel(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, PBYTE pb_OutputLevel);
+
+INT i_APCI1710_GetTimerProgressStatus(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, PBYTE pb_TimerStatus);
+
+/*
++----------------------------------------------------------------------------+
+|                       82X54 WRITE FUNCTION                                 |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_WriteTimerValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_TimerNbr, ULONG ul_WriteValue);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
new file mode 100644 (file)
index 0000000..01100ff
--- /dev/null
@@ -0,0 +1,2032 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : CHRONO.C        | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 chronometer module                          |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 29/06/98 | S. Weber  | Digital input / output implementation          |
+  |----------|-----------|------------------------------------------------|
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "APCI1710_Chrono.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_InitChrono                        |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_ChronoMode,             |
+|                                        BYTE_     b_PCIInputClock,          |
+|                                        BYTE_     b_TimingUnit,             |
+|                                        ULONG_   ul_TimingInterval,         |
+|                                        PULONG_ pul_RealTimingInterval)
+
++----------------------------------------------------------------------------+
+| Task              : Configure the chronometer operating mode (b_ChronoMode)|
+|                     from selected module (b_ModulNbr).                     |
+|                     The ul_TimingInterval and ul_TimingUnit determine the  |
+|                     timing base for the measurement.                       |
+|                     The pul_RealTimingInterval return the real timing      |
+|                     value. You must calling this function be for you call  |
+|                     any other function witch access of the chronometer.    |
+|                                                                            |
+|                     Witch this functionality from the APCI-1710 you have   |
+|                     the possibility to measure the timing witch two event. |
+|                                                                            |
+|                     The mode 0 and 1 is appropriate for period measurement.|
+|                     The mode 2 and 3 is appropriate for frequent           |
+|                     measurement.                                           |
+|                     The mode 4 to 7 is appropriate for measuring the timing|
+|                     between  two event.                                    |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle    : Handle of board APCI-1710   |
+| BYTE_   b_ModulNbr  CR_AREF(insn->chanspec)  : Module number to configure  |
+|                                                (0 to 3)                    |
+| BYTE_   b_ChronoMode                         data[0]    : Chronometer action mode     |
+|                                                (0 to 7).                   |
+| BYTE_   b_PCIInputClock                      data[1] : Selection from PCI bus clock|
+|                                                - APCI1710_30MHZ :          |
+|                                                  The PC have a PCI bus     |
+|                                                  clock from 30 MHz         |
+|                                                - APCI1710_33MHZ :          |
+|                                                  The PC have a PCI bus     |
+|                                                  clock from 33 MHz         |
+|                                                - APCI1710_40MHZ            |
+|                                                  The APCI-1710 have a      |
+|                                                  integrated 40Mhz          |
+|                                                  quartz.                   |
+|               BYTE_   b_TimingUnit   data[2]    : Base timing unity (0 to 4) |
+|                                                 0 : ns                     |
+|                                                 1 : Âµs                     |
+|                                                 2 : ms                     |
+|                                                 3 : s                      |
+|                                                 4 : mn                     |
+|         ULONG_ ul_TimingInterval : data[3]    Base timing value.          |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pul_RealTimingInterval : Real  base timing    |
+|                                                       value.
+|                     data[0]
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: Chronometer mode selection is wrong                |
+|                     -5: The selected PCI input clock is wrong              |
+|                     -6: Timing unity selection is wrong                    |
+|                     -7: Base timing selection is wrong                     |
+|                     -8: You can not used the 40MHz clock selection wich    |
+|                         this board                                         |
+|                     -9: You can not used the 40MHz clock selection wich    |
+|                         this CHRONOS version                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitChrono(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       ULONG ul_TimerValue = 0;
+       ULONG ul_TimingInterval = 0;
+       ULONG ul_RealTimingInterval = 0;
+       double d_RealTimingInterval = 0;
+       DWORD dw_ModeArray[8] =
+               { 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 };
+       BYTE b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit;
+
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_ChronoMode = (BYTE) data[0];
+       b_PCIInputClock = (BYTE) data[1];
+       b_TimingUnit = (BYTE) data[2];
+       ul_TimingInterval = (ULONG) data[3];
+       i_ReturnValue = insn->n;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if chronometer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+             /*****************************/
+                       /* Test the chronometer mode */
+             /*****************************/
+
+                       if (b_ChronoMode <= 7) {
+                /**************************/
+                               /* Test the PCI bus clock */
+                /**************************/
+
+                               if ((b_PCIInputClock == APCI1710_30MHZ) ||
+                                       (b_PCIInputClock == APCI1710_33MHZ) ||
+                                       (b_PCIInputClock == APCI1710_40MHZ)) {
+                   /*************************/
+                                       /* Test the timing unity */
+                   /*************************/
+
+                                       if (b_TimingUnit <= 4) {
+                      /**********************************/
+                                               /* Test the base timing selection */
+                      /**********************************/
+
+                                               if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 66) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165576UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 60) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150240UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 50) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374182UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 1UL))) {
+                         /**************************/
+                                                       /* Test the board version */
+                         /**************************/
+
+                                                       if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) {
+                            /************************/
+                                                               /* Test the TOR version */
+                            /************************/
+
+                                                               if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || (b_PCIInputClock != APCI1710_40MHZ)) {
+                                                                       fpu_begin
+                                                                               ();
+
+                               /****************************************/
+                                                                       /* Calculate the timer 0 division fator */
+                               /****************************************/
+
+                                                                       switch (b_TimingUnit) {
+                                  /******/
+                                                                               /* ns */
+                                  /******/
+
+                                                                       case 0:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimingInterval
+                                                                                       *
+                                                                                       (0.001 * b_PCIInputClock));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_TimingInterval * (0.001 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               ul_RealTimingInterval
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimerValue
+                                                                                       /
+                                                                                       (0.001 * (double)b_PCIInputClock));
+                                                                               d_RealTimingInterval
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_TimerValue
+                                                                                       /
+                                                                                       (0.001
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_PCIInputClock);
+
+                                                                               if ((double)((double)ul_TimerValue / (0.001 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               ul_RealTimingInterval
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_TimingInterval
+                                                                                       =
+                                                                                       ul_TimingInterval
+                                                                                       -
+                                                                                       1;
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       -
+                                                                                       2;
+                                                                               if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_TimerValue)
+                                                                                               *
+                                                                                               0.99392);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* Ã¦s */
+                                  /******/
+
+                                                                       case 1:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimingInterval
+                                                                                       *
+                                                                                       (1.0 * b_PCIInputClock));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_TimingInterval * (1.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               ul_RealTimingInterval
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimerValue
+                                                                                       /
+                                                                                       (1.0 * (double)b_PCIInputClock));
+                                                                               d_RealTimingInterval
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_TimerValue
+                                                                                       /
+                                                                                       (
+                                                                                       (double)
+                                                                                       1.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_PCIInputClock);
+
+                                                                               if ((double)((double)ul_TimerValue / (1.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               ul_RealTimingInterval
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_TimingInterval
+                                                                                       =
+                                                                                       ul_TimingInterval
+                                                                                       -
+                                                                                       1;
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       -
+                                                                                       2;
+                                                                               if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_TimerValue)
+                                                                                               *
+                                                                                               0.99392);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* ms */
+                                  /******/
+
+                                                                       case 2:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimingInterval
+                                                                                       *
+                                                                                       (1000
+                                                                                       *
+                                                                                       b_PCIInputClock);
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_TimingInterval * (1000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               ul_RealTimingInterval
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimerValue
+                                                                                       /
+                                                                                       (1000.0 * (double)b_PCIInputClock));
+                                                                               d_RealTimingInterval
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_TimerValue
+                                                                                       /
+                                                                                       (1000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_PCIInputClock);
+
+                                                                               if ((double)((double)ul_TimerValue / (1000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               ul_RealTimingInterval
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_TimingInterval
+                                                                                       =
+                                                                                       ul_TimingInterval
+                                                                                       -
+                                                                                       1;
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       -
+                                                                                       2;
+                                                                               if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_TimerValue)
+                                                                                               *
+                                                                                               0.99392);
+                                                                               }
+
+                                                                               break;
+
+                                  /*****/
+                                                                               /* s */
+                                  /*****/
+
+                                                                       case 3:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimingInterval
+                                                                                       *
+                                                                                       (1000000.0
+                                                                                               *
+                                                                                               b_PCIInputClock));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_TimingInterval * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               ul_RealTimingInterval
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimerValue
+                                                                                       /
+                                                                                       (1000000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_PCIInputClock));
+                                                                               d_RealTimingInterval
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_TimerValue
+                                                                                       /
+                                                                                       (1000000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_PCIInputClock);
+
+                                                                               if ((double)((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               ul_RealTimingInterval
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_TimingInterval
+                                                                                       =
+                                                                                       ul_TimingInterval
+                                                                                       -
+                                                                                       1;
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       -
+                                                                                       2;
+                                                                               if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_TimerValue)
+                                                                                               *
+                                                                                               0.99392);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* mn */
+                                  /******/
+
+                                                                       case 4:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (ul_TimingInterval
+                                                                                               *
+                                                                                               60)
+                                                                                       *
+                                                                                       (1000000.0
+                                                                                               *
+                                                                                               b_PCIInputClock));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)(ul_TimingInterval * 60.0) * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               ul_RealTimingInterval
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_TimerValue
+                                                                                       /
+                                                                                       (1000000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_PCIInputClock))
+                                                                                       /
+                                                                                       60;
+                                                                               d_RealTimingInterval
+                                                                                       =
+                                                                                       (
+                                                                                       (double)
+                                                                                       ul_TimerValue
+                                                                                       /
+                                                                                       (0.001 * (double)b_PCIInputClock)) / 60.0;
+
+                                                                               if ((double)(((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               ul_RealTimingInterval
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_TimingInterval
+                                                                                       =
+                                                                                       ul_TimingInterval
+                                                                                       -
+                                                                                       1;
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       -
+                                                                                       2;
+                                                                               if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_TimerValue)
+                                                                                               *
+                                                                                               0.99392);
+                                                                               }
+
+                                                                               break;
+                                                                       }
+
+                                                                       fpu_end();
+
+                               /****************************/
+                                                                       /* Save the PCI input clock */
+                               /****************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_ChronoModuleInfo.
+                                                                               b_PCIInputClock
+                                                                               =
+                                                                               b_PCIInputClock;
+
+                               /*************************/
+                                                                       /* Save the timing unity */
+                               /*************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_ChronoModuleInfo.
+                                                                               b_TimingUnit
+                                                                               =
+                                                                               b_TimingUnit;
+
+                               /************************/
+                                                                       /* Save the base timing */
+                               /************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_ChronoModuleInfo.
+                                                                               d_TimingInterval
+                                                                               =
+                                                                               d_RealTimingInterval;
+
+                               /****************************/
+                                                                       /* Set the chronometer mode */
+                               /****************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_ChronoModuleInfo.
+                                                                               dw_ConfigReg
+                                                                               =
+                                                                               dw_ModeArray
+                                                                               [b_ChronoMode];
+
+                               /***********************/
+                                                                       /* Test if 40 MHz used */
+                               /***********************/
+
+                                                                       if (b_PCIInputClock == APCI1710_40MHZ) {
+                                                                               devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_ChronoModuleInfo.
+                                                                                       dw_ConfigReg
+                                                                                       =
+                                                                                       devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_ChronoModuleInfo.
+                                                                                       dw_ConfigReg
+                                                                                       |
+                                                                                       0x80;
+                                                                       }
+
+                                                                       outl(devpriv->s_ModuleInfo[b_ModulNbr].s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr));
+
+                               /***********************/
+                                                                       /* Write timer 0 value */
+                               /***********************/
+
+                                                                       outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
+
+                               /*********************/
+                                                                       /* Chronometer init. */
+                               /*********************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_ChronoModuleInfo.
+                                                                               b_ChronoInit
+                                                                               =
+                                                                               1;
+                                                               } else {
+                               /***********************************************/
+                                                                       /* TOR version error for 40MHz clock selection */
+                               /***********************************************/
+
+                                                                       DPRINTK("TOR version error for 40MHz clock selection\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -9;
+                                                               }
+                                                       } else {
+                            /**************************************************************/
+                                                               /* You can not used the 40MHz clock selection wich this board */
+                            /**************************************************************/
+
+                                                               DPRINTK("You can not used the 40MHz clock selection wich this board\n");
+                                                               i_ReturnValue =
+                                                                       -8;
+                                                       }
+                                               } else {
+                         /**********************************/
+                                                       /* Base timing selection is wrong */
+                         /**********************************/
+
+                                                       DPRINTK("Base timing selection is wrong\n");
+                                                       i_ReturnValue = -7;
+                                               }
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                                       else {
+                      /***********************************/
+                                               /* Timing unity selection is wrong */
+                      /***********************************/
+
+                                               DPRINTK("Timing unity selection is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                               }       // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+                               else {
+                   /*****************************************/
+                                       /* The selected PCI input clock is wrong */
+                   /*****************************************/
+
+                                       DPRINTK("The selected PCI input clock is wrong\n");
+                                       i_ReturnValue = -5;
+                               }       // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+                       }       // if (b_ChronoMode >= 0 && b_ChronoMode <= 7)
+                       else {
+                /***************************************/
+                               /* Chronometer mode selection is wrong */
+                /***************************************/
+
+                               DPRINTK("Chronometer mode selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_ChronoMode >= 0 && b_ChronoMode <= 7)
+               } else {
+             /******************************************/
+                       /* The module is not a Chronometer module */
+             /******************************************/
+
+                       DPRINTK("The module is not a Chronometer module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+       data[0] = ul_RealTimingInterval;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_EnableChrono                          |
+|                                               (BYTE_ b_BoardHandle,        |
+|                                                BYTE_ b_ModulNbr,           |
+|                                                BYTE_ b_CycleMode,          |
+|                                                BYTE_ b_InterruptEnable)
+INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,
+comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                                           |
++----------------------------------------------------------------------------+
+| Task              : Enable the chronometer from selected module            |
+|                     (b_ModulNbr). You must calling the                     |
+|                     "i_APCI1710_InitChrono" function be for you call this  |
+|                     function.                                              |
+|                     If you enable the chronometer interrupt, the           |
+|                     chronometer generate a interrupt after the stop signal.|
+|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
+|                     Interrupt mask description chapter from this manual.   |
+|                     The b_CycleMode parameter determine if you will        |
+|                     measured a single or more cycle.
+
+|                                        Disable the chronometer from selected module           |
+|                     (b_ModulNbr). If you disable the chronometer after a   |
+|                     start signal occur and you restart the chronometer     |
+|                     witch the " i_APCI1710_EnableChrono" function, if no   |
+|                     stop signal occur this start signal is ignored.
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+|                     BYTE_ b_ModulNbr   CR_AREF(chanspec)  : Selected module number (0 to 3) |
+                                  data[0]  ENABle/Disable chrono
+|                     BYTE_ b_CycleMode    : Selected the chronometer        |
+|                                  data[1]           acquisition mode                |
+|                     BYTE_ b_InterruptEnable : Enable or disable the        |
+|                                   data[2]            chronometer interrupt.       |
+|                                               APCI1710_ENABLE:             |
+|                                               Enable the chronometer       |
+|                                               interrupt                    |
+|                                               APCI1710_DISABLE:            |
+|                                               Disable the chronometer      |
+|                                               interrupt                    |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
+|                     -5: Chronometer acquisition mode cycle is wrong        |
+|                     -6: Interrupt parameter is wrong                       |
+|                     -7: Interrupt function not initialised.                |
+|                         See function "i_APCI1710_SetBoardIntRoutineX"
+                      -8: data[0] wrong input    |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       BYTE b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_Action = (BYTE) data[0];
+       b_CycleMode = (BYTE) data[1];
+       b_InterruptEnable = (BYTE) data[2];
+       i_ReturnValue = insn->n;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if chronometer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+             /***********************************/
+                       /* Test if chronometer initialised */
+             /***********************************/
+
+                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_ChronoModuleInfo.b_ChronoInit == 1) {
+
+                               switch (b_Action) {
+
+                               case APCI1710_ENABLE:
+
+                /*********************************/
+                                       /* Test the cycle mode parameter */
+                /*********************************/
+
+                                       if ((b_CycleMode == APCI1710_SINGLE)
+                                               || (b_CycleMode ==
+                                                       APCI1710_CONTINUOUS)) {
+                   /***************************/
+                                               /* Test the interrupt flag */
+                   /***************************/
+
+                                               if ((b_InterruptEnable ==
+                                                               APCI1710_ENABLE)
+                                                       || (b_InterruptEnable ==
+                                                               APCI1710_DISABLE))
+                                               {
+
+                         /***************************/
+                                                       /* Save the interrupt flag */
+                         /***************************/
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_ChronoModuleInfo.
+                                                               b_InterruptMask
+                                                               =
+                                                               b_InterruptEnable;
+
+                         /***********************/
+                                                       /* Save the cycle mode */
+                         /***********************/
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_ChronoModuleInfo.
+                                                               b_CycleMode =
+                                                               b_CycleMode;
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_ChronoModuleInfo.
+                                                               dw_ConfigReg =
+                                                               (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_ChronoModuleInfo.
+                                                               dw_ConfigReg &
+                                                               0x8F) | ((1 &
+                                                                       b_InterruptEnable)
+                                                               << 5) | ((1 &
+                                                                       b_CycleMode)
+                                                               << 6) | 0x10;
+
+                         /*****************************/
+                                                       /* Test if interrupt enabled */
+                         /*****************************/
+
+                                                       if (b_InterruptEnable ==
+                                                               APCI1710_ENABLE)
+                                                       {
+                            /****************************/
+                                                               /* Clear the interrupt flag */
+                            /****************************/
+
+                                                               outl(devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_ChronoModuleInfo.
+                                                                       dw_ConfigReg,
+                                                                       devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 32 +
+                                                                       (64 * b_ModulNbr));
+                                                               devpriv->tsk_Current = current; // Save the current process task structure
+                                                       }
+
+                         /***********************************/
+                                                       /* Enable or disable the interrupt */
+                                                       /* Enable the chronometer          */
+                         /***********************************/
+
+                                                       outl(devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_ChronoModuleInfo.
+                                                               dw_ConfigReg,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               16 +
+                                                               (64 * b_ModulNbr));
+
+                         /*************************/
+                                                       /* Clear status register */
+                         /*************************/
+
+                                                       outl(0, devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               36 +
+                                                               (64 * b_ModulNbr));
+
+                                               }       // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+                                               else {
+                      /********************************/
+                                                       /* Interrupt parameter is wrong */
+                      /********************************/
+
+                                                       DPRINTK("Interrupt parameter is wrong\n");
+                                                       i_ReturnValue = -6;
+                                               }       // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+                                       }       // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+                                       else {
+                   /***********************************************/
+                                               /* Chronometer acquisition mode cycle is wrong */
+                   /***********************************************/
+
+                                               DPRINTK("Chronometer acquisition mode cycle is wrong\n");
+                                               i_ReturnValue = -5;
+                                       }       // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+                                       break;
+
+                               case APCI1710_DISABLE:
+
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_ChronoModuleInfo.
+                                               b_InterruptMask = 0;
+
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_ChronoModuleInfo.
+                                               dw_ConfigReg =
+                                               devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_ChronoModuleInfo.
+                                               dw_ConfigReg & 0x2F;
+
+                /***************************/
+                                       /* Disable the interrupt   */
+                                       /* Disable the chronometer */
+                /***************************/
+
+                                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_ChronoModuleInfo.dw_ConfigReg,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 16 +
+                                               (64 * b_ModulNbr));
+
+                /***************************/
+                                       /* Test if continuous mode */
+                /***************************/
+
+                                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_ChronoModuleInfo.
+                                               b_CycleMode ==
+                                               APCI1710_CONTINUOUS) {
+                   /*************************/
+                                               /* Clear status register */
+                   /*************************/
+
+                                               outl(0, devpriv->s_BoardInfos.
+                                                       ui_Address + 36 +
+                                                       (64 * b_ModulNbr));
+                                       }
+                                       break;
+
+                               default:
+                                       DPRINTK("Inputs wrong! Enable or Disable chrono\n");
+                                       i_ReturnValue = -8;
+                               }       // switch ENABLE/DISABLE
+                       } else {
+                /*******************************/
+                               /* Chronometer not initialised */
+                /*******************************/
+
+                               DPRINTK("Chronometer not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /******************************************/
+                       /* The module is not a Chronometer module */
+             /******************************************/
+
+                       DPRINTK("The module is not a Chronometer module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT       i_APCI1710_InsnReadChrono(comedi_device *dev,comedi_subdevice *s,
+comedi_insn *insn,lsampl_t *data)                   |
++----------------------------------------------------------------------------+
+| Task              : Read  functions for Timer                                     |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadChrono(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_ReadType;
+       INT i_ReturnValue = insn->n;
+
+       b_ReadType = CR_CHAN(insn->chanspec);
+
+       switch (b_ReadType) {
+       case APCI1710_CHRONO_PROGRESS_STATUS:
+               i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_CHRONO_READVALUE:
+               i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (UINT) insn->unused[0],
+                       (PBYTE) & data[0], (PULONG) & data[1]);
+               break;
+
+       case APCI1710_CHRONO_CONVERTVALUE:
+               i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (ULONG) insn->unused[0],
+                       (PULONG) & data[0],
+                       (PBYTE) & data[1],
+                       (PBYTE) & data[2],
+                       (PUINT) & data[3],
+                       (PUINT) & data[4], (PUINT) & data[5]);
+               break;
+
+       case APCI1710_CHRONO_READINTERRUPT:
+               printk("In Chrono Read Interrupt\n");
+
+               data[0] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].b_OldModuleMask;
+               data[1] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+               data[2] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+                            /**************************/
+               /* Increment the read FIFO */
+                            /***************************/
+
+               devpriv->
+                       s_InterruptParameters.
+                       ui_Read = (devpriv->
+                       s_InterruptParameters.
+                       ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+               break;
+
+       default:
+               printk("ReadType Parameter wrong\n");
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetChronoProgressStatus               |
+|                               (BYTE_    b_BoardHandle,                     |
+|                                BYTE_    b_ModulNbr,                        |
+|                                PBYTE_  pb_ChronoStatus)                    |
++----------------------------------------------------------------------------+
+| Task              : Return the chronometer status (pb_ChronoStatus) from   |
+|                     selected chronometer module (b_ModulNbr).              |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
+|                                                status.                     |
+|                                                0 : Measurement not started.|
+|                                                    No start signal occur.  |
+|                                                1 : Measurement started.    |
+|                                                    A start signal occur.   |
+|                                                2 : Measurement stopped.    |
+|                                                    A stop signal occur.    |
+|                                                    The measurement is      |
+|                                                    terminate.              |
+|                                                3: A overflow occur. You    |
+|                                                   must change the base     |
+|                                                   timing witch the         |
+|                                                   function                 |
+|                                                   "i_APCI1710_InitChrono"  |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetChronoProgressStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_ChronoStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if chronometer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+             /***********************************/
+                       /* Test if chronometer initialised */
+             /***********************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_ChronoModuleInfo.b_ChronoInit == 1) {
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 8 + (64 * b_ModulNbr));
+
+                /********************/
+                               /* Test if overflow */
+                /********************/
+
+                               if ((dw_Status & 8) == 8) {
+                   /******************/
+                                       /* Overflow occur */
+                   /******************/
+
+                                       *pb_ChronoStatus = 3;
+                               }       // if ((dw_Status & 8) == 8)
+                               else {
+                   /*******************************/
+                                       /* Test if measurement stopped */
+                   /*******************************/
+
+                                       if ((dw_Status & 2) == 2) {
+                      /***********************/
+                                               /* A stop signal occur */
+                      /***********************/
+
+                                               *pb_ChronoStatus = 2;
+                                       }       // if ((dw_Status & 2) == 2)
+                                       else {
+                      /*******************************/
+                                               /* Test if measurement started */
+                      /*******************************/
+
+                                               if ((dw_Status & 1) == 1) {
+                         /************************/
+                                                       /* A start signal occur */
+                         /************************/
+
+                                                       *pb_ChronoStatus = 1;
+                                               }       // if ((dw_Status & 1) == 1)
+                                               else {
+                         /***************************/
+                                                       /* Measurement not started */
+                         /***************************/
+
+                                                       *pb_ChronoStatus = 0;
+                                               }       // if ((dw_Status & 1) == 1)
+                                       }       // if ((dw_Status & 2) == 2)
+                               }       // if ((dw_Status & 8) == 8)
+                       } else {
+                /*******************************/
+                               /* Chronometer not initialised */
+                /*******************************/
+                               DPRINTK("Chronometer not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /******************************************/
+                       /* The module is not a Chronometer module */
+             /******************************************/
+                       DPRINTK("The module is not a Chronometer module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ReadChronoValue                       |
+|                               (BYTE_     b_BoardHandle,                    |
+|                                BYTE_     b_ModulNbr,                       |
+|                                UINT_    ui_TimeOut,                        |
+|                                PBYTE_   pb_ChronoStatus,                   |
+|                                PULONG_ pul_ChronoValue)                    |
++----------------------------------------------------------------------------+
+| Task              : Return the chronometer status (pb_ChronoStatus) and the|
+|                     timing value (pul_ChronoValue) after a stop signal     |
+|                     occur from selected chronometer module (b_ModulNbr).   |
+|                     This function are only avaible if you have disabled    |
+|                     the interrupt functionality. See function              |
+|                     "i_APCI1710_EnableChrono" and the Interrupt mask       |
+|                     description chapter.                                   |
+|                     You can test the chronometer status witch the          |
+|                     "i_APCI1710_GetChronoProgressStatus" function.         |
+|                                                                            |
+|                     The returned value from pul_ChronoValue parameter is   |
+|                     not real measured timing.                              |
+|                     You must used the "i_APCI1710_ConvertChronoValue"      |
+|                     function or make this operation for calculate the      |
+|                     timing:                                                |
+|                                                                            |
+|                     Timing = pul_ChronoValue * pul_RealTimingInterval.     |
+|                                                                            |
+|                     pul_RealTimingInterval is the returned parameter from  |
+|                     "i_APCI1710_InitChrono" function and the time unity is |
+|                     the b_TimingUnit from "i_APCI1710_InitChrono" function|
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pb_ChronoStatus : Return the chronometer      |
+|                                                status.                     |
+|                                                0 : Measurement not started.|
+|                                                    No start signal occur.  |
+|                                                1 : Measurement started.    |
+|                                                    A start signal occur.   |
+|                                                2 : Measurement stopped.    |
+|                                                    A stop signal occur.    |
+|                                                    The measurement is      |
+|                                                    terminate.              |
+|                                                3: A overflow occur. You    |
+|                                                   must change the base     |
+|                                                   timing witch the         |
+|                                                   function                 |
+|                                                   "i_APCI1710_InitChrono"  |
+|                     PULONG  pul_ChronoValue  : Chronometer timing value.   |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
+|                     -5: Timeout parameter is wrong (0 to 65535)            |
+|                     -6: Interrupt routine installed. You can not read      |
+|                         directly the chronometer measured timing.          |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadChronoValue(comedi_device * dev,
+       BYTE b_ModulNbr,
+       UINT ui_TimeOut, PBYTE pb_ChronoStatus, PULONG pul_ChronoValue)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+       DWORD dw_TimeOut = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if chronometer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+             /***********************************/
+                       /* Test if chronometer initialised */
+             /***********************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_ChronoModuleInfo.b_ChronoInit == 1) {
+                /*****************************/
+                               /* Test the timout parameter */
+                /*****************************/
+
+                               if ((ui_TimeOut >= 0)
+                                       && (ui_TimeOut <= 65535UL)) {
+
+                                       for (;;) {
+                         /*******************/
+                                               /* Read the status */
+                         /*******************/
+
+                                               dw_Status =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address + 8 +
+                                                       (64 * b_ModulNbr));
+
+                         /********************/
+                                               /* Test if overflow */
+                         /********************/
+
+                                               if ((dw_Status & 8) == 8) {
+                            /******************/
+                                                       /* Overflow occur */
+                            /******************/
+
+                                                       *pb_ChronoStatus = 3;
+
+                            /***************************/
+                                                       /* Test if continuous mode */
+                            /***************************/
+
+                                                       if (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_ChronoModuleInfo.
+                                                               b_CycleMode ==
+                                                               APCI1710_CONTINUOUS)
+                                                       {
+                               /*************************/
+                                                               /* Clear status register */
+                               /*************************/
+
+                                                               outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
+                                                       }
+
+                                                       break;
+                                               }       // if ((dw_Status & 8) == 8)
+                                               else {
+                            /*******************************/
+                                                       /* Test if measurement stopped */
+                            /*******************************/
+
+                                                       if ((dw_Status & 2) ==
+                                                               2) {
+                               /***********************/
+                                                               /* A stop signal occur */
+                               /***********************/
+
+                                                               *pb_ChronoStatus
+                                                                       = 2;
+
+                               /***************************/
+                                                               /* Test if continnous mode */
+                               /***************************/
+
+                                                               if (devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_ChronoModuleInfo.
+                                                                       b_CycleMode
+                                                                       ==
+                                                                       APCI1710_CONTINUOUS)
+                                                               {
+                                  /*************************/
+                                                                       /* Clear status register */
+                                  /*************************/
+
+                                                                       outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
+                                                               }
+                                                               break;
+                                                       }       // if ((dw_Status & 2) == 2)
+                                                       else {
+                               /*******************************/
+                                                               /* Test if measurement started */
+                               /*******************************/
+
+                                                               if ((dw_Status & 1) == 1) {
+                                  /************************/
+                                                                       /* A start signal occur */
+                                  /************************/
+
+                                                                       *pb_ChronoStatus
+                                                                               =
+                                                                               1;
+                                                               }       // if ((dw_Status & 1) == 1)
+                                                               else {
+                                  /***************************/
+                                                                       /* Measurement not started */
+                                  /***************************/
+
+                                                                       *pb_ChronoStatus
+                                                                               =
+                                                                               0;
+                                                               }       // if ((dw_Status & 1) == 1)
+                                                       }       // if ((dw_Status & 2) == 2)
+                                               }       // if ((dw_Status & 8) == 8)
+
+                                               if (dw_TimeOut == ui_TimeOut) {
+                            /*****************/
+                                                       /* Timeout occur */
+                            /*****************/
+
+                                                       break;
+                                               } else {
+                            /*************************/
+                                                       /* Increment the timeout */
+                            /*************************/
+
+                                                       dw_TimeOut =
+                                                               dw_TimeOut + 1;
+                                                       mdelay(1000);
+
+                                               }
+                                       }       // for (;;)
+
+                      /*****************************/
+                                       /* Test if stop signal occur */
+                      /*****************************/
+
+                                       if (*pb_ChronoStatus == 2) {
+                         /**********************************/
+                                               /* Read the measured timing value */
+                         /**********************************/
+
+                                               *pul_ChronoValue =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address + 4 +
+                                                       (64 * b_ModulNbr));
+
+                                               if (*pul_ChronoValue != 0) {
+                                                       *pul_ChronoValue =
+                                                               *pul_ChronoValue
+                                                               - 1;
+                                               }
+                                       } else {
+                         /*************************/
+                                               /* Test if timeout occur */
+                         /*************************/
+
+                                               if ((*pb_ChronoStatus != 3)
+                                                       && (dw_TimeOut ==
+                                                               ui_TimeOut)
+                                                       && (ui_TimeOut != 0)) {
+                            /*****************/
+                                                       /* Timeout occur */
+                            /*****************/
+
+                                                       *pb_ChronoStatus = 4;
+                                               }
+                                       }
+
+                               } else {
+                   /******************************/
+                                       /* Timeout parameter is wrong */
+                   /******************************/
+                                       DPRINTK("Timeout parameter is wrong\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*******************************/
+                               /* Chronometer not initialised */
+                /*******************************/
+                               DPRINTK("Chronometer not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /******************************************/
+                       /* The module is not a Chronometer module */
+             /******************************************/
+                       DPRINTK("The module is not a Chronometer module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ConvertChronoValue                    |
+|                               (BYTE_     b_BoardHandle,                    |
+|                                BYTE_     b_ModulNbr,                       |
+|                                ULONG_   ul_ChronoValue,                    |
+|                                PULONG_ pul_Hour,                           |
+|                                PBYTE_   pb_Minute,                         |
+|                                PBYTE_   pb_Second,                         |
+|                                PUINT_  pui_MilliSecond,                    |
+|                                PUINT_  pui_MicroSecond,                    |
+|                                PUINT_  pui_NanoSecond)                     |
++----------------------------------------------------------------------------+
+| Task              : Convert the chronometer measured timing                |
+|                     (ul_ChronoValue) in to h, mn, s, ms, Âµs, ns.           |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle : Handle of board APCI-1710      |
+|                     BYTE_   b_ModulNbr    : Selected module number (0 to 3)|
+|                     ULONG_ ul_ChronoValue : Measured chronometer timing    |
+|                                             value.                         |
+|                                             See"i_APCI1710_ReadChronoValue"|
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_   pul_Hour        : Chronometer timing hour    |
+|                     PBYTE_     pb_Minute      : Chronometer timing minute  |
+|                     PBYTE_     pb_Second      : Chronometer timing second  |
+|                     PUINT_    pui_MilliSecond  : Chronometer timing mini   |
+|                                                 second                     |
+|                     PUINT_    pui_MicroSecond : Chronometer timing micro   |
+|                                                 second                     |
+|                     PUINT_    pui_NanoSecond  : Chronometer timing nano    |
+|                                                 second                     |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ConvertChronoValue(comedi_device * dev,
+       BYTE b_ModulNbr,
+       ULONG ul_ChronoValue,
+       PULONG pul_Hour,
+       PBYTE pb_Minute,
+       PBYTE pb_Second,
+       PUINT pui_MilliSecond, PUINT pui_MicroSecond, PUINT pui_NanoSecond)
+{
+       INT i_ReturnValue = 0;
+       double d_Hour;
+       double d_Minute;
+       double d_Second;
+       double d_MilliSecond;
+       double d_MicroSecond;
+       double d_NanoSecond;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if chronometer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+             /***********************************/
+                       /* Test if chronometer initialised */
+             /***********************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_ChronoModuleInfo.b_ChronoInit == 1) {
+                               fpu_begin();
+
+                               d_Hour = (double)ul_ChronoValue *(double)
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_ChronoModuleInfo.d_TimingInterval;
+
+                               switch (devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_ChronoModuleInfo.b_TimingUnit) {
+                               case 0:
+                                       d_Hour = d_Hour / (double)1000.0;
+
+                               case 1:
+                                       d_Hour = d_Hour / (double)1000.0;
+
+                               case 2:
+                                       d_Hour = d_Hour / (double)1000.0;
+
+                               case 3:
+                                       d_Hour = d_Hour / (double)60.0;
+
+                               case 4:
+                           /**********************/
+                                       /* Calculate the hour */
+                           /**********************/
+
+                                       d_Hour = d_Hour / (double)60.0;
+                                       *pul_Hour = (ULONG) d_Hour;
+
+                           /************************/
+                                       /* Calculate the minute */
+                           /************************/
+
+                                       d_Minute = d_Hour - *pul_Hour;
+                                       d_Minute = d_Minute * 60;
+                                       *pb_Minute = (BYTE) d_Minute;
+
+                           /************************/
+                                       /* Calculate the second */
+                           /************************/
+
+                                       d_Second = d_Minute - *pb_Minute;
+                                       d_Second = d_Second * 60;
+                                       *pb_Second = (BYTE) d_Second;
+
+                           /*****************************/
+                                       /* Calculate the mini second */
+                           /*****************************/
+
+                                       d_MilliSecond = d_Second - *pb_Second;
+                                       d_MilliSecond = d_MilliSecond * 1000;
+                                       *pui_MilliSecond = (UINT) d_MilliSecond;
+
+                           /******************************/
+                                       /* Calculate the micro second */
+                           /******************************/
+
+                                       d_MicroSecond =
+                                               d_MilliSecond -
+                                               *pui_MilliSecond;
+                                       d_MicroSecond = d_MicroSecond * 1000;
+                                       *pui_MicroSecond = (UINT) d_MicroSecond;
+
+                           /******************************/
+                                       /* Calculate the micro second */
+                           /******************************/
+
+                                       d_NanoSecond =
+                                               d_MicroSecond -
+                                               *pui_MicroSecond;
+                                       d_NanoSecond = d_NanoSecond * 1000;
+                                       *pui_NanoSecond = (UINT) d_NanoSecond;
+                                       break;
+                               }
+
+                               fpu_end();
+                       } else {
+                /*******************************/
+                               /* Chronometer not initialised */
+                /*******************************/
+                               DPRINTK("Chronometer not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /******************************************/
+                       /* The module is not a Chronometer module */
+             /******************************************/
+                       DPRINTK("The module is not a Chronometer module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)                    |
++----------------------------------------------------------------------------+
+| Task              : Sets the output witch has been passed with the         |
+|                     parameter b_Channel. Setting an output means setting an|
+|                     output high.                                           |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
+|                     BYTE_ b_OutputChannel : Selection from digital output  |
+|                           CR_CHAN()                  channel (0 to 2)               |
+|                                              0 : Channel H                 |
+|                                              1 : Channel A                 |
+|                                              2 : Channel B                 |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: The selected digital output is wrong               |
+|                     -5: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_SetChronoChlOff                       |
+|                               (BYTE_  b_BoardHandle,                       |
+|                                BYTE_  b_ModulNbr,                          |
+|                                BYTE_  b_OutputChannel)                     |
++----------------------------------------------------------------------------+
+| Task              : Resets the output witch has been passed with the       |
+|                     parameter b_Channel. Resetting an output means setting |
+|                     an output low.                                         |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710
+                        data[0] : Chl ON, Chl OFF , Chl Read , Port Read
+
+|                     BYTE_ b_ModulNbr  CR_AREF    : Selected module number (0 to 3)|
+|                     BYTE_ b_OutputChannel CR_CHAN : Selection from digital output  |
+|                                             channel (0 to 2)               |
+|                                              0 : Channel H                 |
+|                                              1 : Channel A                 |
+|                                              2 : Channel B                 |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: The selected digital output is wrong               |
+|                     -5: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ReadChronoChlValue                    |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr,                         |
+|                                BYTE_   b_InputChannel,                     |
+|                                PBYTE_ pb_ChannelStatus)                    |
++----------------------------------------------------------------------------+
+| Task              : Return the status from selected digital input          |
+|                     (b_InputChannel) from selected chronometer             |
+|                     module (b_ModulNbr).                                   |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
+|                     BYTE_ b_InputChannel  : Selection from digital input   |
+|                                             channel (0 to 2)               |
+|                                   CR_CHAN()             0 : Channel E               |
+|                                                1 : Channel F               |
+|                                                2 : Channel G               |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel status.|
+|                                data[0]                0 : Channel is not active   |
+|                                                1 : Channel is active       |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: The selected digital input is wrong                |
+|                     -5: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ReadChronoPortValue                   |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr,                         |
+|                                PBYTE_ pb_PortValue)                        |
++----------------------------------------------------------------------------+
+| Task              : Return the status from digital inputs port from        |
+|                     selected  (b_ModulNbr) chronometer module.             |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_PortValue   : Digital inputs port status.
+|                     data[0]
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a Chronometer module             |
+|                     -4: Chronometer not initialised see function           |
+|                         "i_APCI1710_InitChrono"                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       BYTE b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+       DWORD dw_Status;
+       PBYTE pb_ChannelStatus;
+       PBYTE pb_PortValue;
+
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       i_ReturnValue = insn->n;
+       b_IOType = (BYTE) data[0];
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if chronometer */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+             /***********************************/
+                       /* Test if chronometer initialised */
+             /***********************************/
+
+                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_ChronoModuleInfo.b_ChronoInit == 1) {
+                /***********************************/
+                               /* Test the digital output channel */
+                /***********************************/
+                               switch (b_IOType) {
+
+                               case APCI1710_CHRONO_SET_CHANNELOFF:
+
+                                       b_OutputChannel =
+                                               (BYTE) CR_CHAN(insn->chanspec);
+                                       if (b_OutputChannel <= 2) {
+
+                                               outl(0, devpriv->s_BoardInfos.
+                                                       ui_Address + 20 +
+                                                       (b_OutputChannel * 4) +
+                                                       (64 * b_ModulNbr));
+                                       }       // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+                                       else {
+                   /****************************************/
+                                               /* The selected digital output is wrong */
+                   /****************************************/
+
+                                               DPRINTK("The selected digital output is wrong\n");
+                                               i_ReturnValue = -4;
+
+                                       }       // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+
+                                       break;
+
+                               case APCI1710_CHRONO_SET_CHANNELON:
+
+                                       b_OutputChannel =
+                                               (BYTE) CR_CHAN(insn->chanspec);
+                                       if (b_OutputChannel <= 2) {
+
+                                               outl(1, devpriv->s_BoardInfos.
+                                                       ui_Address + 20 +
+                                                       (b_OutputChannel * 4) +
+                                                       (64 * b_ModulNbr));
+                                       }       // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+                                       else {
+                   /****************************************/
+                                               /* The selected digital output is wrong */
+                   /****************************************/
+
+                                               DPRINTK("The selected digital output is wrong\n");
+                                               i_ReturnValue = -4;
+
+                                       }       // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+
+                                       break;
+
+                               case APCI1710_CHRONO_READ_CHANNEL:
+                /**********************************/
+                                       /* Test the digital input channel */
+                /**********************************/
+                                       pb_ChannelStatus = (PBYTE) & data[0];
+                                       b_InputChannel =
+                                               (BYTE) CR_CHAN(insn->chanspec);
+
+                                       if (b_InputChannel <= 2) {
+
+                                               dw_Status =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address + 12 +
+                                                       (64 * b_ModulNbr));
+
+                                               *pb_ChannelStatus =
+                                                       (BYTE) (((dw_Status >>
+                                                                       b_InputChannel)
+                                                               & 1) ^ 1);
+                                       }       // if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
+                                       else {
+                   /***************************************/
+                                               /* The selected digital input is wrong */
+                   /***************************************/
+
+                                               DPRINTK("The selected digital input is wrong\n");
+                                               i_ReturnValue = -4;
+                                       }       // if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
+
+                                       break;
+
+                               case APCI1710_CHRONO_READ_PORT:
+
+                                       pb_PortValue = (PBYTE) & data[0];
+
+                                       dw_Status =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 12 +
+                                               (64 * b_ModulNbr));
+
+                                       *pb_PortValue =
+                                               (BYTE) ((dw_Status & 0x7) ^ 7);
+                                       break;
+                               }
+                       } else {
+                /*******************************/
+                               /* Chronometer not initialised */
+                /*******************************/
+
+                               DPRINTK("Chronometer not initialised\n");
+                               i_ReturnValue = -5;
+                       }
+               } else {
+             /******************************************/
+                       /* The module is not a Chronometer module */
+             /******************************************/
+
+                       DPRINTK("The module is not a Chronometer module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
new file mode 100644 (file)
index 0000000..737d34c
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_30MHZ           30
+#define APCI1710_33MHZ           33
+#define APCI1710_40MHZ           40
+
+#define APCI1710_SINGLE     0
+#define APCI1710_CONTINUOUS 1
+
+#define APCI1710_CHRONO_PROGRESS_STATUS                0
+#define APCI1710_CHRONO_READVALUE                      1
+#define APCI1710_CHRONO_CONVERTVALUE           2
+#define APCI1710_CHRONO_READINTERRUPT       3
+
+#define APCI1710_CHRONO_SET_CHANNELON                  0
+#define APCI1710_CHRONO_SET_CHANNELOFF         1
+#define APCI1710_CHRONO_READ_CHANNEL           2
+#define APCI1710_CHRONO_READ_PORT                      3
+
+/*
++----------------------------------------------------------------------------+
+|                  CHRONOMETER INISIALISATION FUNCTION   |
++----------------------------------------------------------------------------+
+ */
+
+INT i_APCI1710_InsnConfigInitChrono(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*
++----------------------------------------------------------------------------+
+|                       CHRONOMETER READ FUNCTION                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadChrono(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_GetChronoProgressStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_ChronoStatus);
+
+INT i_APCI1710_ReadChronoValue(comedi_device * dev,
+       BYTE b_ModulNbr,
+       UINT ui_TimeOut, PBYTE pb_ChronoStatus, PULONG pul_ChronoValue);
+
+INT i_APCI1710_ConvertChronoValue(comedi_device * dev,
+       BYTE b_ModulNbr,
+       ULONG ul_ChronoValue,
+       PULONG pul_Hour,
+       PBYTE pb_Minute,
+       PBYTE pb_Second,
+       PUINT pui_MilliSecond, PUINT pui_MicroSecond, PUINT pui_NanoSecond);
+
+/*
++----------------------------------------------------------------------------+
+|                       CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION                  |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
new file mode 100644 (file)
index 0000000..531822c
--- /dev/null
@@ -0,0 +1,1020 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : DIG_IO.C        | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 digital I/O module                          |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 16/06/98 | S. Weber  | Digital input / output implementation          |
+  |----------|-----------|------------------------------------------------|
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "APCI1710_Dig_io.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev, |
+|                                              comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)|
++----------------------------------------------------------------------------+
+| Task              : Configure the digital I/O operating mode from selected |
+|                     module  (b_ModulNbr). You must calling this function be|
+|                     for you call any other function witch access of digital|
+|                     I/O.                                                   |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                                                                       |
+|                  BYTE_ b_ModulNbr      data[0]: Module number to               |
+|                                             configure (0 to 3)             |
+|                     BYTE_ b_ChannelAMode data[1]  : Channel A mode selection       |
+|                                             0 : Channel used for digital   |
+|                                                 input                      |
+|                                             1 : Channel used for digital   |
+|                                                 output                     |
+|                     BYTE_ b_ChannelBMode data[2] : Channel B mode selection       |
+|                                             0 : Channel used for digital   |
+|                                                 input                      |
+|                                             1 : Channel used for digital   |
+|                                                 output                                        |
+                                               data[0]   memory on/off
+Activates and deactivates the digital output memory.
+                                               After having      |
+|                 called up this function with memory on,the output you have previously|
+|                     activated with the function are not reset
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a digital I/O module              |
+|                    -4: Bi-directional channel A configuration error        |
+|                    -5: Bi-directional channel B configuration error        |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+       BYTE b_MemoryOnOff, b_ConfigType;
+       INT i_ReturnValue = 0;
+       DWORD dw_WriteConfig = 0;
+
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_ConfigType = (BYTE) data[0];  // Memory or  Init
+       b_ChannelAMode = (BYTE) data[1];
+       b_ChannelBMode = (BYTE) data[2];
+       b_MemoryOnOff = (BYTE) data[1]; // if memory operation
+       i_ReturnValue = insn->n;
+
+               /**************************/
+       /* Test the module number */
+               /**************************/
+
+       if (b_ModulNbr >= 4) {
+               DPRINTK("Module Number invalid\n");
+               i_ReturnValue = -2;
+               return i_ReturnValue;
+       }
+       switch (b_ConfigType) {
+       case APCI1710_DIGIO_MEMORYONOFF:
+
+               if (b_MemoryOnOff)      // If Memory ON
+               {
+                /****************************/
+                       /* Set the output memory on */
+                /****************************/
+
+                       devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_DigitalIOInfo.b_OutputMemoryEnabled = 1;
+
+                /***************************/
+                       /* Clear the output memory */
+                /***************************/
+                       devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_DigitalIOInfo.dw_OutputMemory = 0;
+               } else          // If memory off
+               {
+                /*****************************/
+                       /* Set the output memory off */
+                /*****************************/
+
+                       devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_DigitalIOInfo.b_OutputMemoryEnabled = 0;
+               }
+               break;
+
+       case APCI1710_DIGIO_INIT:
+
+       /*******************************/
+               /* Test if digital I/O counter */
+       /*******************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+
+       /***************************************************/
+                       /* Test the bi-directional channel A configuration */
+       /***************************************************/
+
+                       if ((b_ChannelAMode == 0) || (b_ChannelAMode == 1)) {
+       /***************************************************/
+                               /* Test the bi-directional channel B configuration */
+       /***************************************************/
+
+                               if ((b_ChannelBMode == 0)
+                                       || (b_ChannelBMode == 1)) {
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_DigitalIOInfo.b_DigitalInit =
+                                               1;
+
+       /********************************/
+                                       /* Save channel A configuration */
+       /********************************/
+
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_DigitalIOInfo.
+                                               b_ChannelAMode = b_ChannelAMode;
+
+       /********************************/
+                                       /* Save channel B configuration */
+       /********************************/
+
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_DigitalIOInfo.
+                                               b_ChannelBMode = b_ChannelBMode;
+
+       /*****************************************/
+                                       /* Set the channel A and B configuration */
+       /*****************************************/
+
+                                       dw_WriteConfig =
+                                               (DWORD) (b_ChannelAMode |
+                                               (b_ChannelBMode * 2));
+
+       /***************************/
+                                       /* Write the configuration */
+       /***************************/
+
+                                       outl(dw_WriteConfig,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 4 +
+                                               (64 * b_ModulNbr));
+
+                               } else {
+       /************************************************/
+                                       /* Bi-directional channel B configuration error */
+       /************************************************/
+                                       DPRINTK("Bi-directional channel B configuration error\n");
+                                       i_ReturnValue = -5;
+                               }
+
+                       } else {
+       /************************************************/
+                               /* Bi-directional channel A configuration error */
+       /************************************************/
+                               DPRINTK("Bi-directional channel A configuration error\n");
+                               i_ReturnValue = -4;
+
+                       }
+
+               } else {
+       /******************************************/
+                       /* The module is not a digital I/O module */
+       /******************************************/
+                       DPRINTK("The module is not a digital I/O module\n");
+                       i_ReturnValue = -3;
+               }
+       }                       // end of Switch
+       printk("Return Value %d\n", i_ReturnValue);
+       return i_ReturnValue;
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            INPUT FUNCTIONS                                 |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+
+|INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice
+*s,    comedi_insn *insn,lsampl_t *data)
+
++----------------------------------------------------------------------------+
+| Task              : Read the status from selected digital I/O digital input|
+|                     (b_InputChannel)                                       |
++----------------------------------------------------------------------------|
+
+
+|
+|  BYTE_ b_ModulNbr  CR_AREF(chanspec)          : Selected module number   |
+|                                                   (0 to 3)                 |
+|  BYTE_ b_InputChannel CR_CHAN(chanspec)        : Selection from digital   |
+|                                                   input ( 0 to 6)          |
+|                                                      0 : Channel C         |
+|                                                      1 : Channel D         |
+|                                                      2 : Channel E         |
+|                                                      3 : Channel F         |
+|                                                      4 : Channel G         |
+|                                                      5 : Channel A         |
+|                                                      6 : Channel B
+
+
+       |
++----------------------------------------------------------------------------+
+| Output Parameters :                                   data[0]   : Digital input channel    |
+|                                                   status                   |
+|                                                   0 : Channle is not active|
+|                                                   1 : Channle is active    |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a digital I/O module              |
+|                    -4: The selected digital I/O digital input is wrong     |
+|                    -5: Digital I/O not initialised                         |
+|                    -6: The digital channel A is used for output            |
+|                    -7: The digital channel B is used for output            |
++----------------------------------------------------------------------------+
+*/
+
+//_INT_   i_APCI1710_ReadDigitalIOChlValue      (BYTE_    b_BoardHandle,
+//                                             BYTE_    b_ModulNbr,
+//                                             BYTE_    b_InputChannel,
+//
+//                                             PBYTE_  pb_ChannelStatus)
+INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg;
+       BYTE b_ModulNbr, b_InputChannel;
+       PBYTE pb_ChannelStatus;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
+       data[0] = 0;
+       pb_ChannelStatus = (PBYTE) & data[0];
+       i_ReturnValue = insn->n;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if digital I/O counter */
+          /*******************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+             /******************************************/
+                       /* Test the digital imnput channel number */
+             /******************************************/
+
+                       if (b_InputChannel <= 6) {
+                /**********************************************/
+                               /* Test if the digital I/O module initialised */
+                /**********************************************/
+
+                               if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_DigitalIOInfo.b_DigitalInit == 1) {
+                   /**********************************/
+                                       /* Test if channel A or channel B */
+                   /**********************************/
+
+                                       if (b_InputChannel > 4) {
+                      /*********************/
+                                               /* Test if channel A */
+                      /*********************/
+
+                                               if (b_InputChannel == 5) {
+                         /***************************/
+                                                       /* Test the channel A mode */
+                         /***************************/
+
+                                                       if (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               b_ChannelAMode
+                                                               != 0) {
+                            /********************************************/
+                                                               /* The digital channel A is used for output */
+                            /********************************************/
+
+                                                               i_ReturnValue =
+                                                                       -6;
+                                                       }
+                                               }       // if (b_InputChannel == 5)
+                                               else {
+                         /***************************/
+                                                       /* Test the channel B mode */
+                         /***************************/
+
+                                                       if (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               b_ChannelBMode
+                                                               != 0) {
+                            /********************************************/
+                                                               /* The digital channel B is used for output */
+                            /********************************************/
+
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }
+                                               }       // if (b_InputChannel == 5)
+                                       }       // if (b_InputChannel > 4)
+
+                   /***********************/
+                                       /* Test if error occur */
+                   /***********************/
+
+                                       if (i_ReturnValue >= 0) {
+                      /**************************/
+                                               /* Read all digital input */
+                      /**************************/
+
+                                               //INPDW (ps_APCI1710Variable->
+                                               //   s_Board [b_BoardHandle].
+                                               //   s_BoardInfos.
+                                               //  ui_Address + (64 * b_ModulNbr),
+                                               // &dw_StatusReg);
+
+                                               dw_StatusReg =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address +
+                                                       (64 * b_ModulNbr));
+
+                                               *pb_ChannelStatus =
+                                                       (BYTE) ((dw_StatusReg ^
+                                                               0x1C) >>
+                                                       b_InputChannel) & 1;
+
+                                       }       // if (i_ReturnValue == 0)
+                               } else {
+                   /*******************************/
+                                       /* Digital I/O not initialised */
+                   /*******************************/
+                                       DPRINTK("Digital I/O not initialised\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /********************************/
+                               /* Selected digital input error */
+                /********************************/
+                               DPRINTK("Selected digital input error\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /******************************************/
+                       /* The module is not a digital I/O module */
+             /******************************************/
+                       DPRINTK("The module is not a digital I/O module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            OUTPUT FUNCTIONS                                |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
+|*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
+
++----------------------------------------------------------------------------+
+| Task              : Sets or resets the output witch has been passed with the         |
+|                     parameter b_Channel. Setting an output means setting   |
+|                     an ouput high.                                         |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+|                     BYTE_ b_ModulNbr (aref )    : Selected module number (0 to 3)|
+|                     BYTE_ b_OutputChannel (CR_CHAN) : Selection from digital output  |
+|                                             channel (0 to 2)               |
+|                                                0 : Channel H               |
+|                                                1 : Channel A               |
+|                                                2 : Channel B               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a digital I/O module              |
+|                    -4: The selected digital output is wrong                |
+|                    -5: digital I/O not initialised see function            |
+|                        " i_APCI1710_InitDigitalIO"                         |
+|                    -6: The digital channel A is used for input             |
+|                    -7: The digital channel B is used for input
+                                        -8: Digital Output Memory OFF.                          |
+|                        Use previously the function                         |
+|                        "i_APCI1710_SetDigitalIOMemoryOn".            |
++----------------------------------------------------------------------------+
+*/
+
+//_INT_   i_APCI1710_SetDigitalIOChlOn    (BYTE_ b_BoardHandle,
+//                                       BYTE_ b_ModulNbr,
+//                                       BYTE_ b_OutputChannel)
+INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_WriteValue = 0;
+       BYTE b_ModulNbr, b_OutputChannel;
+       i_ReturnValue = insn->n;
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_OutputChannel = CR_CHAN(insn->chanspec);
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if digital I/O counter */
+          /*******************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+             /**********************************************/
+                       /* Test if the digital I/O module initialised */
+             /**********************************************/
+
+                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_DigitalIOInfo.b_DigitalInit == 1) {
+                /******************************************/
+                               /* Test the digital output channel number */
+                /******************************************/
+
+                               switch (b_OutputChannel) {
+                   /*************/
+                                       /* Channel H */
+                   /*************/
+
+                               case 0:
+                                       break;
+
+                   /*************/
+                                       /* Channel A */
+                   /*************/
+
+                               case 1:
+                                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_DigitalIOInfo.
+                                               b_ChannelAMode != 1) {
+                           /*******************************************/
+                                               /* The digital channel A is used for input */
+                           /*******************************************/
+
+                                               i_ReturnValue = -6;
+                                       }
+                                       break;
+
+                   /*************/
+                                       /* Channel B */
+                   /*************/
+
+                               case 2:
+                                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_DigitalIOInfo.
+                                               b_ChannelBMode != 1) {
+                           /*******************************************/
+                                               /* The digital channel B is used for input */
+                           /*******************************************/
+
+                                               i_ReturnValue = -7;
+                                       }
+                                       break;
+
+                               default:
+                        /****************************************/
+                                       /* The selected digital output is wrong */
+                        /****************************************/
+
+                                       i_ReturnValue = -4;
+                                       break;
+                               }
+
+                /***********************/
+                               /* Test if error occur */
+                /***********************/
+
+                               if (i_ReturnValue >= 0) {
+
+                       /*********************************/
+                                       /* Test if set channel ON        */
+                   /*********************************/
+                                       if (data[0]) {
+                   /*********************************/
+                                               /* Test if output memory enabled */
+                   /*********************************/
+
+                                               if (devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_DigitalIOInfo.
+                                                       b_OutputMemoryEnabled ==
+                                                       1) {
+                                                       dw_WriteValue =
+                                                               devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               dw_OutputMemory
+                                                               | (1 <<
+                                                               b_OutputChannel);
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               dw_OutputMemory
+                                                               = dw_WriteValue;
+                                               } else {
+                                                       dw_WriteValue =
+                                                               1 <<
+                                                               b_OutputChannel;
+                                               }
+                                       }       // set channel off
+                                       else {
+                                               if (devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_DigitalIOInfo.
+                                                       b_OutputMemoryEnabled ==
+                                                       1) {
+                                                       dw_WriteValue =
+                                                               devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               dw_OutputMemory
+                                                               & (0xFFFFFFFFUL
+                                                               -
+                                                               (1 << b_OutputChannel));
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               dw_OutputMemory
+                                                               = dw_WriteValue;
+                                               } else {
+                      /*****************************/
+                                                       /* Digital Output Memory OFF */
+                      /*****************************/
+                                                       // +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn"
+                                                       i_ReturnValue = -8;
+                                               }
+
+                                       }
+                   /*******************/
+                                       /* Write the value */
+                   /*******************/
+
+                                       //OUTPDW (ps_APCI1710Variable->
+                                       //    s_Board [b_BoardHandle].
+                                       //   s_BoardInfos.
+                                       //   ui_Address + (64 * b_ModulNbr),
+                                       //   dw_WriteValue);
+                                       outl(dw_WriteValue,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + (64 * b_ModulNbr));
+                               }
+                       } else {
+                /*******************************/
+                               /* Digital I/O not initialised */
+                /*******************************/
+
+                               i_ReturnValue = -5;
+                       }
+               } else {
+             /******************************************/
+                       /* The module is not a digital I/O module */
+             /******************************************/
+
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+
+|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice
+       *s,     comedi_insn *insn,lsampl_t *data)
++----------------------------------------------------------------------------+
+| Task              : write:
+                                         Sets or resets one or several outputs from port.                 |
+|                     Setting an output means setting an output high.        |
+|                     If you have switched OFF the digital output memory     |
+|                     (OFF), all the other output are set to "0".
+
+|                      read:
+                                         Read the status from digital input port                |
+|                     from selected digital I/O module (b_ModulNbr)
++----------------------------------------------------------------------------+
+| Input Parameters  :
+       BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+|   BYTE_ b_ModulNbr  CR_AREF(aref)    : Selected module number (0 to 3)|
+|   BYTE_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 )
+|                       data[0]           read or write port
+                        data[1]            if write then indicate ON or OFF
+
+                        if read : data[1] will return port status.
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
+
+                INPUT :
+
+                                         0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a digital I/O module              |
+|                    -4: Digital I/O not initialised
+
+                               OUTPUT:   0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a digital I/O module              |
+|                    -4: Output value wrong                                  |
+|                    -5: digital I/O not initialised see function            |
+|                        " i_APCI1710_InitDigitalIO"                         |
+|                    -6: The digital channel A is used for input             |
+|                    -7: The digital channel B is used for input
+                                       -8: Digital Output Memory OFF.                          |
+|                        Use previously the function                         |
+|                        "i_APCI1710_SetDigitalIOMemoryOn".               |
++----------------------------------------------------------------------------+
+*/
+
+//_INT_   i_APCI1710_SetDigitalIOPortOn   (BYTE_ b_BoardHandle,
+//                                       BYTE_ b_ModulNbr,
+//                                       BYTE_ b_PortValue)
+INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_WriteValue = 0;
+       DWORD dw_StatusReg;
+       BYTE b_ModulNbr, b_PortValue;
+       BYTE b_PortOperation, b_PortOnOFF;
+
+       PBYTE pb_PortValue;
+
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_PortOperation = (BYTE) data[0];       // Input or output
+       b_PortOnOFF = (BYTE) data[1];   // if output then On or Off
+       b_PortValue = (BYTE) data[2];   // if out put then Value
+       i_ReturnValue = insn->n;
+       pb_PortValue = (PBYTE) & data[0];
+// if input then read value
+
+       switch (b_PortOperation) {
+       case APCI1710_INPUT:
+       /**************************/
+               /* Test the module number */
+       /**************************/
+
+               if (b_ModulNbr < 4) {
+          /*******************************/
+                       /* Test if digital I/O counter */
+          /*******************************/
+
+                       if ((devpriv->s_BoardInfos.
+                                       dw_MolduleConfiguration[b_ModulNbr] &
+                                       0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+             /**********************************************/
+                               /* Test if the digital I/O module initialised */
+             /**********************************************/
+
+                               if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_DigitalIOInfo.b_DigitalInit == 1) {
+                /**************************/
+                                       /* Read all digital input */
+                /**************************/
+
+                                       //INPDW (ps_APCI1710Variable->
+                                       //      s_Board [b_BoardHandle].
+                                       //      s_BoardInfos.
+                                       //      ui_Address + (64 * b_ModulNbr),
+                                       //      &dw_StatusReg);
+
+                                       dw_StatusReg =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + (64 * b_ModulNbr));
+                                       *pb_PortValue =
+                                               (BYTE) (dw_StatusReg ^ 0x1C);
+
+                               } else {
+                /*******************************/
+                                       /* Digital I/O not initialised */
+                /*******************************/
+
+                                       i_ReturnValue = -4;
+                               }
+                       } else {
+             /******************************************/
+                               /* The module is not a digital I/O module */
+             /******************************************/
+
+                               i_ReturnValue = -3;
+                       }
+               } else {
+          /***********************/
+                       /* Module number error */
+          /***********************/
+
+                       i_ReturnValue = -2;
+               }
+
+               break;
+
+       case APCI1710_OUTPUT:
+       /**************************/
+               /* Test the module number */
+       /**************************/
+
+               if (b_ModulNbr < 4) {
+          /*******************************/
+                       /* Test if digital I/O counter */
+          /*******************************/
+
+                       if ((devpriv->s_BoardInfos.
+                                       dw_MolduleConfiguration[b_ModulNbr] &
+                                       0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+             /**********************************************/
+                               /* Test if the digital I/O module initialised */
+             /**********************************************/
+
+                               if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_DigitalIOInfo.b_DigitalInit == 1) {
+                /***********************/
+                                       /* Test the port value */
+                /***********************/
+
+                                       if (b_PortValue <= 7) {
+                   /***********************************/
+                                               /* Test the digital output channel */
+                   /***********************************/
+
+                   /**************************/
+                                               /* Test if channel A used */
+                   /**************************/
+
+                                               if ((b_PortValue & 2) == 2) {
+                                                       if (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               b_ChannelAMode
+                                                               != 1) {
+                         /*******************************************/
+                                                               /* The digital channel A is used for input */
+                         /*******************************************/
+
+                                                               i_ReturnValue =
+                                                                       -6;
+                                                       }
+                                               }       // if ((b_PortValue & 2) == 2)
+
+                   /**************************/
+                                               /* Test if channel B used */
+                   /**************************/
+
+                                               if ((b_PortValue & 4) == 4) {
+                                                       if (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_DigitalIOInfo.
+                                                               b_ChannelBMode
+                                                               != 1) {
+                         /*******************************************/
+                                                               /* The digital channel B is used for input */
+                         /*******************************************/
+
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }
+                                               }       // if ((b_PortValue & 4) == 4)
+
+                   /***********************/
+                                               /* Test if error occur */
+                   /***********************/
+
+                                               if (i_ReturnValue >= 0) {
+
+                                                       //if(data[1])
+                                                       //{
+                                                       switch (b_PortOnOFF) {
+                          /*********************************/
+                                                               /* Test if set Port ON                   */
+                      /*********************************/
+
+                                                       case APCI1710_ON:
+
+                      /*********************************/
+                                                               /* Test if output memory enabled */
+                      /*********************************/
+
+                                                               if (devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_DigitalIOInfo.
+                                                                       b_OutputMemoryEnabled
+                                                                       == 1) {
+                                                                       dw_WriteValue
+                                                                               =
+                                                                               devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_DigitalIOInfo.
+                                                                               dw_OutputMemory
+                                                                               |
+                                                                               b_PortValue;
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_DigitalIOInfo.
+                                                                               dw_OutputMemory
+                                                                               =
+                                                                               dw_WriteValue;
+                                                               } else {
+                                                                       dw_WriteValue
+                                                                               =
+                                                                               b_PortValue;
+                                                               }
+                                                               break;
+
+                                                               // If Set PORT  OFF
+                                                       case APCI1710_OFF:
+
+                          /*********************************/
+                                                               /* Test if output memory enabled */
+                      /*********************************/
+
+                                                               if (devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_DigitalIOInfo.
+                                                                       b_OutputMemoryEnabled
+                                                                       == 1) {
+                                                                       dw_WriteValue
+                                                                               =
+                                                                               devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_DigitalIOInfo.
+                                                                               dw_OutputMemory
+                                                                               &
+                                                                               (0xFFFFFFFFUL
+                                                                               -
+                                                                               b_PortValue);
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_DigitalIOInfo.
+                                                                               dw_OutputMemory
+                                                                               =
+                                                                               dw_WriteValue;
+                                                               } else {
+                         /*****************************/
+                                                                       /* Digital Output Memory OFF */
+                         /*****************************/
+
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -8;
+                                                               }
+                                                       }       // switch
+
+                      /*******************/
+                                                       /* Write the value */
+                      /*******************/
+
+                                                       //  OUTPDW (ps_APCI1710Variable->
+                                                       //      s_Board [b_BoardHandle].
+                                                       //      s_BoardInfos.
+                                                       //      ui_Address + (64 * b_ModulNbr),
+                                                       //      dw_WriteValue);
+                                                       outl(dw_WriteValue,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               (64 * b_ModulNbr));
+                                               }
+                                       } else {
+                   /**********************/
+                                               /* Output value wrong */
+                   /**********************/
+
+                                               i_ReturnValue = -4;
+                                       }
+                               } else {
+                /*******************************/
+                                       /* Digital I/O not initialised */
+                /*******************************/
+
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+             /******************************************/
+                               /* The module is not a digital I/O module */
+             /******************************************/
+
+                               i_ReturnValue = -3;
+                       }
+               } else {
+          /***********************/
+                       /* Module number error */
+          /***********************/
+
+                       i_ReturnValue = -2;
+               }
+               break;
+
+       default:
+               i_ReturnValue = -9;
+               DPRINTK("NO INPUT/OUTPUT specified\n");
+       }                       //switch INPUT / OUTPUT
+       return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
new file mode 100644 (file)
index 0000000..a12f356
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define                APCI1710_ON                             1       // Digital  Output ON or OFF
+#define                APCI1710_OFF                    0
+
+#define                APCI1710_INPUT                  0       // Digital I/O
+#define                APCI1710_OUTPUT                 1
+
+#define         APCI1710_DIGIO_MEMORYONOFF  0x10       //
+#define         APCI1710_DIGIO_INIT         0x11
+
+/*
++----------------------------------------------------------------------------+
+|                       DIGITAL I/O INISIALISATION FUNCTION                  |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigDigitalIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+/*
++----------------------------------------------------------------------------+
+|                            INPUT OUTPUT  FUNCTIONS                         |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
new file mode 100644 (file)
index 0000000..ddffb06
--- /dev/null
@@ -0,0 +1,5363 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : INC_CPT.C       | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 incremental counter module                  |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |----------|-----------|------------------------------------------------|
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+  | 29/06/01 | Guinot C. | - 1100/0231 -> 0701/0232                       |
+  |          |           | See i_APCI1710_DisableFrequencyMeasurement     |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_INCCPT.h"
+
+/*
++----------------------------------------------------------------------------+
+| INT  i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s,
+comedi_insn *insn,lsampl_t *data)
+
++----------------------------------------------------------------------------+
+| Task              : Configuration function for INC_CPT                             |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                                                                           |
++----------------------------------------------------------------------------+
+| Output Parameters : *data
++----------------------------------------------------------------------------+
+| Return Value      :                 |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_ConfigType;
+       INT i_ReturnValue = 0;
+       ui_ConfigType = CR_CHAN(insn->chanspec);
+
+       printk("\nINC_CPT");
+
+       devpriv->tsk_Current = current; // Save the current process task structure
+       switch (ui_ConfigType) {
+       case APCI1710_INCCPT_INITCOUNTER:
+               i_ReturnValue = i_APCI1710_InitCounter(dev,
+                       CR_AREF(insn->chanspec),
+                       (BYTE) data[0],
+                       (BYTE) data[1],
+                       (BYTE) data[2], (BYTE) data[3], (BYTE) data[4]);
+               break;
+
+       case APCI1710_INCCPT_COUNTERAUTOTEST:
+               i_ReturnValue = i_APCI1710_CounterAutoTest(dev,
+                       (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_INITINDEX:
+               i_ReturnValue = i_APCI1710_InitIndex(dev,
+                       CR_AREF(insn->chanspec),
+                       (BYTE) data[0],
+                       (BYTE) data[1], (BYTE) data[2], (BYTE) data[3]);
+               break;
+
+       case APCI1710_INCCPT_INITREFERENCE:
+               i_ReturnValue = i_APCI1710_InitReference(dev,
+                       CR_AREF(insn->chanspec), (BYTE) data[0]);
+               break;
+
+       case APCI1710_INCCPT_INITEXTERNALSTROBE:
+               i_ReturnValue = i_APCI1710_InitExternalStrobe(dev,
+                       CR_AREF(insn->chanspec),
+                       (BYTE) data[0], (BYTE) data[1]);
+               break;
+
+       case APCI1710_INCCPT_INITCOMPARELOGIC:
+               i_ReturnValue = i_APCI1710_InitCompareLogic(dev,
+                       CR_AREF(insn->chanspec), (UINT) data[0]);
+               break;
+
+       case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:
+               i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
+                       CR_AREF(insn->chanspec),
+                       (BYTE) data[0],
+                       (BYTE) data[1], (ULONG) data[2], (PULONG) & data[0]);
+               break;
+
+       default:
+               printk("Insn Config : Config Parameter Wrong\n");
+
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitCounter                           |
+|                               (BYTE_          b_BoardHandle,               |
+|                                BYTE_          b_ModulNbr,                  |
+|                                BYTE_          b_CounterRange,              |
+|                                BYTE_          b_FirstCounterModus,         |
+|                                BYTE_          b_FirstCounterOption,        |
+|                                BYTE_          b_SecondCounterModus,        |
+|                                BYTE_          b_SecondCounterOption)       |
++----------------------------------------------------------------------------+
+| Task              : Configure the counter operating mode from selected     |
+|                     module (b_ModulNbr). You must calling this function be |
+|                     for you call any other function witch access of        |
+|                     counters.                                              |
+|                                                                            |
+|                          Counter range                                     |
+|                          -------------                                     |
+| +------------------------------------+-----------------------------------+ |
+| | Parameter       Passed value       |        Description                | |
+| |------------------------------------+-----------------------------------| |
+| |b_ModulNbr   APCI1710_16BIT_COUNTER |  The module is configured for     | |
+| |                                    |  two 16-bit counter.              | |
+| |                                    |  - b_FirstCounterModus and        | |
+| |                                    |    b_FirstCounterOption           | |
+| |                                    |    configure the first 16 bit     | |
+| |                                    |    counter.                       | |
+| |                                    |  - b_SecondCounterModus and       | |
+| |                                    |    b_SecondCounterOption          | |
+| |                                    |    configure the second 16 bit    | |
+| |                                    |    counter.                       | |
+| |------------------------------------+-----------------------------------| |
+| |b_ModulNbr   APCI1710_32BIT_COUNTER |  The module is configured for one | |
+| |                                    |  32-bit counter.                  | |
+| |                                    |  - b_FirstCounterModus and        | |
+| |                                    |    b_FirstCounterOption           | |
+| |                                    |    configure the 32 bit counter.  | |
+| |                                    |  - b_SecondCounterModus and       | |
+| |                                    |    b_SecondCounterOption          | |
+| |                                    |    are not used and have no       | |
+| |                                    |    importance.                    | |
+| +------------------------------------+-----------------------------------+ |
+|                                                                            |
+|                      Counter operating mode                                |
+|                      ----------------------                                |
+|                                                                            |
+| +--------------------+-------------------------+-------------------------+ |
+| |    Parameter       |     Passed value        |    Description          | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus | APCI1710_QUADRUPLE_MODE | In the quadruple mode,  | |
+| |       or           |                         | the edge analysis       | |
+| |b_SecondCounterModus|                         | circuit generates a     | |
+| |                    |                         | counting pulse from     | |
+| |                    |                         | each edge of 2 signals  | |
+| |                    |                         | which are phase shifted | |
+| |                    |                         | in relation to each     | |
+| |                    |                         | other.                  | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus |   APCI1710_DOUBLE_MODE  | Functions in the same   | |
+| |       or           |                         | way as the quadruple    | |
+| |b_SecondCounterModus|                         | mode, except that only  | |
+| |                    |                         | two of the four edges   | |
+| |                    |                         | are analysed per        | |
+| |                    |                         | period                  | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus |   APCI1710_SIMPLE_MODE  | Functions in the same   | |
+| |       or           |                         | way as the quadruple    | |
+| |b_SecondCounterModus|                         | mode, except that only  | |
+| |                    |                         | one of the four edges   | |
+| |                    |                         | is analysed per         | |
+| |                    |                         | period.                 | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus |   APCI1710_DIRECT_MODE  | In the direct mode the  | |
+| |       or           |                         | both edge analysis      | |
+| |b_SecondCounterModus|                         | circuits are inactive.  | |
+| |                    |                         | The inputs A, B in the  | |
+| |                    |                         | 32-bit mode or A, B and | |
+| |                    |                         | C, D in the 16-bit mode | |
+| |                    |                         | represent, each, one    | |
+| |                    |                         | clock pulse gate circuit| |
+| |                    |                         | There by frequency and  | |
+| |                    |                         | pulse duration          | |
+| |                    |                         | measurements can be     | |
+| |                    |                         | performed.              | |
+| +--------------------+-------------------------+-------------------------+ |
+|                                                                            |
+|                                                                            |
+|       IMPORTANT!                                                           |
+|       If you have configured the module for two 16-bit counter, a mixed    |
+|       mode with a counter in quadruple/double/single mode                  |
+|       and the other counter in direct mode is not possible!                |
+|                                                                            |
+|                                                                            |
+|         Counter operating option for quadruple/double/simple mode          |
+|         ---------------------------------------------------------          |
+|                                                                            |
+| +----------------------+-------------------------+------------------------+|
+| |       Parameter      |     Passed value        |  Description           ||
+| |----------------------+-------------------------+------------------------||
+| |b_FirstCounterOption  | APCI1710_HYSTERESIS_ON  | In both edge analysis  ||
+| |        or            |                         | circuits is available  ||
+| |b_SecondCounterOption |                         | one hysteresis circuit.||
+| |                      |                         | It suppresses each     ||
+| |                      |                         | time the first counting||
+| |                      |                         | pulse after a change   ||
+| |                      |                         | of rotation.           ||
+| |----------------------+-------------------------+------------------------||
+| |b_FirstCounterOption  | APCI1710_HYSTERESIS_OFF | The first counting     ||
+| |       or             |                         | pulse is not suppress  ||
+| |b_SecondCounterOption |                         | after a change of      ||
+| |                      |                         | rotation.              ||
+| +----------------------+-------------------------+------------------------+|
+|                                                                            |
+|                                                                            |
+|       IMPORTANT!                                                           |
+|       This option are only avaible if you have selected the direct mode.   |
+|                                                                            |
+|                                                                            |
+|               Counter operating option for direct mode                     |
+|               ----------------------------------------                     |
+|                                                                            |
+| +----------------------+--------------------+----------------------------+ |
+| |      Parameter       |     Passed value   |       Description          | |
+| |----------------------+--------------------+----------------------------| |
+| |b_FirstCounterOption  | APCI1710_INCREMENT | The counter increment for  | |
+| |       or             |                    | each counting pulse        | |
+| |b_SecondCounterOption |                    |                            | |
+| |----------------------+--------------------+----------------------------| |
+| |b_FirstCounterOption  | APCI1710_DECREMENT | The counter decrement for  | |
+| |       or             |                    | each counting pulse        | |
+| |b_SecondCounterOption |                    |                            | |
+| +----------------------+--------------------+----------------------------+ |
+|                                                                            |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr            : Module number to         |
+|                                                   configure (0 to 3)       |
+|                     BYTE_ b_CounterRange        : Selection form counter   |
+|                                                   range.                   |
+|                     BYTE_ b_FirstCounterModus   : First counter operating  |
+|                                                   mode.                    |
+|                     BYTE_ b_FirstCounterOption  : First counter  option.   |
+|                     BYTE_ b_SecondCounterModus  : Second counter operating |
+|                                                   mode.                    |
+|                     BYTE_ b_SecondCounterOption : Second counter  option.  |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module is not a counter module                  |
+|                    -3: The selected counter range is wrong.                |
+|                    -4: The selected first counter operating mode is wrong. |
+|                    -5: The selected first counter operating option is wrong|
+|                    -6: The selected second counter operating mode is wrong.|
+|                    -7: The selected second counter operating option is     |
+|                        wrong.                                              |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitCounter(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_CounterRange,
+       BYTE b_FirstCounterModus,
+       BYTE b_FirstCounterOption,
+       BYTE b_SecondCounterModus, BYTE b_SecondCounterOption)
+{
+       INT i_ReturnValue = 0;
+
+       /*******************************/
+       /* Test if incremental counter */
+       /*******************************/
+
+       if ((devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER) {
+          /**************************/
+               /* Test the counter range */
+          /**************************/
+
+               if (b_CounterRange == APCI1710_16BIT_COUNTER
+                       || b_CounterRange == APCI1710_32BIT_COUNTER) {
+             /********************************/
+                       /* Test the first counter modus */
+             /********************************/
+
+                       if (b_FirstCounterModus == APCI1710_QUADRUPLE_MODE ||
+                               b_FirstCounterModus == APCI1710_DOUBLE_MODE ||
+                               b_FirstCounterModus == APCI1710_SIMPLE_MODE ||
+                               b_FirstCounterModus == APCI1710_DIRECT_MODE) {
+                /*********************************/
+                               /* Test the first counter option */
+                /*********************************/
+
+                               if ((b_FirstCounterModus == APCI1710_DIRECT_MODE
+                                               && (b_FirstCounterOption ==
+                                                       APCI1710_INCREMENT
+                                                       || b_FirstCounterOption
+                                                       == APCI1710_DECREMENT))
+                                       || (b_FirstCounterModus !=
+                                               APCI1710_DIRECT_MODE
+                                               && (b_FirstCounterOption ==
+                                                       APCI1710_HYSTERESIS_ON
+                                                       || b_FirstCounterOption
+                                                       ==
+                                                       APCI1710_HYSTERESIS_OFF)))
+                               {
+                   /**************************/
+                                       /* Test if 16-bit counter */
+                   /**************************/
+
+                                       if (b_CounterRange ==
+                                               APCI1710_16BIT_COUNTER) {
+                      /*********************************/
+                                               /* Test the second counter modus */
+                      /*********************************/
+
+                                               if ((b_FirstCounterModus !=
+                                                               APCI1710_DIRECT_MODE
+                                                               &&
+                                                               (b_SecondCounterModus
+                                                                       ==
+                                                                       APCI1710_QUADRUPLE_MODE
+                                                                       ||
+                                                                       b_SecondCounterModus
+                                                                       ==
+                                                                       APCI1710_DOUBLE_MODE
+                                                                       ||
+                                                                       b_SecondCounterModus
+                                                                       ==
+                                                                       APCI1710_SIMPLE_MODE))
+                                                       || (b_FirstCounterModus
+                                                               ==
+                                                               APCI1710_DIRECT_MODE
+                                                               &&
+                                                               b_SecondCounterModus
+                                                               ==
+                                                               APCI1710_DIRECT_MODE))
+                                               {
+                         /**********************************/
+                                                       /* Test the second counter option */
+                         /**********************************/
+
+                                                       if ((b_SecondCounterModus == APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_INCREMENT || b_SecondCounterOption == APCI1710_DECREMENT)) || (b_SecondCounterModus != APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_HYSTERESIS_ON || b_SecondCounterOption == APCI1710_HYSTERESIS_OFF))) {
+                                                               i_ReturnValue =
+                                                                       0;
+                                                       } else {
+                            /*********************************************************/
+                                                               /* The selected second counter operating option is wrong */
+                            /*********************************************************/
+
+                                                               DPRINTK("The selected second counter operating option is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }
+                                               } else {
+                         /*******************************************************/
+                                                       /* The selected second counter operating mode is wrong */
+                         /*******************************************************/
+
+                                                       DPRINTK("The selected second counter operating mode is wrong\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       }
+                               } else {
+                   /********************************************************/
+                                       /* The selected first counter operating option is wrong */
+                   /********************************************************/
+
+                                       DPRINTK("The selected first counter operating option is wrong\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /******************************************************/
+                               /* The selected first counter operating mode is wrong */
+                /******************************************************/
+                               DPRINTK("The selected first counter operating mode is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /***************************************/
+                       /* The selected counter range is wrong */
+             /***************************************/
+
+                       DPRINTK("The selected counter range is wrong\n");
+                       i_ReturnValue = -3;
+               }
+
+          /*************************/
+               /* Test if a error occur */
+          /*************************/
+
+               if (i_ReturnValue == 0) {
+             /**************************/
+                       /* Test if 16-Bit counter */
+             /**************************/
+
+                       if (b_CounterRange == APCI1710_32BIT_COUNTER) {
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister1 = b_CounterRange |
+                                       b_FirstCounterModus |
+                                       b_FirstCounterOption;
+                       } else {
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister1 = b_CounterRange |
+                                       (b_FirstCounterModus & 0x5) |
+                                       (b_FirstCounterOption & 0x20) |
+                                       (b_SecondCounterModus & 0xA) |
+                                       (b_SecondCounterOption & 0x40);
+
+                /***********************/
+                               /* Test if direct mode */
+                /***********************/
+
+                               if (b_FirstCounterModus == APCI1710_DIRECT_MODE) {
+                                       devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister1 = devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister1 |
+                                               APCI1710_DIRECT_MODE;
+                               }
+                       }
+
+             /***************************/
+                       /* Write the configuration */
+             /***************************/
+
+                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               dw_ModeRegister1_2_3_4,
+                               devpriv->s_BoardInfos.
+                               ui_Address + 20 + (64 * b_ModulNbr));
+
+                       devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_CounterInit = 1;
+               }
+       } else {
+          /**************************************/
+               /* The module is not a counter module */
+          /**************************************/
+
+               DPRINTK("The module is not a counter module\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_CounterAutoTest                       |
+|                                               (BYTE_     b_BoardHandle,    |
+|                                                PBYTE_   pb_TestStatus)     |
++----------------------------------------------------------------------------+
+| Task              : A test mode is intended for testing the component and  |
+|                     the connected periphery. All the 8-bit counter chains  |
+|                     are operated internally as down counters.              |
+|                     Independently from the external signals,               |
+|                     all the four 8-bit counter chains are decremented in   |
+|                     parallel by each negative clock pulse edge of CLKX.    |
+|                                                                            |
+|                       Counter auto test conclusion                         |
+|                       ----------------------------                         |
+|              +-----------------+-----------------------------+             |
+|              | pb_TestStatus   |    Error description        |             |
+|              |     mask        |                             |             |
+|              |-----------------+-----------------------------|             |
+|              |    0000         |     No error detected       |             |
+|              |-----------------|-----------------------------|             |
+|              |    0001         | Error detected of counter 0 |             |
+|              |-----------------|-----------------------------|             |
+|              |    0010         | Error detected of counter 1 |             |
+|              |-----------------|-----------------------------|             |
+|              |    0100         | Error detected of counter 2 |             |
+|              |-----------------|-----------------------------|             |
+|              |    1000         | Error detected of counter 3 |             |
+|              +-----------------+-----------------------------+             |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle : Handle of board APCI-1710      |  |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_TestStatus  : Auto test conclusion. See table|
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_CounterAutoTest(comedi_device * dev, PBYTE pb_TestStatus)
+{
+       BYTE b_ModulCpt = 0;
+       INT i_ReturnValue = 0;
+       DWORD dw_LathchValue;
+
+       *pb_TestStatus = 0;
+
+       /********************************/
+       /* Test if counter module found */
+       /********************************/
+
+       if ((devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[0] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER
+               || (devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[1] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER
+               || (devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[2] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER
+               || (devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[3] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER) {
+               for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) {
+             /*******************************/
+                       /* Test if incremental counter */
+             /*******************************/
+
+                       if ((devpriv->s_BoardInfos.
+                                       dw_MolduleConfiguration[b_ModulCpt] &
+                                       0xFFFF0000UL) ==
+                               APCI1710_INCREMENTAL_COUNTER) {
+                /******************/
+                               /* Start the test */
+                /******************/
+
+                               outl(3, devpriv->s_BoardInfos.
+                                       ui_Address + 16 + (64 * b_ModulCpt));
+
+                /*********************/
+                               /* Tatch the counter */
+                /*********************/
+
+                               outl(1, devpriv->s_BoardInfos.
+                                       ui_Address + (64 * b_ModulCpt));
+
+                /************************/
+                               /* Read the latch value */
+                /************************/
+
+                               dw_LathchValue = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 4 + (64 * b_ModulCpt));
+
+                               if ((dw_LathchValue & 0xFF) !=
+                                       ((dw_LathchValue >> 8) & 0xFF)
+                                       && (dw_LathchValue & 0xFF) !=
+                                       ((dw_LathchValue >> 16) & 0xFF)
+                                       && (dw_LathchValue & 0xFF) !=
+                                       ((dw_LathchValue >> 24) & 0xFF)) {
+                                       *pb_TestStatus =
+                                               *pb_TestStatus | (1 <<
+                                               b_ModulCpt);
+                               }
+
+                /*****************/
+                               /* Stop the test */
+                /*****************/
+
+                               outl(0, devpriv->s_BoardInfos.
+                                       ui_Address + 16 + (64 * b_ModulCpt));
+                       }
+               }
+       } else {
+          /***************************/
+               /* No counter module found */
+          /***************************/
+
+               DPRINTK("No counter module found\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitIndex (BYTE_ b_BoardHandle,       |
+|                                                 BYTE_ b_ModulNbr,          |
+|                                                 BYTE_ b_ReferenceAction,   |
+|                                                 BYTE_ b_IndexOperation,    |
+|                                                 BYTE_ b_AutoMode,          |
+|                                                 BYTE_ b_InterruptEnable)   |
++----------------------------------------------------------------------------+
+| Task              : Initialise the index corresponding to the selected     |
+|                     module (b_ModulNbr). If a INDEX flag occur, you have   |
+|                     the possibility to clear the 32-Bit counter or to latch|
+|                     the current 32-Bit value in to the first latch         |
+|                     register. The b_IndexOperation parameter give the      |
+|                     possibility to choice the INDEX action.                |
+|                     If you have enabled the automatic mode, each INDEX     |
+|                     action is cleared automatically, else you must read    |
+|                     the index status ("i_APCI1710_ReadIndexStatus")        |
+|                     after each INDEX action.                               |
+|                                                                            |
+|                                                                            |
+|                               Index action                                 |
+|                               ------------                                 |
+|                                                                            |
+|           +------------------------+------------------------------------+  |
+|           |   b_IndexOperation     |         Operation                  |  |
+|           |------------------------+------------------------------------|  |
+|           |APCI1710_LATCH_COUNTER  | After a index signal, the counter  |  |
+|           |                        | value (32-Bit) is latched in to    |  |
+|           |                        | the first latch register           |  |
+|           |------------------------|------------------------------------|  |
+|           |APCI1710_CLEAR_COUNTER  | After a index signal, the counter  |  |
+|           |                        | value is cleared (32-Bit)          |  |
+|           +------------------------+------------------------------------+  |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
+|                     BYTE_ b_ReferenceAction : Determine if the reference   |
+|                                               must set or no for the       |
+|                                               acceptance from index        |
+|                                               APCI1710_ENABLE :            |
+|                                                  Reference must be set for |
+|                                                  accepted the index        |
+|                                               APCI1710_DISABLE :           |
+|                                                  Reference have not        |
+|                                                  importance                |
+|                     BYTE_ b_IndexOperation  : Index operating mode.        |
+|                                               See table.                   |
+|                     BYTE_ b_AutoMode        : Enable or disable the        |
+|                                               automatic index reset.       |
+|                                               APCI1710_ENABLE :            |
+|                                                 Enable the automatic mode  |
+|                                               APCI1710_DISABLE :           |
+|                                                 Disable the automatic mode |
+|                     BYTE_ b_InterruptEnable : Enable or disable the        |
+|                                               interrupt.                   |
+|                                               APCI1710_ENABLE :            |
+|                                               Enable the interrupt         |
+|                                               APCI1710_DISABLE :           |
+|                                               Disable the interrupt        |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4  The reference action parameter is wrong            |
+|                     -5: The index operating mode parameter is wrong        |
+|                     -6: The auto mode parameter is wrong                   |
+|                     -7: Interrupt parameter is wrong                       |
+|                     -8: Interrupt function not initialised.                |
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitIndex(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_ReferenceAction,
+       BYTE b_IndexOperation, BYTE b_AutoMode, BYTE b_InterruptEnable)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /********************************/
+                       /* Test the reference parameter */
+             /********************************/
+
+                       if (b_ReferenceAction == APCI1710_ENABLE ||
+                               b_ReferenceAction == APCI1710_DISABLE) {
+                /****************************/
+                               /* Test the index parameter */
+                /****************************/
+
+                               if (b_IndexOperation ==
+                                       APCI1710_HIGH_EDGE_LATCH_COUNTER
+                                       || b_IndexOperation ==
+                                       APCI1710_LOW_EDGE_LATCH_COUNTER
+                                       || b_IndexOperation ==
+                                       APCI1710_HIGH_EDGE_CLEAR_COUNTER
+                                       || b_IndexOperation ==
+                                       APCI1710_LOW_EDGE_CLEAR_COUNTER
+                                       || b_IndexOperation ==
+                                       APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER
+                                       || b_IndexOperation ==
+                                       APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+                               {
+                   /********************************/
+                                       /* Test the auto mode parameter */
+                   /********************************/
+
+                                       if (b_AutoMode == APCI1710_ENABLE ||
+                                               b_AutoMode == APCI1710_DISABLE)
+                                       {
+                      /***************************/
+                                               /* Test the interrupt mode */
+                      /***************************/
+
+                                               if (b_InterruptEnable ==
+                                                       APCI1710_ENABLE
+                                                       || b_InterruptEnable ==
+                                                       APCI1710_DISABLE) {
+
+                            /************************************/
+                                                       /* Makte the configuration commando */
+                            /************************************/
+
+                                                       if (b_ReferenceAction ==
+                                                               APCI1710_ENABLE)
+                                                       {
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       |
+                                                                       APCI1710_ENABLE_INDEX_ACTION;
+                                                       } else {
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       &
+                                                                       APCI1710_DISABLE_INDEX_ACTION;
+                                                       }
+
+                            /****************************************/
+                                                       /* Test if low level latch or/and clear */
+                            /****************************************/
+
+                                                       if (b_IndexOperation ==
+                                                               APCI1710_LOW_EDGE_LATCH_COUNTER
+                                                               ||
+                                                               b_IndexOperation
+                                                               ==
+                                                               APCI1710_LOW_EDGE_CLEAR_COUNTER
+                                                               ||
+                                                               b_IndexOperation
+                                                               ==
+                                                               APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+                                                       {
+                               /*************************************/
+                                                               /* Set the index level to low (DQ26) */
+                               /*************************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       |
+                                                                       APCI1710_SET_LOW_INDEX_LEVEL;
+                                                       } else {
+                               /**************************************/
+                                                               /* Set the index level to high (DQ26) */
+                               /**************************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       &
+                                                                       APCI1710_SET_HIGH_INDEX_LEVEL;
+                                                       }
+
+                            /***********************************/
+                                                       /* Test if latch and clear counter */
+                            /***********************************/
+
+                                                       if (b_IndexOperation ==
+                                                               APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER
+                                                               ||
+                                                               b_IndexOperation
+                                                               ==
+                                                               APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+                                                       {
+                               /***************************************/
+                                                               /* Set the latch and clear flag (DQ27) */
+                               /***************************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       |
+                                                                       APCI1710_ENABLE_LATCH_AND_CLEAR;
+                                                       }       // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+                                                       else {
+                               /*****************************************/
+                                                               /* Clear the latch and clear flag (DQ27) */
+                               /*****************************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       &
+                                                                       APCI1710_DISABLE_LATCH_AND_CLEAR;
+
+                               /*************************/
+                                                               /* Test if latch counter */
+                               /*************************/
+
+                                                               if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER) {
+                                  /*********************************/
+                                                                       /* Enable the latch from counter */
+                                  /*********************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister2
+                                                                               =
+                                                                               devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister2
+                                                                               |
+                                                                               APCI1710_INDEX_LATCH_COUNTER;
+                                                               } else {
+                                  /*********************************/
+                                                                       /* Enable the clear from counter */
+                                  /*********************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister2
+                                                                               =
+                                                                               devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister2
+                                                                               &
+                                                                               (~APCI1710_INDEX_LATCH_COUNTER);
+                                                               }
+                                                       }       // // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+
+                                                       if (b_AutoMode ==
+                                                               APCI1710_DISABLE)
+                                                       {
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       |
+                                                                       APCI1710_INDEX_AUTO_MODE;
+                                                       } else {
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister2
+                                                                       &
+                                                                       (~APCI1710_INDEX_AUTO_MODE);
+                                                       }
+
+                                                       if (b_InterruptEnable ==
+                                                               APCI1710_ENABLE)
+                                                       {
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister3
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister3
+                                                                       |
+                                                                       APCI1710_ENABLE_INDEX_INT;
+                                                       } else {
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister3
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister3
+                                                                       &
+                                                                       APCI1710_DISABLE_INDEX_INT;
+                                                       }
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_SiemensCounterInfo.
+                                                               s_InitFlag.
+                                                               b_IndexInit = 1;
+
+                                               } else {
+                         /********************************/
+                                                       /* Interrupt parameter is wrong */
+                         /********************************/
+                                                       DPRINTK("Interrupt parameter is wrong\n");
+                                                       i_ReturnValue = -7;
+                                               }
+                                       } else {
+                      /************************************/
+                                               /* The auto mode parameter is wrong */
+                      /************************************/
+
+                                               DPRINTK("The auto mode parameter is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }
+                               } else {
+                   /***********************************************/
+                                       /* The index operating mode parameter is wrong */
+                   /***********************************************/
+
+                                       DPRINTK("The index operating mode parameter is wrong\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*******************************************/
+                               /* The reference action parameter is wrong */
+                /*******************************************/
+
+                               DPRINTK("The reference action parameter is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitReference                         |
+|                                                (BYTE_ b_BoardHandle,       |
+|                                                 BYTE_ b_ModulNbr,          |
+|                                                 BYTE_ b_ReferenceLevel)    |
++----------------------------------------------------------------------------+
+| Task              : Initialise the reference corresponding to the selected |
+|                     module (b_ModulNbr).                                   |
+|                                                                            |
+|                               Reference level                              |
+|                               ---------------                              |
+|             +--------------------+-------------------------+               |
+|             | b_ReferenceLevel   |         Operation       |               |
+|             +--------------------+-------------------------+               |
+|             |   APCI1710_LOW     |  Reference occur if "0" |               |
+|             |--------------------|-------------------------|               |
+|             |   APCI1710_HIGH    |  Reference occur if "1" |               |
+|             +--------------------+-------------------------+               |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
+|                     BYTE_ b_ReferenceLevel  : Reference level.             |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: The selected module number parameter is wrong      |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Reference level parameter is wrong                 |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitReference(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_ReferenceLevel)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /**************************************/
+                       /* Test the reference level parameter */
+             /**************************************/
+
+                       if (b_ReferenceLevel == 0 || b_ReferenceLevel == 1) {
+                               if (b_ReferenceLevel == 1) {
+                                       devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister2 = devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister2 |
+                                               APCI1710_REFERENCE_HIGH;
+                               } else {
+                                       devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister2 = devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister2 &
+                                               APCI1710_REFERENCE_LOW;
+                               }
+
+                               outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       dw_ModeRegister1_2_3_4,
+                                       devpriv->s_BoardInfos.ui_Address + 20 +
+                                       (64 * b_ModulNbr));
+
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_InitFlag.b_ReferenceInit = 1;
+                       } else {
+                /**************************************/
+                               /* Reference level parameter is wrong */
+                /**************************************/
+
+                               DPRINTK("Reference level parameter is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_    i_APCI1710_InitExternalStrobe                |
+|                                      (BYTE_ b_BoardHandle,                |
+|                                       BYTE_ b_ModulNbr,                   |
+|                                       BYTE_ b_ExternalStrobe,             |
+|                                       BYTE_ b_ExternalStrobeLevel)        |
++----------------------------------------------------------------------------+
+| Task              : Initialises the external strobe level corresponding to |
+|                    the selected module (b_ModulNbr).                      |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
+|                    BYTE_ b_ExternalStrobe  : External strobe selection    |
+|                                              0 : External strobe A        |
+|                                              1 : External strobe B        |
+|                    BYTE_ b_ExternalStrobeLevel : External strobe level    |
+|                                              APCI1710_LOW :               |
+|                                              External latch occurs if "0" |
+|                                              APCI1710_HIGH :              |
+|                                              External latch occurs if "1" |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: The selected module number is wrong                |
+|                     -3: Counter not initialised.                           |
+|                        See function "i_APCI1710_InitCounter"              |
+|                     -4: External strobe selection is wrong                 |
+|                     -5: External strobe level parameter is wrong           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitExternalStrobe(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_ExternalStrobe, BYTE b_ExternalStrobeLevel)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /**************************************/
+                       /* Test the external strobe selection */
+             /**************************************/
+
+                       if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) {
+                /******************/
+                               /* Test the level */
+                /******************/
+
+                               if ((b_ExternalStrobeLevel == APCI1710_HIGH) ||
+                                       ((b_ExternalStrobeLevel == APCI1710_LOW
+                                                       && (devpriv->
+                                                               s_BoardInfos.
+                                                               dw_MolduleConfiguration
+                                                               [b_ModulNbr] &
+                                                               0xFFFF) >=
+                                                       0x3135))) {
+                   /*****************/
+                                       /* Set the level */
+                   /*****************/
+
+                                       devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister4 = (devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister4 & (0xFF -
+                                                       (0x10 << b_ExternalStrobe))) | ((b_ExternalStrobeLevel ^ 1) << (4 + b_ExternalStrobe));
+                               } else {
+                   /********************************************/
+                                       /* External strobe level parameter is wrong */
+                   /********************************************/
+
+                                       DPRINTK("External strobe level parameter is wrong\n");
+                                       i_ReturnValue = -5;
+                               }
+                       }       // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)
+                       else {
+                /**************************************/
+                               /* External strobe selection is wrong */
+                /**************************************/
+
+                               DPRINTK("External strobe selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+       /*
+          +----------------------------------------------------------------------------+
+          | Function Name     : _INT_ i_APCI1710_InitCompareLogic                      |
+          |                               (BYTE_   b_BoardHandle,                      |
+          |                                BYTE_   b_ModulNbr,                         |
+          |                                UINT_  ui_CompareValue)                     |
+          +----------------------------------------------------------------------------+
+          | Task              : Set the 32-Bit compare value. At that moment that the  |
+          |                     incremental counter arrive to the compare value        |
+          |                     (ui_CompareValue) a interrupt is generated.            |
+          +----------------------------------------------------------------------------+
+          | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+          |                     BYTE_  b_ModulNbr       : Module number to configure   |
+          |                                               (0 to 3)                     |
+          |                     UINT_ ui_CompareValue   : 32-Bit compare value         |
+          +----------------------------------------------------------------------------+
+          | Output Parameters : -
+          +----------------------------------------------------------------------------+
+          | Return Value      :  0: No error                                           |
+          |                     -1: The handle parameter of the board is wrong         |
+          |                     -2: No counter module found                            |
+          |                     -3: Counter not initialised see function               |
+          |                         "i_APCI1710_InitCounter"                           |
+          +----------------------------------------------------------------------------+
+        */
+
+INT i_APCI1710_InitCompareLogic(comedi_device * dev,
+       BYTE b_ModulNbr, UINT ui_CompareValue)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+
+                       outl(ui_CompareValue, devpriv->s_BoardInfos.
+                               ui_Address + 28 + (64 * b_ModulNbr));
+
+                       devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_CompareLogicInit = 1;
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitFrequencyMeasurement              |
+|                              (BYTE_           b_BoardHandle,              |
+|                               BYTE_           b_ModulNbr,                 |
+|                               BYTE_           b_PCIInputClock,            |
+|                               BYTE_           b_TimingUnity,              |
+|                               ULONG_         ul_TimingInterval,           |
+|                               PULONG_       pul_RealTimingInterval)       |
++----------------------------------------------------------------------------+
+| Task              : Sets the time for the frequency measurement.           |
+|                    Configures the selected TOR incremental counter of the |
+|                    selected module (b_ModulNbr). The ul_TimingInterval and|
+|                    ul_TimingUnity determine the time base for the         |
+|                    measurement. The pul_RealTimingInterval returns the    |
+|                    real time value. You must call up this function before |
+|                    you call up any other function which gives access to   |
+|                    the frequency measurement.                             |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |
+|                                              configured (0 to 3)          |
+|                    BYTE_  b_PCIInputClock  : Selection of the PCI bus     |
+|                                              clock                        |
+|                                              - APCI1710_30MHZ :           |
+|                                                The PC has a PCI bus clock |
+|                                                of 30 MHz                  |
+|                                              - APCI1710_33MHZ :           |
+|                                                The PC has a PCI bus clock |
+|                                                of 33 MHz                  |
+|                    BYTE_  b_TimingUnity    : Base time unit (0 to 2)      |
+|                                                0 : ns                     |
+|                                                1 : Ã¦s                     |
+|                                                2 : ms                     |
+|                    ULONG_ ul_TimingInterval: Base time value.             |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_RealTimingInterval : Real base time value. |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: The selected module number is wrong                |
+|                     -3: Counter not initialised see function               |
+|                        "i_APCI1710_InitCounter"                           |
+|                     -4: The selected PCI input clock is wrong              |
+|                     -5: Timing unity selection is wrong                    |
+|                     -6: Base timing selection is wrong                     |
+|                    -7: 40MHz quartz not on board                          |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitFrequencyMeasurement(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PCIInputClock,
+       BYTE b_TimingUnity,
+       ULONG ul_TimingInterval, PULONG pul_RealTimingInterval)
+{
+       INT i_ReturnValue = 0;
+       ULONG ul_TimerValue = 0;
+       double d_RealTimingInterval;
+       DWORD dw_Status = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /**************************/
+                       /* Test the PCI bus clock */
+             /**************************/
+
+                       if ((b_PCIInputClock == APCI1710_30MHZ) ||
+                               (b_PCIInputClock == APCI1710_33MHZ) ||
+                               (b_PCIInputClock == APCI1710_40MHZ)) {
+                /************************/
+                               /* Test the timing unit */
+                /************************/
+
+                               if (b_TimingUnity <= 2) {
+                   /**********************************/
+                                       /* Test the base timing selection */
+                   /**********************************/
+
+                                       if (((b_PCIInputClock == APCI1710_30MHZ)
+                                                       && (b_TimingUnity == 0)
+                                                       && (ul_TimingInterval >=
+                                                               266)
+                                                       && (ul_TimingInterval <=
+                                                               8738133UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_30MHZ)
+                                                       && (b_TimingUnity == 1)
+                                                       && (ul_TimingInterval >=
+                                                               1)
+                                                       && (ul_TimingInterval <=
+                                                               8738UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_30MHZ)
+                                                       && (b_TimingUnity == 2)
+                                                       && (ul_TimingInterval >=
+                                                               1)
+                                                       && (ul_TimingInterval <=
+                                                               8UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_33MHZ)
+                                                       && (b_TimingUnity == 0)
+                                                       && (ul_TimingInterval >=
+                                                               242)
+                                                       && (ul_TimingInterval <=
+                                                               7943757UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_33MHZ)
+                                                       && (b_TimingUnity == 1)
+                                                       && (ul_TimingInterval >=
+                                                               1)
+                                                       && (ul_TimingInterval <=
+                                                               7943UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_33MHZ)
+                                                       && (b_TimingUnity == 2)
+                                                       && (ul_TimingInterval >=
+                                                               1)
+                                                       && (ul_TimingInterval <=
+                                                               7UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_40MHZ)
+                                                       && (b_TimingUnity == 0)
+                                                       && (ul_TimingInterval >=
+                                                               200)
+                                                       && (ul_TimingInterval <=
+                                                               6553500UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_40MHZ)
+                                                       && (b_TimingUnity == 1)
+                                                       && (ul_TimingInterval >=
+                                                               1)
+                                                       && (ul_TimingInterval <=
+                                                               6553UL))
+                                               || ((b_PCIInputClock ==
+                                                               APCI1710_40MHZ)
+                                                       && (b_TimingUnity == 2)
+                                                       && (ul_TimingInterval >=
+                                                               1)
+                                                       && (ul_TimingInterval <=
+                                                               6UL))) {
+                      /**********************/
+                                               /* Test if 40MHz used */
+                      /**********************/
+
+                                               if (b_PCIInputClock ==
+                                                       APCI1710_40MHZ) {
+                         /******************************/
+                                                       /* Test if firmware >= Rev1.5 */
+                         /******************************/
+
+                                                       if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3135) {
+                            /*********************************/
+                                                               /* Test if 40MHz quartz on board */
+                            /*********************************/
+
+                                                               /*INPDW (ps_APCI1710Variable->
+                                                                  s_Board [b_BoardHandle].
+                                                                  s_BoardInfos.
+                                                                  ui_Address + 36 + (64 * b_ModulNbr), &dw_Status); */
+                                                               dw_Status =
+                                                                       inl
+                                                                       (devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 36 +
+                                                                       (64 * b_ModulNbr));
+
+                            /******************************/
+                                                               /* Test the quartz flag (DQ0) */
+                            /******************************/
+
+                                                               if ((dw_Status & 1) != 1) {
+                               /*****************************/
+                                                                       /* 40MHz quartz not on board */
+                               /*****************************/
+
+                                                                       DPRINTK("40MHz quartz not on board\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -7;
+                                                               }
+                                                       } else {
+                            /*****************************/
+                                                               /* 40MHz quartz not on board */
+                            /*****************************/
+                                                               DPRINTK("40MHz quartz not on board\n");
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }
+                                               }       // if (b_PCIInputClock == APCI1710_40MHZ)
+
+                      /***************************/
+                                               /* Test if not error occur */
+                      /***************************/
+
+                                               if (i_ReturnValue == 0) {
+                         /****************************/
+                                                       /* Test the INC_CPT version */
+                         /****************************/
+
+                                                       if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131) {
+
+                               /**********************/
+                                                               /* Test if 40MHz used */
+                               /**********************/
+
+                                                               if (b_PCIInputClock == APCI1710_40MHZ) {
+                                  /*********************************/
+                                                                       /* Enable the 40MHz quarz (DQ30) */
+                                  /*********************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister4
+                                                                               =
+                                                                               devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister4
+                                                                               |
+                                                                               APCI1710_ENABLE_40MHZ_FREQUENCY;
+                                                               }       // if (b_PCIInputClock == APCI1710_40MHZ)
+                                                               else {
+                                  /**********************************/
+                                                                       /* Disable the 40MHz quarz (DQ30) */
+                                  /**********************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister4
+                                                                               =
+                                                                               devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_SiemensCounterInfo.
+                                                                               s_ModeRegister.
+                                                                               s_ByteModeRegister.
+                                                                               b_ModeRegister4
+                                                                               &
+                                                                               APCI1710_DISABLE_40MHZ_FREQUENCY;
+
+                                                               }       // if (b_PCIInputClock == APCI1710_40MHZ)
+
+                            /********************************/
+                                                               /* Calculate the division fator */
+                            /********************************/
+
+                                                               fpu_begin();
+                                                               switch (b_TimingUnity) {
+                               /******/
+                                                                       /* ns */
+                               /******/
+
+                                                               case 0:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_TimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_TimingInterval
+                                                                               *
+                                                                               (0.00025 * b_PCIInputClock));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       *pul_RealTimingInterval
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_TimerValue
+                                                                               /
+                                                                               (0.00025 * (double)b_PCIInputClock));
+                                                                       d_RealTimingInterval
+                                                                               =
+                                                                               (double)
+                                                                               ul_TimerValue
+                                                                               /
+                                                                               (0.00025
+                                                                               *
+                                                                               (double)
+                                                                               b_PCIInputClock);
+
+                                                                       if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
+                                                                               *pul_RealTimingInterval
+                                                                                       =
+                                                                                       *pul_RealTimingInterval
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_TimingInterval
+                                                                               =
+                                                                               ul_TimingInterval
+                                                                               -
+                                                                               1;
+                                                                       ul_TimerValue
+                                                                               =
+                                                                               ul_TimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       break;
+
+                               /******/
+                                                                       /* Ã¦s */
+                               /******/
+
+                                                               case 1:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_TimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_TimingInterval
+                                                                               *
+                                                                               (0.25 * b_PCIInputClock));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       *pul_RealTimingInterval
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_TimerValue
+                                                                               /
+                                                                               (0.25 * (double)b_PCIInputClock));
+                                                                       d_RealTimingInterval
+                                                                               =
+                                                                               (double)
+                                                                               ul_TimerValue
+                                                                               /
+                                                                               (
+                                                                               (double)
+                                                                               0.25
+                                                                               *
+                                                                               (double)
+                                                                               b_PCIInputClock);
+
+                                                                       if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
+                                                                               *pul_RealTimingInterval
+                                                                                       =
+                                                                                       *pul_RealTimingInterval
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_TimingInterval
+                                                                               =
+                                                                               ul_TimingInterval
+                                                                               -
+                                                                               1;
+                                                                       ul_TimerValue
+                                                                               =
+                                                                               ul_TimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       break;
+
+                               /******/
+                                                                       /* ms */
+                               /******/
+
+                                                               case 2:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_TimerValue
+                                                                               =
+                                                                               ul_TimingInterval
+                                                                               *
+                                                                               (250.0
+                                                                               *
+                                                                               b_PCIInputClock);
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       *pul_RealTimingInterval
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_TimerValue
+                                                                               /
+                                                                               (250.0 * (double)b_PCIInputClock));
+                                                                       d_RealTimingInterval
+                                                                               =
+                                                                               (double)
+                                                                               ul_TimerValue
+                                                                               /
+                                                                               (250.0
+                                                                               *
+                                                                               (double)
+                                                                               b_PCIInputClock);
+
+                                                                       if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
+                                                                               *pul_RealTimingInterval
+                                                                                       =
+                                                                                       *pul_RealTimingInterval
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_TimingInterval
+                                                                               =
+                                                                               ul_TimingInterval
+                                                                               -
+                                                                               1;
+                                                                       ul_TimerValue
+                                                                               =
+                                                                               ul_TimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       break;
+                                                               }
+
+                                                               fpu_end();
+                            /*************************/
+                                                               /* Write the timer value */
+                            /*************************/
+
+                                                               outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 32 + (64 * b_ModulNbr));
+
+                            /*******************************/
+                                                               /* Set the initialisation flag */
+                            /*******************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_InitFlag.
+                                                                       b_FrequencyMeasurementInit
+                                                                       = 1;
+                                                       } else {
+                            /***************************/
+                                                               /* Counter not initialised */
+                            /***************************/
+
+                                                               DPRINTK("Counter not initialised\n");
+                                                               i_ReturnValue =
+                                                                       -3;
+                                                       }
+                                               }       // if (i_ReturnValue == 0)
+                                       } else {
+                      /**********************************/
+                                               /* Base timing selection is wrong */
+                      /**********************************/
+
+                                               DPRINTK("Base timing selection is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }
+                               } else {
+                   /***********************************/
+                                       /* Timing unity selection is wrong */
+                   /***********************************/
+
+                                       DPRINTK("Timing unity selection is wrong\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /*****************************************/
+                               /* The selected PCI input clock is wrong */
+                /*****************************************/
+
+                               DPRINTK("The selected PCI input clock is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*########################################################################### */
+
+                                                       //INSN BITS
+/*########################################################################### */
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT       i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s,
+comedi_insn *insn,lsampl_t *data)                   |
++----------------------------------------------------------------------------+
+| Task              : Set & Clear Functions for INC_CPT                                          |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_BitsType;
+       INT i_ReturnValue = 0;
+       ui_BitsType = CR_CHAN(insn->chanspec);
+       devpriv->tsk_Current = current; // Save the current process task structure
+
+       switch (ui_BitsType) {
+       case APCI1710_INCCPT_CLEARCOUNTERVALUE:
+               i_ReturnValue = i_APCI1710_ClearCounterValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_CLEARALLCOUNTERVALUE:
+               i_ReturnValue = i_APCI1710_ClearAllCounterValue(dev);
+               break;
+
+       case APCI1710_INCCPT_SETINPUTFILTER:
+               i_ReturnValue = i_APCI1710_SetInputFilter(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) data[0], (BYTE) data[1]);
+               break;
+
+       case APCI1710_INCCPT_LATCHCOUNTER:
+               i_ReturnValue = i_APCI1710_LatchCounter(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+               break;
+
+       case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE:
+               i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+               break;
+
+       case APCI1710_INCCPT_SETDIGITALCHLON:
+               i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_SETDIGITALCHLOFF:
+               i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       default:
+               printk("Bits Config Parameter Wrong\n");
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ClearCounterValue                     |
+|                               (BYTE_      b_BoardHandle,                   |
+|                                BYTE_       b_ModulNbr)                     |
++----------------------------------------------------------------------------+
+| Task              : Clear the counter value from selected module           |
+|                     (b_ModulNbr).                                          |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+|                     BYTE_ b_ModulNbr    : Module number to configure       |
+|                                           (0 to 3)                         |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: The selected module number parameter is wrong      |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ClearCounterValue(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*********************/
+                       /* Clear the counter */
+             /*********************/
+
+                       outl(1, devpriv->s_BoardInfos.
+                               ui_Address + 16 + (64 * b_ModulNbr));
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ClearAllCounterValue                  |
+|                               (BYTE_      b_BoardHandle)                   |
++----------------------------------------------------------------------------+
+| Task              : Clear all counter value.                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ClearAllCounterValue(comedi_device * dev)
+{
+       BYTE b_ModulCpt = 0;
+       INT i_ReturnValue = 0;
+
+       /********************************/
+       /* Test if counter module found */
+       /********************************/
+
+       if ((devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[0] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER
+               || (devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[1] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER
+               || (devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[2] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER
+               || (devpriv->s_BoardInfos.
+                       dw_MolduleConfiguration[3] & 0xFFFF0000UL) ==
+               APCI1710_INCREMENTAL_COUNTER) {
+               for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) {
+             /*******************************/
+                       /* Test if incremental counter */
+             /*******************************/
+
+                       if ((devpriv->s_BoardInfos.
+                                       dw_MolduleConfiguration[b_ModulCpt] &
+                                       0xFFFF0000UL) ==
+                               APCI1710_INCREMENTAL_COUNTER) {
+                /*********************/
+                               /* Clear the counter */
+                /*********************/
+
+                               outl(1, devpriv->s_BoardInfos.
+                                       ui_Address + 16 + (64 * b_ModulCpt));
+                       }
+               }
+       } else {
+          /***************************/
+               /* No counter module found */
+          /***************************/
+
+               DPRINTK("No counter module found\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_SetInputFilter                        |
+|                                      (BYTE_ b_BoardHandle,                |
+|                                       BYTE_ b_Module,                     |
+|                                       BYTE_ b_PCIInputClock,              |
+|                                       BYTE_ b_Filter)                     |
++----------------------------------------------------------------------------+
+| Task              : Disable or enable the software filter from selected    |
+|                    module (b_ModulNbr). b_Filter determine the filter time|
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |
+|                                              configured (0 to 3)          |
+|                    BYTE_  b_PCIInputClock  : Selection of the PCI bus     |
+|                                              clock                        |
+|                                              - APCI1710_30MHZ :           |
+|                                                The PC has a PCI bus clock |
+|                                                of 30 MHz                  |
+|                                              - APCI1710_33MHZ :           |
+|                                                The PC has a PCI bus clock |
+|                                                of 33 MHz                  |
+|                                              - APCI1710_40MHZ :           |
+|                                                The APCI1710 has a 40MHz    |
+|                                                quartz                     |
+|                    BYTE_  b_Filter         : Filter selection             |
+|                                                                            |
+|                              30 MHz                                       |
+|                              ------                                       |
+|                                      0:  Software filter not used         |
+|                                      1:  Filter from 266ns  (3.750000MHz) |
+|                                      2:  Filter from 400ns  (2.500000MHz) |
+|                                      3:  Filter from 533ns  (1.876170MHz) |
+|                                      4:  Filter from 666ns  (1.501501MHz) |
+|                                      5:  Filter from 800ns  (1.250000MHz) |
+|                                      6:  Filter from 933ns  (1.071800MHz) |
+|                                      7:  Filter from 1066ns (0.938080MHz) |
+|                                      8:  Filter from 1200ns (0.833333MHz) |
+|                                      9:  Filter from 1333ns (0.750000MHz) |
+|                                      10: Filter from 1466ns (0.682100MHz) |
+|                                      11: Filter from 1600ns (0.625000MHz) |
+|                                      12: Filter from 1733ns (0.577777MHz) |
+|                                      13: Filter from 1866ns (0.535900MHz) |
+|                                      14: Filter from 2000ns (0.500000MHz) |
+|                                      15: Filter from 2133ns (0.468800MHz) |
+|                                                                           |
+|                              33 MHz                                       |
+|                              ------                                       |
+|                                      0:  Software filter not used         |
+|                                      1:  Filter from 242ns  (4.125000MHz) |
+|                                      2:  Filter from 363ns  (2.754820MHz) |
+|                                      3:  Filter from 484ns  (2.066115MHz) |
+|                                      4:  Filter from 605ns  (1.652892MHz) |
+|                                      5:  Filter from 726ns  (1.357741MHz) |
+|                                      6:  Filter from 847ns  (1.180637MHz) |
+|                                      7:  Filter from 968ns  (1.033055MHz) |
+|                                      8:  Filter from 1089ns (0.918273MHz) |
+|                                      9:  Filter from 1210ns (0.826446MHz) |
+|                                      10: Filter from 1331ns (0.751314MHz) |
+|                                      11: Filter from 1452ns (0.688705MHz) |
+|                                      12: Filter from 1573ns (0.635727MHz) |
+|                                      13: Filter from 1694ns (0.590318MHz) |
+|                                      14: Filter from 1815ns (0.550964MHz) |
+|                                      15: Filter from 1936ns (0.516528MHz) |
+|                                                                           |
+|                              40 MHz                                       |
+|                              ------                                       |
+|                                      0:  Software filter not used         |
+|                                      1:  Filter from 200ns  (5.000000MHz) |
+|                                      2:  Filter from 300ns  (3.333333MHz) |
+|                                      3:  Filter from 400ns  (2.500000MHz) |
+|                                      4:  Filter from 500ns  (2.000000MHz) |
+|                                      5:  Filter from 600ns  (1.666666MHz) |
+|                                      6:  Filter from 700ns  (1.428500MHz) |
+|                                      7:  Filter from 800ns  (1.250000MHz) |
+|                                      8:  Filter from 900ns  (1.111111MHz) |
+|                                      9:  Filter from 1000ns (1.000000MHz) |
+|                                      10: Filter from 1100ns (0.909090MHz) |
+|                                      11: Filter from 1200ns (0.833333MHz) |
+|                                      12: Filter from 1300ns (0.769200MHz) |
+|                                      13: Filter from 1400ns (0.714200MHz) |
+|                                      14: Filter from 1500ns (0.666666MHz) |
+|                                      15: Filter from 1600ns (0.625000MHz) |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: The selected module number is wrong                |
+|                     -3: The module is not a counter module                 |
+|                                        -4: The selected PCI input clock is wrong              |
+|                                        -5: The selected filter value is wrong                 |
+|                                        -6: 40MHz quartz not on board                          |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetInputFilter(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_PCIInputClock, BYTE b_Filter)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if incremental counter */
+          /*******************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
+             /******************************/
+                       /* Test if firmware >= Rev1.5 */
+             /******************************/
+
+                       if ((devpriv->s_BoardInfos.
+                                       dw_MolduleConfiguration[b_ModulNbr] &
+                                       0xFFFF) >= 0x3135) {
+                /**************************/
+                               /* Test the PCI bus clock */
+                /**************************/
+
+                               if ((b_PCIInputClock == APCI1710_30MHZ) ||
+                                       (b_PCIInputClock == APCI1710_33MHZ) ||
+                                       (b_PCIInputClock == APCI1710_40MHZ)) {
+                   /*************************/
+                                       /* Test the filter value */
+                   /*************************/
+
+                                       if (b_Filter < 16) {
+                      /**********************/
+                                               /* Test if 40MHz used */
+                      /**********************/
+
+                                               if (b_PCIInputClock ==
+                                                       APCI1710_40MHZ) {
+                         /*********************************/
+                                                       /* Test if 40MHz quartz on board */
+                         /*********************************/
+
+                                                       dw_Status =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               36 +
+                                                               (64 * b_ModulNbr));
+
+                         /******************************/
+                                                       /* Test the quartz flag (DQ0) */
+                         /******************************/
+
+                                                       if ((dw_Status & 1) !=
+                                                               1) {
+                            /*****************************/
+                                                               /* 40MHz quartz not on board */
+                            /*****************************/
+
+                                                               DPRINTK("40MHz quartz not on board\n");
+                                                               i_ReturnValue =
+                                                                       -6;
+                                                       }
+                                               }       // if (b_PCIInputClock == APCI1710_40MHZ)
+
+                      /***************************/
+                                               /* Test if error not occur */
+                      /***************************/
+
+                                               if (i_ReturnValue == 0) {
+                         /**********************/
+                                                       /* Test if 40MHz used */
+                         /**********************/
+
+                                                       if (b_PCIInputClock ==
+                                                               APCI1710_40MHZ)
+                                                       {
+                            /*********************************/
+                                                               /* Enable the 40MHz quarz (DQ31) */
+                            /*********************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       |
+                                                                       APCI1710_ENABLE_40MHZ_FILTER;
+
+                                                       }       // if (b_PCIInputClock == APCI1710_40MHZ)
+                                                       else {
+                            /**********************************/
+                                                               /* Disable the 40MHz quarz (DQ31) */
+                            /**********************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_SiemensCounterInfo.
+                                                                       s_ModeRegister.
+                                                                       s_ByteModeRegister.
+                                                                       b_ModeRegister4
+                                                                       &
+                                                                       APCI1710_DISABLE_40MHZ_FILTER;
+
+                                                       }       // if (b_PCIInputClock == APCI1710_40MHZ)
+
+                         /************************/
+                                                       /* Set the filter value */
+                         /************************/
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_SiemensCounterInfo.
+                                                               s_ModeRegister.
+                                                               s_ByteModeRegister.
+                                                               b_ModeRegister3
+                                                               =
+                                                               (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_SiemensCounterInfo.
+                                                               s_ModeRegister.
+                                                               s_ByteModeRegister.
+                                                               b_ModeRegister3
+                                                               & 0x1F) |
+                                                               ((b_Filter &
+                                                                       0x7) <<
+                                                               5);
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_SiemensCounterInfo.
+                                                               s_ModeRegister.
+                                                               s_ByteModeRegister.
+                                                               b_ModeRegister4
+                                                               =
+                                                               (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_SiemensCounterInfo.
+                                                               s_ModeRegister.
+                                                               s_ByteModeRegister.
+                                                               b_ModeRegister4
+                                                               & 0xFE) |
+                                                               ((b_Filter &
+                                                                       0x8) >>
+                                                               3);
+
+                         /***************************/
+                                                       /* Write the configuration */
+                         /***************************/
+
+                                                       outl(devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_SiemensCounterInfo.
+                                                               s_ModeRegister.
+                                                               dw_ModeRegister1_2_3_4,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               20 +
+                                                               (64 * b_ModulNbr));
+                                               }       // if (i_ReturnValue == 0)
+                                       }       // if (b_Filter < 16)
+                                       else {
+                      /**************************************/
+                                               /* The selected filter value is wrong */
+                      /**************************************/
+
+                                               DPRINTK("The selected filter value is wrong\n");
+                                               i_ReturnValue = -5;
+                                       }       // if (b_Filter < 16)
+                               }       // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))
+                               else {
+                   /*****************************************/
+                                       /* The selected PCI input clock is wrong */
+                   /*****************************************/
+
+                                       DPRINTK("The selected PCI input clock is wrong\n");
+                                       i_ReturnValue = 4;
+                               }       // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))
+                       } else {
+                /**************************************/
+                               /* The module is not a counter module */
+                /**************************************/
+
+                               DPRINTK("The module is not a counter module\n");
+                               i_ReturnValue = -3;
+                       }
+               } else {
+             /**************************************/
+                       /* The module is not a counter module */
+             /**************************************/
+
+                       DPRINTK("The module is not a counter module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_LatchCounter (BYTE_ b_BoardHandle,    |
+|                                                    BYTE_ b_ModulNbr,       |
+|                                                    BYTE_ b_LatchReg)       |
++----------------------------------------------------------------------------+
+| Task              : Latch the courant value from selected module           |
+|                     (b_ModulNbr) in to the selected latch register         |
+|                     (b_LatchReg).                                          |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+|                     BYTE_ b_ModulNbr    : Module number to configure       |
+|                                           (0 to 3)                         |
+|                     BYTE_ b_LatchReg    : Selected latch register          |
+|                               0 : for the first latch register             |
+|                               1 : for the second latch register            |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: The selected latch register parameter is wrong     |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_LatchCounter(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_LatchReg)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*************************************/
+                       /* Test the latch register parameter */
+             /*************************************/
+
+                       if (b_LatchReg < 2) {
+                /*********************/
+                               /* Tatch the counter */
+                /*********************/
+
+                               outl(1 << (b_LatchReg * 4),
+                                       devpriv->s_BoardInfos.ui_Address +
+                                       (64 * b_ModulNbr));
+                       } else {
+                /**************************************************/
+                               /* The selected latch register parameter is wrong */
+                /**************************************************/
+
+                               DPRINTK("The selected latch register parameter is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_    i_APCI1710_SetIndexAndReferenceSource        |
+|                                      (BYTE_ b_BoardHandle,                |
+|                                       BYTE_ b_ModulNbr,                   |
+|                                       BYTE_ b_SourceSelection)            |
++----------------------------------------------------------------------------+
+| Task              : Determine the hardware source for the index and the    |
+|                    reference logic. Per default the index logic is        |
+|                    connected to the difference input C and the reference  |
+|                    logic is connected to the 24V input E                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
+|                    BYTE_ b_SourceSelection : APCI1710_SOURCE_0 :          |
+|                                              The index logic is connected |
+|                                              to the difference input C and|
+|                                              the reference logic is       |
+|                                              connected to the 24V input E.|
+|                                              This is the default          |
+|                                              configuration.               |
+|                                              APCI1710_SOURCE_1 :          |
+|                                              The reference logic is       |
+|                                              connected to the difference  |
+|                                              input C and the index logic  |
+|                                              is connected to the 24V      |
+|                                              input E                      |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                    -2: The selected module number is wrong                |
+|                    -3: The module is not a counter module.                |
+|                    -4: The source selection is wrong                      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetIndexAndReferenceSource(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_SourceSelection)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if incremental counter */
+          /*******************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
+             /******************************/
+                       /* Test if firmware >= Rev1.5 */
+             /******************************/
+
+                       if ((devpriv->s_BoardInfos.
+                                       dw_MolduleConfiguration[b_ModulNbr] &
+                                       0xFFFF) >= 0x3135) {
+                /*****************************/
+                               /* Test the source selection */
+                /*****************************/
+
+                               if (b_SourceSelection == APCI1710_SOURCE_0 ||
+                                       b_SourceSelection == APCI1710_SOURCE_1)
+                               {
+                   /******************************************/
+                                       /* Test if invert the index and reference */
+                   /******************************************/
+
+                                       if (b_SourceSelection ==
+                                               APCI1710_SOURCE_1) {
+                      /********************************************/
+                                               /* Invert index and reference source (DQ25) */
+                      /********************************************/
+
+                                               devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SiemensCounterInfo.
+                                                       s_ModeRegister.
+                                                       s_ByteModeRegister.
+                                                       b_ModeRegister4 =
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SiemensCounterInfo.
+                                                       s_ModeRegister.
+                                                       s_ByteModeRegister.
+                                                       b_ModeRegister4 |
+                                                       APCI1710_INVERT_INDEX_RFERENCE;
+                                       } else {
+                      /****************************************/
+                                               /* Set the default configuration (DQ25) */
+                      /****************************************/
+
+                                               devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SiemensCounterInfo.
+                                                       s_ModeRegister.
+                                                       s_ByteModeRegister.
+                                                       b_ModeRegister4 =
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SiemensCounterInfo.
+                                                       s_ModeRegister.
+                                                       s_ByteModeRegister.
+                                                       b_ModeRegister4 &
+                                                       APCI1710_DEFAULT_INDEX_RFERENCE;
+                                       }
+                               }       // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)
+                               else {
+                   /*********************************/
+                                       /* The source selection is wrong */
+                   /*********************************/
+
+                                       DPRINTK("The source selection is wrong\n");
+                                       i_ReturnValue = -4;
+                               }       // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)
+                       } else {
+                /**************************************/
+                               /* The module is not a counter module */
+                /**************************************/
+
+                               DPRINTK("The module is not a counter module\n");
+                               i_ReturnValue = -3;
+                       }
+               } else {
+             /**************************************/
+                       /* The module is not a counter module */
+             /**************************************/
+
+                       DPRINTK("The module is not a counter module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***************************************/
+               /* The selected module number is wrong */
+          /***************************************/
+
+               DPRINTK("The selected module number is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_    i_APCI1710_SetDigitalChlOn                   |
+|                                 (BYTE_  b_BoardHandle,                    |
+|                                  BYTE_  b_ModulNbr)                       |
++----------------------------------------------------------------------------+
+| Task              : Sets the digital output H Setting an output means      |
+|                    setting an ouput high.                                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |
+|                                              configured (0 to 3)          |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: The selected module number is wrong                |
+|                     -3: Counter not initialised see function               |
+|                        "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetDigitalChlOn(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+                       devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.
+                               b_ModeRegister3 = devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.b_ModeRegister3 | 0x10;
+
+             /*********************/
+                       /* Set the output On */
+             /*********************/
+
+                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
+                               ui_Address + 20 + (64 * b_ModulNbr));
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_    i_APCI1710_SetDigitalChlOff                  |
+|                                 (BYTE_  b_BoardHandle,                    |
+|                                  BYTE_  b_ModulNbr)                       |
++----------------------------------------------------------------------------+
+| Task              : Resets the digital output H. Resetting an output means |
+|                    setting an ouput low.                                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |
+|                                              configured (0 to 3)          |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: The selected module number is wrong                |
+|                     -3: Counter not initialised see function               |
+|                        "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetDigitalChlOff(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+                       devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.
+                               b_ModeRegister3 = devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.b_ModeRegister3 & 0xEF;
+
+             /**********************/
+                       /* Set the output Off */
+             /**********************/
+
+                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
+                               ui_Address + 20 + (64 * b_ModulNbr));
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*########################################################################### */
+
+                                                       // INSN WRITE
+/*########################################################################### */
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT       i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,
+comedi_insn *insn,lsampl_t *data)                   |
++----------------------------------------------------------------------------+
+| Task              : Enable Disable functions for INC_CPT                                       |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_InsnWriteINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_WriteType;
+       INT i_ReturnValue = 0;
+
+       ui_WriteType = CR_CHAN(insn->chanspec);
+       devpriv->tsk_Current = current; // Save the current process task structure
+
+       switch (ui_WriteType) {
+       case APCI1710_INCCPT_ENABLELATCHINTERRUPT:
+               i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_DISABLELATCHINTERRUPT:
+               i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:
+               i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) data[0], (UINT) data[1]);
+               break;
+
+       case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
+               i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (ULONG) data[0]);
+
+               break;
+
+       case APCI1710_INCCPT_ENABLEINDEX:
+               i_APCI1710_EnableIndex(dev, (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_DISABLEINDEX:
+               i_ReturnValue = i_APCI1710_DisableIndex(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_ENABLECOMPARELOGIC:
+               i_ReturnValue = i_APCI1710_EnableCompareLogic(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_DISABLECOMPARELOGIC:
+               i_ReturnValue = i_APCI1710_DisableCompareLogic(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT:
+               i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+               break;
+
+       case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT:
+               i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev,
+                       (BYTE) CR_AREF(insn->chanspec));
+               break;
+
+       default:
+               printk("Write Config Parameter Wrong\n");
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_EnableLatchInterrupt                  |
+|                               (BYTE_ b_BoardHandle,                        |
+|                                BYTE_ b_ModulNbr)                           |
++----------------------------------------------------------------------------+
+| Task              : Enable the latch interrupt from selected module        |
+|                     (b_ModulNbr). Each software or hardware latch occur a  |
+|                     interrupt.                                             |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+|                     BYTE_ b_ModulNbr    : Module number to configure       |
+|                                           (0 to 3)                         |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Interrupt routine not installed see function       |
+|                         "i_APCI1710_SetBoardIntRoutine"                    |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+
+                /********************/
+                       /* Enable interrupt */
+                /********************/
+
+                       devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.
+                               b_ModeRegister2 = devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.
+                               b_ModeRegister2 | APCI1710_ENABLE_LATCH_INT;
+
+                /***************************/
+                       /* Write the configuration */
+                /***************************/
+
+                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
+                               ui_Address + 20 + (64 * b_ModulNbr));
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_DisableLatchInterrupt                 |
+|                               (BYTE_ b_BoardHandle,                        |
+|                                BYTE_ b_ModulNbr)                           |
++----------------------------------------------------------------------------+
+| Task              : Disable the latch interrupt from selected module       |
+|                     (b_ModulNbr).                                          |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+|                     BYTE_ b_ModulNbr    : Module number to configure       |
+|                                           (0 to 3)                         |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Interrupt routine not installed see function       |
+|                         "i_APCI1710_SetBoardIntRoutine"                    |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+
+                /***************************/
+                       /* Write the configuration */
+                /***************************/
+
+                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               dw_ModeRegister1_2_3_4 &
+                               ((APCI1710_DISABLE_LATCH_INT << 8) | 0xFF),
+                               devpriv->s_BoardInfos.ui_Address + 20 +
+                               (64 * b_ModulNbr));
+
+                       mdelay(1000);
+
+                /*********************/
+                       /* Disable interrupt */
+                /*********************/
+
+                       devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.
+                               b_ModeRegister2 = devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_ModeRegister.
+                               s_ByteModeRegister.
+                               b_ModeRegister2 & APCI1710_DISABLE_LATCH_INT;
+
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_Write16BitCounterValue                |
+|                                               (BYTE_  b_BoardHandle        |
+|                                                BYTE_  b_ModulNbr,          |
+|                                                BYTE_  b_SelectedCounter,   |
+|                                                UINT_ ui_WriteValue)        |
++----------------------------------------------------------------------------+
+| Task              : Write a 16-Bit value (ui_WriteValue) in to the selected|
+|                     16-Bit counter (b_SelectedCounter) from selected module|
+|                     (b_ModulNbr).                                          |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                              (0 to 3)                      |
+|                     BYTE_ b_SelectedCounter : Selected 16-Bit counter      |
+|                                               (0 or 1)                     |
+|                     UINT_ ui_WriteValue     : 16-Bit write value           |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: The selected 16-Bit counter parameter is wrong     |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Write16BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_SelectedCounter, UINT ui_WriteValue)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /******************************/
+                       /* Test the counter selection */
+             /******************************/
+
+                       if (b_SelectedCounter < 2) {
+                /*******************/
+                               /* Write the value */
+                /*******************/
+
+                               outl((ULONG) ((ULONG) (ui_WriteValue) << (16 *
+                                                       b_SelectedCounter)),
+                                       devpriv->s_BoardInfos.ui_Address + 8 +
+                                       (b_SelectedCounter * 4) +
+                                       (64 * b_ModulNbr));
+                       } else {
+                /**************************************************/
+                               /* The selected 16-Bit counter parameter is wrong */
+                /**************************************************/
+
+                               DPRINTK("The selected 16-Bit counter parameter is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_Write32BitCounterValue                |
+|                                               (BYTE_   b_BoardHandle       |
+|                                                BYTE_   b_ModulNbr,         |
+|                                                ULONG_ ul_WriteValue)       |
++----------------------------------------------------------------------------+
+| Task              : Write a 32-Bit value (ui_WriteValue) in to the selected|
+|                     module (b_ModulNbr).                                   |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                              (0 to 3)                      |
+|                     ULONG_ ul_WriteValue    : 32-Bit write value           |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Write32BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, ULONG ul_WriteValue)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*******************/
+                       /* Write the value */
+             /*******************/
+
+                       outl(ul_WriteValue, devpriv->s_BoardInfos.
+                               ui_Address + 4 + (64 * b_ModulNbr));
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_EnableIndex (BYTE_  b_BoardHandle,    |
+|                                                   BYTE_  b_ModulNbr)       |
++----------------------------------------------------------------------------+
+| Task              : Enable the INDEX actions                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Index not initialised see function                 |
+|                         "i_APCI1710_InitIndex"                             |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnableIndex(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+       ULONG ul_InterruptLatchReg;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*****************************/
+                       /* Test if index initialised */
+             /*****************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister2 = devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister2 | APCI1710_ENABLE_INDEX;
+
+                               ul_InterruptLatchReg =
+                                       inl(devpriv->s_BoardInfos.ui_Address +
+                                       24 + (64 * b_ModulNbr));
+
+                               outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       dw_ModeRegister1_2_3_4,
+                                       devpriv->s_BoardInfos.ui_Address + 20 +
+                                       (64 * b_ModulNbr));
+                       } else {
+                /*************************************************************/
+                               /* Index not initialised see function "i_APCI1710_InitIndex" */
+                /*************************************************************/
+
+                               DPRINTK("Index not initialised \n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_DisableIndex (BYTE_  b_BoardHandle,   |
+|                                                    BYTE_  b_ModulNbr)      |
++----------------------------------------------------------------------------+
+| Task              : Disable the INDEX actions                              |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Index not initialised see function                 |
+|                         "i_APCI1710_InitIndex"                             |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisableIndex(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*****************************/
+                       /* Test if index initialised */
+             /*****************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister2 = devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister2 &
+                                       APCI1710_DISABLE_INDEX;
+
+                               outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       dw_ModeRegister1_2_3_4,
+                                       devpriv->s_BoardInfos.ui_Address + 20 +
+                                       (64 * b_ModulNbr));
+                       } else {
+                /*************************************************************/
+                               /* Index not initialised see function "i_APCI1710_InitIndex" */
+                /*************************************************************/
+
+                               DPRINTK("Index not initialised  \n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_EnableCompareLogic                    |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr)                         |
++----------------------------------------------------------------------------+
+| Task              : Enable the 32-Bit compare logic. At that moment that   |
+|                     the incremental counter arrive to the compare value a  |
+|                     interrupt is generated.                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+|                     BYTE_  b_ModulNbr       : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : -
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Compare logic not initialised.                     |
+|                         See function "i_APCI1710_InitCompareLogic"         |
+|                     -5: Interrupt function not initialised.                |
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnableCompareLogic(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*************************************/
+                       /* Test if compare logic initialised */
+             /*************************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_CompareLogicInit == 1) {
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister3 = devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister3 |
+                                       APCI1710_ENABLE_COMPARE_INT;
+
+                   /***************************/
+                               /* Write the configuration */
+                   /***************************/
+
+                               outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       dw_ModeRegister1_2_3_4,
+                                       devpriv->s_BoardInfos.ui_Address + 20 +
+                                       (64 * b_ModulNbr));
+                       } else {
+                /*********************************/
+                               /* Compare logic not initialised */
+                /*********************************/
+
+                               DPRINTK("Compare logic not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_DisableCompareLogic                   |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr)                         |
++----------------------------------------------------------------------------+
+| Task              : Disable the 32-Bit compare logic.
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+|                     BYTE_  b_ModulNbr       : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : -
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Compare logic not initialised.                     |
+|                         See function "i_APCI1710_InitCompareLogic"         |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisableCompareLogic(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*************************************/
+                       /* Test if compare logic initialised */
+             /*************************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_CompareLogicInit == 1) {
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister3 = devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister3 &
+                                       APCI1710_DISABLE_COMPARE_INT;
+
+                /***************************/
+                               /* Write the configuration */
+                /***************************/
+
+                               outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       dw_ModeRegister1_2_3_4,
+                                       devpriv->s_BoardInfos.ui_Address + 20 +
+                                       (64 * b_ModulNbr));
+                       } else {
+                /*********************************/
+                               /* Compare logic not initialised */
+                /*********************************/
+
+                               DPRINTK("Compare logic not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+       /*
+          +----------------------------------------------------------------------------+
+          | Function Name     : _INT_ i_APCI1710_EnableFrequencyMeasurement            |
+          |                            (BYTE_   b_BoardHandle,                      |
+          |                             BYTE_   b_ModulNbr,                         |
+          |                             BYTE_   b_InterruptEnable)                  |
+          +----------------------------------------------------------------------------+
+          | Task              : Enables the frequency measurement function             |
+          +----------------------------------------------------------------------------+
+          | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+          |                  BYTE_  b_ModulNbr       : Number of the module to be   |
+          |                                            configured (0 to 3)          |
+          |                  BYTE_  b_InterruptEnable: Enable or disable the        |
+          |                                            interrupt.                   |
+          |                                            APCI1710_ENABLE:             |
+          |                                            Enable the interrupt         |
+          |                                            APCI1710_DISABLE:            |
+          |                                            Disable the interrupt        |
+          +----------------------------------------------------------------------------+
+          | Output Parameters : -                                                      |
+          +----------------------------------------------------------------------------+
+          | Return Value      :  0: No error                                           |
+          |                     -1: The handle parameter of the board is wrong         |
+          |                     -2: The selected module number is wrong                |
+          |                     -3: Counter not initialised see function               |
+          |                      "i_APCI1710_InitCounter"                           |
+          |                     -4: Frequency measurement logic not initialised.       |
+          |                      See function "i_APCI1710_InitFrequencyMeasurement" |
+          |                     -5: Interrupt parameter is wrong                       |
+          |                     -6: Interrupt function not initialised.                |
+          +----------------------------------------------------------------------------+
+        */
+
+INT i_APCI1710_EnableFrequencyMeasurement(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_InterruptEnable)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /********************************************/
+                       /* Test if frequency mesurement initialised */
+             /********************************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_FrequencyMeasurementInit == 1) {
+                /***************************/
+                               /* Test the interrupt mode */
+                /***************************/
+
+                               if ((b_InterruptEnable == APCI1710_DISABLE) ||
+                                       (b_InterruptEnable == APCI1710_ENABLE))
+                               {
+
+                      /************************************/
+                                       /* Enable the frequency measurement */
+                      /************************************/
+
+                                       devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister3 = devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister3 |
+                                               APCI1710_ENABLE_FREQUENCY;
+
+                      /*********************************************/
+                                       /* Disable or enable the frequency interrupt */
+                      /*********************************************/
+
+                                       devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister3 = (devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister3 &
+                                               APCI1710_DISABLE_FREQUENCY_INT)
+                                               | (b_InterruptEnable << 3);
+
+                      /***************************/
+                                       /* Write the configuration */
+                      /***************************/
+
+                                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               dw_ModeRegister1_2_3_4,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 20 +
+                                               (64 * b_ModulNbr));
+
+                                       devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SiemensCounterInfo.
+                                               s_InitFlag.
+                                               b_FrequencyMeasurementEnable =
+                                               1;
+                               } else {
+                   /********************************/
+                                       /* Interrupt parameter is wrong */
+                   /********************************/
+
+                                       DPRINTK("Interrupt parameter is wrong\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /***********************************************/
+                               /* Frequency measurement logic not initialised */
+                /***********************************************/
+
+                               DPRINTK("Frequency measurement logic not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+       /*
+          +----------------------------------------------------------------------------+
+          | Function Name     : _INT_ i_APCI1710_DisableFrequencyMeasurement           |
+          |                            (BYTE_   b_BoardHandle,                      |
+          |                             BYTE_   b_ModulNbr)                         |
+          +----------------------------------------------------------------------------+
+          | Task              : Disables the frequency measurement function             |
+          +----------------------------------------------------------------------------+
+          | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+          |                  BYTE_  b_ModulNbr       : Number of the module to be   |
+          |                                            configured (0 to 3)          |
+          +----------------------------------------------------------------------------+
+          | Output Parameters : -                                                      |
+          +----------------------------------------------------------------------------+
+          | Return Value      :  0: No error                                           |
+          |                     -1: The handle parameter of the board is wrong         |
+          |                     -2: The selected module number is wrong                |
+          |                     -3: Counter not initialised see function               |
+          |                      "i_APCI1710_InitCounter"                           |
+          |                     -4: Frequency measurement logic not initialised.       |
+          |                      See function "i_APCI1710_InitFrequencyMeasurement" |
+          +----------------------------------------------------------------------------+
+        */
+
+INT i_APCI1710_DisableFrequencyMeasurement(comedi_device * dev, BYTE b_ModulNbr)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /********************************************/
+                       /* Test if frequency mesurement initialised */
+             /********************************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_FrequencyMeasurementInit == 1) {
+                /*************************************/
+                               /* Disable the frequency measurement */
+                /*************************************/
+
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister3 = devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister3 &
+                                       APCI1710_DISABLE_FREQUENCY
+                                       // Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared
+                                       & APCI1710_DISABLE_FREQUENCY_INT;
+                               // End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared
+
+                /***************************/
+                               /* Write the configuration */
+                /***************************/
+
+                               outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       dw_ModeRegister1_2_3_4,
+                                       devpriv->s_BoardInfos.ui_Address + 20 +
+                                       (64 * b_ModulNbr));
+
+                /*************************************/
+                               /* Disable the frequency measurement */
+                /*************************************/
+
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_InitFlag.
+                                       b_FrequencyMeasurementEnable = 0;
+                       } else {
+                /***********************************************/
+                               /* Frequency measurement logic not initialised */
+                /***********************************************/
+
+                               DPRINTK("Frequency measurement logic not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*########################################################################### */
+
+                                                       // INSN READ
+
+/*########################################################################### */
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT       i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,
+comedi_insn *insn,lsampl_t *data)                   |
++----------------------------------------------------------------------------+
+| Task              : Read and Get functions for INC_CPT                                       |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_InsnReadINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_ReadType;
+       INT i_ReturnValue = 0;
+
+       ui_ReadType = CR_CHAN(insn->chanspec);
+
+       devpriv->tsk_Current = current; // Save the current process task structure
+       switch (ui_ReadType) {
+       case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
+               i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) CR_RANGE(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_READLATCHREGISTERVALUE:
+               i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) CR_RANGE(insn->chanspec), (PULONG) & data[0]);
+               printk("Latch Register Value %d\n", data[0]);
+               break;
+
+       case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
+               i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) CR_RANGE(insn->chanspec), (PUINT) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
+               i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PULONG) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_GETINDEXSTATUS:
+               i_ReturnValue = i_APCI1710_GetIndexStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_GETREFERENCESTATUS:
+               i_ReturnValue = i_APCI1710_GetReferenceStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_GETUASSTATUS:
+               i_ReturnValue = i_APCI1710_GetUASStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_GETCBSTATUS:
+               i_ReturnValue = i_APCI1710_GetCBStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_GET16BITCBSTATUS:
+               i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (PBYTE) & data[0], (PBYTE) & data[1]);
+               break;
+
+       case APCI1710_INCCPT_GETUDSTATUS:
+               i_ReturnValue = i_APCI1710_GetUDStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+
+               break;
+
+       case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:
+               i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+               break;
+
+       case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:
+               i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (PBYTE) & data[0],
+                       (PBYTE) & data[1], (PULONG) & data[2]);
+               break;
+
+       case APCI1710_INCCPT_READINTERRUPT:
+               data[0] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].b_OldModuleMask;
+               data[1] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+               data[2] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+               /**************************/
+               /* Increment the read FIFO */
+               /***************************/
+
+               devpriv->
+                       s_InterruptParameters.
+                       ui_Read = (devpriv->s_InterruptParameters.
+                       ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+               break;
+
+       default:
+               printk("ReadType Parameter wrong\n");
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ReadLatchRegisterStatus               |
+|                                                   (BYTE_   b_BoardHandle,  |
+|                                                    BYTE_   b_ModulNbr,     |
+|                                                    BYTE_   b_LatchReg,     |
+|                                                    PBYTE_ pb_LatchStatus)  |
++----------------------------------------------------------------------------+
+| Task              : Read the latch register status from selected module    |
+|                     (b_ModulNbr) and selected latch register (b_LatchReg). |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+|                     BYTE_ b_ModulNbr    : Module number to configure       |
+|                                           (0 to 3)                         |
+|                     BYTE_ b_LatchReg    : Selected latch register          |
+|                               0 : for the first latch register             |
+|                               1 : for the second latch register            |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_LatchStatus :   Latch register status.       |
+|                                               0 : No latch occur           |
+|                                               1 : A software latch occur   |
+|                                               2 : A hardware latch occur   |
+|                                               3 : A software and hardware  |
+|                                                   latch occur              |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: The selected latch register parameter is wrong     |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadLatchRegisterStatus(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_LatchReg, PBYTE pb_LatchStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_LatchReg;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*************************************/
+                       /* Test the latch register parameter */
+             /*************************************/
+
+                       if (b_LatchReg < 2) {
+                               dw_LatchReg = inl(devpriv->s_BoardInfos.
+                                       ui_Address + (64 * b_ModulNbr));
+
+                               *pb_LatchStatus =
+                                       (BYTE) ((dw_LatchReg >> (b_LatchReg *
+                                                       4)) & 0x3);
+                       } else {
+                /**************************************************/
+                               /* The selected latch register parameter is wrong */
+                /**************************************************/
+
+                               DPRINTK("The selected latch register parameter is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ReadLatchRegisterValue                |
+|                                                   (BYTE_     b_BoardHandle,|
+|                                                    BYTE_     b_ModulNbr,   |
+|                                                    BYTE_     b_LatchReg,   |
+|                                                    PULONG_ pul_LatchValue) |
++----------------------------------------------------------------------------+
+| Task              : Read the latch register value from selected module     |
+|                     (b_ModulNbr) and selected latch register (b_LatchReg). |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+|                     BYTE_ b_ModulNbr    : Module number to configure       |
+|                                           (0 to 3)                         |
+|                     BYTE_ b_LatchReg    : Selected latch register          |
+|                               0 : for the first latch register             |
+|                               1 : for the second latch register            |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_LatchValue : Latch register value          |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: The selected latch register parameter is wrong     |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadLatchRegisterValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_LatchReg, PULONG pul_LatchValue)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*************************************/
+                       /* Test the latch register parameter */
+             /*************************************/
+
+                       if (b_LatchReg < 2) {
+                               *pul_LatchValue = inl(devpriv->s_BoardInfos.
+                                       ui_Address + ((b_LatchReg + 1) * 4) +
+                                       (64 * b_ModulNbr));
+
+                       } else {
+                /**************************************************/
+                               /* The selected latch register parameter is wrong */
+                /**************************************************/
+
+                               DPRINTK("The selected latch register parameter is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_Read16BitCounterValue                 |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_SelectedCounter,        |
+|                                        PUINT_   pui_CounterValue)          |
++----------------------------------------------------------------------------+
+| Task              : Latch the selected 16-Bit counter (b_SelectedCounter)  |
+|                     from selected module (b_ModulNbr) in to the first      |
+|                     latch register and return the latched value.           |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                              (0 to 3)                      |
+|                     BYTE_ b_SelectedCounter : Selected 16-Bit counter      |
+|                                               (0 or 1)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PUINT_ pui_CounterValue : 16-Bit counter value         |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: The selected 16-Bit counter parameter is wrong     |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Read16BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_SelectedCounter, PUINT pui_CounterValue)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_LathchValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /******************************/
+                       /* Test the counter selection */
+             /******************************/
+
+                       if (b_SelectedCounter < 2) {
+                /*********************/
+                               /* Latch the counter */
+                /*********************/
+
+                               outl(1, devpriv->s_BoardInfos.
+                                       ui_Address + (64 * b_ModulNbr));
+
+                /************************/
+                               /* Read the latch value */
+                /************************/
+
+                               dw_LathchValue = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 4 + (64 * b_ModulNbr));
+
+                               *pui_CounterValue =
+                                       (UINT) ((dw_LathchValue >> (16 *
+                                                       b_SelectedCounter)) &
+                                       0xFFFFU);
+                       } else {
+                /**************************************************/
+                               /* The selected 16-Bit counter parameter is wrong */
+                /**************************************************/
+
+                               DPRINTK("The selected 16-Bit counter parameter is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_Read32BitCounterValue                 |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        PULONG_ pul_CounterValue)           |
++----------------------------------------------------------------------------+
+| Task              : Latch the 32-Bit counter from selected module          |
+|                     (b_ModulNbr) in to the first latch register and return |
+|                     the latched value.                                     |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                              (0 to 3)                      |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pul_CounterValue : 32-Bit counter value       |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Read32BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, PULONG pul_CounterValue)
+{
+       INT i_ReturnValue = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*********************/
+                       /* Tatch the counter */
+             /*********************/
+
+                       outl(1, devpriv->s_BoardInfos.
+                               ui_Address + (64 * b_ModulNbr));
+
+             /************************/
+                       /* Read the latch value */
+             /************************/
+
+                       *pul_CounterValue = inl(devpriv->s_BoardInfos.
+                               ui_Address + 4 + (64 * b_ModulNbr));
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetIndexStatus (BYTE_   b_BoardHandle,|
+|                                                      BYTE_   b_ModulNbr,   |
+|                                                      PBYTE_ pb_IndexStatus)|
++----------------------------------------------------------------------------+
+| Task              : Return the index status                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_IndexStatus   : 0 : No INDEX occur           |
+|                                               1 : A INDEX occur            |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Index not initialised see function                 |
+|                         "i_APCI1710_InitIndex"                             |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetIndexStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_IndexStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*****************************/
+                       /* Test if index initialised */
+             /*****************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
+                               dw_StatusReg = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 12 + (64 * b_ModulNbr));
+
+                               *pb_IndexStatus = (BYTE) (dw_StatusReg & 1);
+                       } else {
+                /*************************************************************/
+                               /* Index not initialised see function "i_APCI1710_InitIndex" */
+                /*************************************************************/
+
+                               DPRINTK("Index not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetReferenceStatus                    |
+|                                                (BYTE_   b_BoardHandle,     |
+|                                                 BYTE_   b_ModulNbr,        |
+|                                                 PBYTE_ pb_ReferenceStatus) |
++----------------------------------------------------------------------------+
+| Task              : Return the reference status                            |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_ReferenceStatus   : 0 : No REFERENCE occur   |
+|                                                   1 : A REFERENCE occur    |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Reference not initialised see function             |
+|                         "i_APCI1710_InitReference"                         |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetReferenceStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_ReferenceStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*********************************/
+                       /* Test if reference initialised */
+             /*********************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_ReferenceInit) {
+                               dw_StatusReg = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 24 + (64 * b_ModulNbr));
+
+                               *pb_ReferenceStatus =
+                                       (BYTE) (~dw_StatusReg & 1);
+                       } else {
+                /*********************************************************************/
+                               /* Reference not initialised see function "i_APCI1710_InitReference" */
+                /*********************************************************************/
+
+                               DPRINTK("Reference not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetUASStatus                          |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr,                         |
+|                                PBYTE_ pb_UASStatus)                        |
++----------------------------------------------------------------------------+
+| Task              : Return the error signal (UAS) status                   |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_UASStatus      : 0 : UAS is low "0"          |
+|                                                1 : UAS is high "1"         |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetUASStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_UASStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+                       dw_StatusReg = inl(devpriv->s_BoardInfos.
+                               ui_Address + 24 + (64 * b_ModulNbr));
+
+                       *pb_UASStatus = (BYTE) ((dw_StatusReg >> 1) & 1);
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetCBStatus                           |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr,                         |
+|                                PBYTE_ pb_CBStatus)                         |
++----------------------------------------------------------------------------+
+| Task              : Return the counter overflow status                     |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_CBStatus      : 0 : Counter no overflow      |
+|                                               1 : Counter overflow         |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetCBStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_CBStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+                       dw_StatusReg = inl(devpriv->s_BoardInfos.
+                               ui_Address + 16 + (64 * b_ModulNbr));
+
+                       *pb_CBStatus = (BYTE) (dw_StatusReg & 1);
+
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_Get16BitCBStatus                      |
+|                                      (BYTE_     b_BoardHandle,            |
+|                                       BYTE_     b_ModulNbr,               |
+|                                       PBYTE_ pb_CBStatusCounter0,         |
+|                                       PBYTE_ pb_CBStatusCounter1)         |
++----------------------------------------------------------------------------+
+| Task              : Returns the counter overflow (counter initialised to   |
+|                    2*16-bit) status from selected incremental counter     |
+|                    module                                                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_CBStatusCounter0 : 0 : No overflow occur for |
+|                                                     the first 16-bit      |
+|                                                     counter               |
+|                                                 1 : Overflow occur for the|
+|                                                     first 16-bit counter  |
+|                    PBYTE_ pb_CBStatusCounter1 : 0 : No overflow occur for |
+|                                                     the second 16-bit     |
+|                                                     counter               |
+|                                                 1 : Overflow occur for the|
+|                                                     second 16-bit counter |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Counter not initialised to 2*16-bit mode.          |
+|                        See function "i_APCI1710_InitCounter"              |
+|                     -5: Firmware revision error                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Get16BitCBStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0, PBYTE pb_CBStatusCounter1)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /*************************/
+                       /* Test if 2*16-Bit mode */
+             /*************************/
+
+                       if ((devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister1 & 0x10) == 0x10) {
+                /*****************************/
+                               /* Test the Firmware version */
+                /*****************************/
+
+                               if ((devpriv->s_BoardInfos.
+                                               dw_MolduleConfiguration
+                                               [b_ModulNbr] & 0xFFFF) >=
+                                       0x3136) {
+                                       dw_StatusReg =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 16 +
+                                               (64 * b_ModulNbr));
+
+                                       *pb_CBStatusCounter1 =
+                                               (BYTE) ((dw_StatusReg >> 0) &
+                                               1);
+                                       *pb_CBStatusCounter0 =
+                                               (BYTE) ((dw_StatusReg >> 1) &
+                                               1);
+                               }       // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)
+                               else {
+                   /****************************/
+                                       /* Firmware revision error  */
+                   /****************************/
+
+                                       i_ReturnValue = -5;
+                               }       // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)
+                       }       // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)
+                       else {
+                /********************************************/
+                               /* Counter not initialised to 2*16-bit mode */
+                               /* "i_APCI1710_InitCounter"                 */
+                /********************************************/
+
+                               DPRINTK("Counter not initialised\n");
+                               i_ReturnValue = -4;
+                       }       // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)
+               }               // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)
+               else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }               // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)
+       }                       // if (b_ModulNbr < 4)
+       else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }                       // if (b_ModulNbr < 4)
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetUDStatus                           |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr,                         |
+|                                PBYTE_ pb_UDStatus)                         |
++----------------------------------------------------------------------------+
+| Task              : Return the counter progress status                     |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |
+|                                                   selected mode down       |
+|                                               1 : Counter progress in the  |
+|                                                   selected mode up         |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetUDStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_UDStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+                       dw_StatusReg = inl(devpriv->s_BoardInfos.
+                               ui_Address + 24 + (64 * b_ModulNbr));
+
+                       *pb_UDStatus = (BYTE) ((dw_StatusReg >> 2) & 1);
+
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetInterruptUDLatchedStatus           |
+|                               (BYTE_   b_BoardHandle,                      |
+|                                BYTE_   b_ModulNbr,                         |
+|                                PBYTE_ pb_UDStatus)                         |
++----------------------------------------------------------------------------+
+| Task              : Return the counter progress latched status after a     |
+|                     index interrupt occur.                                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Module number to configure   |
+|                                               (0 to 3)                     |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |
+|                                                   selected mode down       |
+|                                               1 : Counter progress in the  |
+|                                                   selected mode up         |
+|                                               2 : No index interrupt occur |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: No counter module found                            |
+|                     -3: Counter not initialised see function               |
+|                         "i_APCI1710_InitCounter"                           |
+|                     -4: Interrupt function not initialised.                |
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetInterruptUDLatchedStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_UDStatus)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+                /*********************************/
+                       /* Test if index interrupt occur */
+                /*********************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_IndexInterruptOccur == 1) {
+                               devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_InitFlag.b_IndexInterruptOccur = 0;
+
+                               dw_StatusReg = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 12 + (64 * b_ModulNbr));
+
+                               *pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 1);
+                       } else {
+                   /****************************/
+                               /* No index interrupt occur */
+                   /****************************/
+
+                               *pb_UDStatus = 2;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+       /*
+          +----------------------------------------------------------------------------+
+          | Function Name     : _INT_ i_APCI1710_ReadFrequencyMeasurement              |
+          |                            (BYTE_            b_BoardHandle,             |
+          |                             BYTE_            b_ModulNbr,                |
+          |                             PBYTE_          pb_Status,                  |
+          |                             PULONG_        pul_ReadValue)               |
+          +----------------------------------------------------------------------------+
+          | Task              : Returns the status (pb_Status) and the number of       |
+          |                  increments in the set time.                            |
+          |                  See function " i_APCI1710_InitFrequencyMeasurement "   |
+          +----------------------------------------------------------------------------+
+          | Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |
+          |                  BYTE_  b_ModulNbr       : Number of the module to be   |
+          |                                            configured (0 to 3)          |
+          +----------------------------------------------------------------------------+
+          | Output Parameters : PBYTE_ pb_Status     : Returns the frequency        |
+          |                                            measurement status           |
+          |                                            0 : Counting cycle not       |
+          |                                                started.                 |
+          |                                            1 : Counting cycle started.  |
+          |                                            2 : Counting cycle stopped.  |
+          |                                                The measurement cycle is |
+          |                                                completed.               |
+          |                  PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |
+          |                                                   selected mode down       |
+          |                                               1 : Counter progress in the  |
+          |                                                   selected mode up         |
+          |                  PULONG_ pul_ReadValue   : Return the number of         |
+          |                                            increments in the defined    |
+          |                                            time base.                   |
+          +----------------------------------------------------------------------------+
+          | Return Value      :  0: No error                                           |
+          |                     -1: The handle parameter of the board is wrong         |
+          |                     -2: The selected module number is wrong                |
+          |                     -3: Counter not initialised see function               |
+          |                      "i_APCI1710_InitCounter"                           |
+          |                     -4: Frequency measurement logic not initialised.       |
+          |                      See function "i_APCI1710_InitFrequencyMeasurement" |
+          +----------------------------------------------------------------------------+
+        */
+
+INT i_APCI1710_ReadFrequencyMeasurement(comedi_device * dev,
+       BYTE b_ModulNbr,
+       PBYTE pb_Status, PBYTE pb_UDStatus, PULONG pul_ReadValue)
+{
+       INT i_ReturnValue = 0;
+       UINT ui_16BitValue;
+       DWORD dw_StatusReg;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /*******************************/
+               /* Test if counter initialised */
+          /*******************************/
+
+               if (devpriv->
+                       s_ModuleInfo[b_ModulNbr].
+                       s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+             /********************************************/
+                       /* Test if frequency mesurement initialised */
+             /********************************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_SiemensCounterInfo.
+                               s_InitFlag.b_FrequencyMeasurementInit == 1) {
+                /******************/
+                               /* Test if enable */
+                /******************/
+
+                               if (devpriv->
+                                       s_ModuleInfo[b_ModulNbr].
+                                       s_SiemensCounterInfo.
+                                       s_InitFlag.
+                                       b_FrequencyMeasurementEnable == 1) {
+                   /*******************/
+                                       /* Read the status */
+                   /*******************/
+
+                                       dw_StatusReg =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 32 +
+                                               (64 * b_ModulNbr));
+
+                   /**************************/
+                                       /* Test if frequency stop */
+                   /**************************/
+
+                                       if (dw_StatusReg & 1) {
+                                               *pb_Status = 2;
+                                               *pb_UDStatus =
+                                                       (BYTE) ((dw_StatusReg >>
+                                                               1) & 3);
+
+                      /******************/
+                                               /* Read the value */
+                      /******************/
+
+                                               *pul_ReadValue =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address + 28 +
+                                                       (64 * b_ModulNbr));
+
+                                               if (*pb_UDStatus == 0) {
+                         /*************************/
+                                                       /* Test the counter mode */
+                         /*************************/
+
+                                                       if ((devpriv->s_ModuleInfo[b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER) {
+                            /****************************************/
+                                                               /* Test if 16-bit counter 1 pulse occur */
+                            /****************************************/
+
+                                                               if ((*pul_ReadValue & 0xFFFFU) != 0) {
+                                                                       ui_16BitValue
+                                                                               =
+                                                                               (UINT)
+                                                                               *
+                                                                               pul_ReadValue
+                                                                               &
+                                                                               0xFFFFU;
+                                                                       *pul_ReadValue
+                                                                               =
+                                                                               (*pul_ReadValue
+                                                                               &
+                                                                               0xFFFF0000UL)
+                                                                               |
+                                                                               (0xFFFFU
+                                                                               -
+                                                                               ui_16BitValue);
+                                                               }
+
+                            /****************************************/
+                                                               /* Test if 16-bit counter 2 pulse occur */
+                            /****************************************/
+
+                                                               if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
+                                                                       ui_16BitValue
+                                                                               =
+                                                                               (UINT)
+                                                                               (
+                                                                               (*pul_ReadValue
+                                                                                       >>
+                                                                                       16)
+                                                                               &
+                                                                               0xFFFFU);
+                                                                       *pul_ReadValue
+                                                                               =
+                                                                               (*pul_ReadValue
+                                                                               &
+                                                                               0xFFFFUL)
+                                                                               |
+                                                                               (
+                                                                               (0xFFFFU - ui_16BitValue) << 16);
+                                                               }
+                                                       } else {
+                                                               if (*pul_ReadValue != 0) {
+                                                                       *pul_ReadValue
+                                                                               =
+                                                                               0xFFFFFFFFUL
+                                                                               -
+                                                                               *pul_ReadValue;
+                                                               }
+                                                       }
+                                               } else {
+                                                       if (*pb_UDStatus == 1) {
+                            /****************************************/
+                                                               /* Test if 16-bit counter 2 pulse occur */
+                            /****************************************/
+
+                                                               if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
+                                                                       ui_16BitValue
+                                                                               =
+                                                                               (UINT)
+                                                                               (
+                                                                               (*pul_ReadValue
+                                                                                       >>
+                                                                                       16)
+                                                                               &
+                                                                               0xFFFFU);
+                                                                       *pul_ReadValue
+                                                                               =
+                                                                               (*pul_ReadValue
+                                                                               &
+                                                                               0xFFFFUL)
+                                                                               |
+                                                                               (
+                                                                               (0xFFFFU - ui_16BitValue) << 16);
+                                                               }
+                                                       } else {
+                                                               if (*pb_UDStatus
+                                                                       == 2) {
+                               /****************************************/
+                                                                       /* Test if 16-bit counter 1 pulse occur */
+                               /****************************************/
+
+                                                                       if ((*pul_ReadValue & 0xFFFFU) != 0) {
+                                                                               ui_16BitValue
+                                                                                       =
+                                                                                       (UINT)
+                                                                                       *
+                                                                                       pul_ReadValue
+                                                                                       &
+                                                                                       0xFFFFU;
+                                                                               *pul_ReadValue
+                                                                                       =
+                                                                                       (*pul_ReadValue
+                                                                                       &
+                                                                                       0xFFFF0000UL)
+                                                                                       |
+                                                                                       (0xFFFFU
+                                                                                       -
+                                                                                       ui_16BitValue);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       } else {
+                                               *pb_Status = 1;
+                                               *pb_UDStatus = 0;
+                                       }
+                               } else {
+                                       *pb_Status = 0;
+                                       *pb_UDStatus = 0;
+                               }
+                       } else {
+                /***********************************************/
+                               /* Frequency measurement logic not initialised */
+                /***********************************************/
+
+                               DPRINTK("Frequency measurement logic not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /****************************************/
+                       /* Counter not initialised see function */
+                       /* "i_APCI1710_InitCounter"             */
+             /****************************************/
+
+                       DPRINTK("Counter not initialised\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*************************************************/
+               /* The selected module number parameter is wrong */
+          /*************************************************/
+
+               DPRINTK("The selected module number parameter is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
new file mode 100644 (file)
index 0000000..c3e8cad
--- /dev/null
@@ -0,0 +1,269 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_16BIT_COUNTER                         0x10
+#define APCI1710_32BIT_COUNTER                         0x0
+#define APCI1710_QUADRUPLE_MODE                        0x0
+#define APCI1710_DOUBLE_MODE                           0x3
+#define APCI1710_SIMPLE_MODE                           0xF
+#define APCI1710_DIRECT_MODE                           0x80
+#define APCI1710_HYSTERESIS_ON                         0x60
+#define APCI1710_HYSTERESIS_OFF                        0x0
+#define APCI1710_INCREMENT                             0x60
+#define APCI1710_DECREMENT                             0x0
+#define APCI1710_LATCH_COUNTER                         0x1
+#define APCI1710_CLEAR_COUNTER                         0x0
+#define APCI1710_LOW                                   0x0
+#define APCI1710_HIGH                                  0x1
+
+/*********************/
+/* Version 0600-0229 */
+/*********************/
+
+#define APCI1710_HIGH_EDGE_CLEAR_COUNTER               0x0
+#define APCI1710_HIGH_EDGE_LATCH_COUNTER               0x1
+#define APCI1710_LOW_EDGE_CLEAR_COUNTER                0x2
+#define APCI1710_LOW_EDGE_LATCH_COUNTER                0x3
+#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER     0x4
+#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER      0x5
+#define APCI1710_SOURCE_0                              0x0
+#define APCI1710_SOURCE_1                              0x1
+
+#define APCI1710_30MHZ           30
+#define APCI1710_33MHZ           33
+#define APCI1710_40MHZ           40
+
+#define APCI1710_ENABLE_LATCH_INT              0x80
+#define APCI1710_DISABLE_LATCH_INT             (~APCI1710_ENABLE_LATCH_INT)
+
+#define APCI1710_INDEX_LATCH_COUNTER           0x10
+#define APCI1710_INDEX_AUTO_MODE               0x8
+#define APCI1710_ENABLE_INDEX                  0x4
+#define APCI1710_DISABLE_INDEX                 (~APCI1710_ENABLE_INDEX)
+#define APCI1710_ENABLE_LATCH_AND_CLEAR        0x8
+#define APCI1710_DISABLE_LATCH_AND_CLEAR       (~APCI1710_ENABLE_LATCH_AND_CLEAR)
+#define APCI1710_SET_LOW_INDEX_LEVEL           0x4
+#define APCI1710_SET_HIGH_INDEX_LEVEL           (~APCI1710_SET_LOW_INDEX_LEVEL)
+#define APCI1710_INVERT_INDEX_RFERENCE         0x2
+#define APCI1710_DEFAULT_INDEX_RFERENCE         (~APCI1710_INVERT_INDEX_RFERENCE)
+
+#define APCI1710_ENABLE_INDEX_INT              0x1
+#define APCI1710_DISABLE_INDEX_INT             (~APCI1710_ENABLE_INDEX_INT)
+
+#define APCI1710_ENABLE_FREQUENCY              0x4
+#define APCI1710_DISABLE_FREQUENCY             (~APCI1710_ENABLE_FREQUENCY)
+
+#define APCI1710_ENABLE_FREQUENCY_INT          0x8
+#define APCI1710_DISABLE_FREQUENCY_INT         (~APCI1710_ENABLE_FREQUENCY_INT)
+
+#define APCI1710_ENABLE_40MHZ_FREQUENCY                0x40
+#define APCI1710_DISABLE_40MHZ_FREQUENCY       (~APCI1710_ENABLE_40MHZ_FREQUENCY)
+
+#define APCI1710_ENABLE_40MHZ_FILTER           0x80
+#define APCI1710_DISABLE_40MHZ_FILTER          (~APCI1710_ENABLE_40MHZ_FILTER)
+
+#define APCI1710_ENABLE_COMPARE_INT            0x2
+#define APCI1710_DISABLE_COMPARE_INT           (~APCI1710_ENABLE_COMPARE_INT)
+
+#define APCI1710_ENABLE_INDEX_ACTION           0x20
+#define APCI1710_DISABLE_INDEX_ACTION          (~APCI1710_ENABLE_INDEX_ACTION)
+#define APCI1710_REFERENCE_HIGH                0x40
+#define APCI1710_REFERENCE_LOW                 (~APCI1710_REFERENCE_HIGH)
+
+#define APCI1710_TOR_GATE_LOW          0x40
+#define APCI1710_TOR_GATE_HIGH         (~APCI1710_TOR_GATE_LOW)
+
+//      INSN CONFIG
+#define        APCI1710_INCCPT_INITCOUNTER                                                     100
+#define APCI1710_INCCPT_COUNTERAUTOTEST                                                101
+#define APCI1710_INCCPT_INITINDEX                                                      102
+#define APCI1710_INCCPT_INITREFERENCE                                          103
+#define APCI1710_INCCPT_INITEXTERNALSTROBE                                     104
+#define APCI1710_INCCPT_INITCOMPARELOGIC                                       105
+#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT                       106
+
+// INSN READ
+#define APCI1710_INCCPT_READLATCHREGISTERSTATUS                                200
+#define APCI1710_INCCPT_READLATCHREGISTERVALUE                         201
+#define APCI1710_INCCPT_READ16BITCOUNTERVALUE                          202
+#define APCI1710_INCCPT_READ32BITCOUNTERVALUE                          203
+#define APCI1710_INCCPT_GETINDEXSTATUS                                         204
+#define APCI1710_INCCPT_GETREFERENCESTATUS                                     205
+#define APCI1710_INCCPT_GETUASSTATUS                                           206
+#define APCI1710_INCCPT_GETCBSTATUS                                                    207
+#define APCI1710_INCCPT_GET16BITCBSTATUS                                       208
+#define APCI1710_INCCPT_GETUDSTATUS                                                    209
+#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS                    210
+#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT                       211
+#define APCI1710_INCCPT_READINTERRUPT                       212
+
+//INSN BITS
+#define APCI1710_INCCPT_CLEARCOUNTERVALUE                                      300
+#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE                           301
+#define APCI1710_INCCPT_SETINPUTFILTER                                         302
+#define APCI1710_INCCPT_LATCHCOUNTER                                           303
+#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE                     304
+#define APCI1710_INCCPT_SETDIGITALCHLON                                                305
+#define APCI1710_INCCPT_SETDIGITALCHLOFF                                       306
+
+// INSN WRITE
+#define APCI1710_INCCPT_ENABLELATCHINTERRUPT                           400
+#define APCI1710_INCCPT_DISABLELATCHINTERRUPT                          401
+#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE                         402
+#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE                         403
+#define APCI1710_INCCPT_ENABLEINDEX                                                    404
+#define APCI1710_INCCPT_DISABLEINDEX                                           405
+#define APCI1710_INCCPT_ENABLECOMPARELOGIC                                     406
+#define APCI1710_INCCPT_DISABLECOMPARELOGIC                                    407
+#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT                     408
+#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT                    409
+
+/************ Main Functions *************/
+INT i_APCI1710_InsnConfigINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnBitsINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnWriteINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnReadINCCPT(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+/*********** Supplementary Functions********/
+
+// INSN CONFIG
+
+INT i_APCI1710_InitCounter(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_CounterRange,
+       BYTE b_FirstCounterModus,
+       BYTE b_FirstCounterOption,
+       BYTE b_SecondCounterModus, BYTE b_SecondCounterOption);
+
+INT i_APCI1710_CounterAutoTest(comedi_device * dev, PBYTE pb_TestStatus);
+
+INT i_APCI1710_InitIndex(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_ReferenceAction,
+       BYTE b_IndexOperation, BYTE b_AutoMode, BYTE b_InterruptEnable);
+
+INT i_APCI1710_InitReference(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_ReferenceLevel);
+
+INT i_APCI1710_InitExternalStrobe(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_ExternalStrobe, BYTE b_ExternalStrobeLevel);
+
+INT i_APCI1710_InitCompareLogic(comedi_device * dev,
+       BYTE b_ModulNbr, UINT ui_CompareValue);
+
+INT i_APCI1710_InitFrequencyMeasurement(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PCIInputClock,
+       BYTE b_TimingUnity,
+       ULONG ul_TimingInterval, PULONG pul_RealTimingInterval);
+
+//INSN BITS
+
+INT i_APCI1710_ClearCounterValue(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_ClearAllCounterValue(comedi_device * dev);
+
+INT i_APCI1710_SetInputFilter(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_PCIInputClock, BYTE b_Filter);
+
+INT i_APCI1710_LatchCounter(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_LatchReg);
+
+INT i_APCI1710_SetIndexAndReferenceSource(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_SourceSelection);
+
+INT i_APCI1710_SetDigitalChlOn(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_SetDigitalChlOff(comedi_device * dev, BYTE b_ModulNbr);
+
+// INSN WRITE
+INT i_APCI1710_EnableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_DisableLatchInterrupt(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_Write16BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_SelectedCounter, UINT ui_WriteValue);
+
+INT i_APCI1710_Write32BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, ULONG ul_WriteValue);
+
+INT i_APCI1710_EnableIndex(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_DisableIndex(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_EnableCompareLogic(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_DisableCompareLogic(comedi_device * dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_EnableFrequencyMeasurement(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_InterruptEnable);
+
+INT i_APCI1710_DisableFrequencyMeasurement(comedi_device * dev,
+       BYTE b_ModulNbr);
+
+// INSN READ
+
+INT i_APCI1710_ReadLatchRegisterStatus(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_LatchReg, PBYTE pb_LatchStatus);
+
+INT i_APCI1710_ReadLatchRegisterValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_LatchReg, PULONG pul_LatchValue);
+
+INT i_APCI1710_Read16BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, BYTE b_SelectedCounter, PUINT pui_CounterValue);
+
+INT i_APCI1710_Read32BitCounterValue(comedi_device * dev,
+       BYTE b_ModulNbr, PULONG pul_CounterValue);
+
+INT i_APCI1710_GetIndexStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_IndexStatus);
+
+INT i_APCI1710_GetReferenceStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_ReferenceStatus);
+
+INT i_APCI1710_GetUASStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_UASStatus);
+
+INT i_APCI1710_GetCBStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_CBStatus);
+
+INT i_APCI1710_Get16BitCBStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0, PBYTE pb_CBStatusCounter1);
+
+INT i_APCI1710_GetUDStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_UDStatus);
+
+INT i_APCI1710_GetInterruptUDLatchedStatus(comedi_device * dev,
+       BYTE b_ModulNbr, PBYTE pb_UDStatus);
+
+INT i_APCI1710_ReadFrequencyMeasurement(comedi_device * dev,
+       BYTE b_ModulNbr,
+       PBYTE pb_Status, PBYTE pb_UDStatus, PULONG pul_ReadValue);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
new file mode 100644 (file)
index 0000000..90b8dc9
--- /dev/null
@@ -0,0 +1,861 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : Inp_CPT.C       | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 pulse encoder module                        |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |----------|-----------|------------------------------------------------|
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Inp_cpt.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitPulseEncoder                      |
+|                               (BYTE_          b_BoardHandle,               |
+|                                BYTE_          b_ModulNbr,                  |
+|                                BYTE_          b_PulseEncoderNbr,           |
+|                                BYTE_          b_InputLevelSelection,       |
+|                                BYTE_          b_TriggerOutputAction,       |
+|                                ULONG_        ul_StartValue)                |
++----------------------------------------------------------------------------+
+| Task              : Configure the pulse encoder operating mode selected via|
+|                     b_ModulNbr and b_PulseEncoderNbr. The pulse encoder    |
+|                     after each pulse decrement the counter value from 1.   |
+|                                                                            |
+|                     You must calling this function be for you call any     |
+|                     other function witch access of pulse encoders.         |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr            : Module number to         |
+|                                                   configure (0 to 3)       |
+|                     BYTE_ b_PulseEncoderNbr     : Pulse encoder selection  |
+|                                                   (0 to 3)                 |
+|                     BYTE_ b_InputLevelSelection : Input level selection    |
+|                                                   (0 or 1)                 |
+|                                                       0 : Set pulse encoder|
+|                                                           count the the low|
+|                                                           level pulse.     |
+|                                                       1 : Set pulse encoder|
+|                                                           count the the    |
+|                                                           high level pulse.|
+|                     BYTE_ b_TriggerOutputAction : Digital TRIGGER output   |
+|                                                   action                   |
+|                                                       0 : No action        |
+|                                                       1 : Set the trigger  |
+|                                                           output to "1"    |
+|                                                           (high) after the |
+|                                                           passage from 1 to|
+|                                                           0 from pulse     |
+|                                                           encoder.         |
+|                                                       2 : Set the trigger  |
+|                                                           output to "0"    |
+|                                                           (low) after the  |
+|                                                           passage from 1 to|
+|                                                           0 from pulse     |
+|                                                           encoder          |
+|                     ULONG_ ul_StartValue        : Pulse encoder start value|
+|                                                   (1 to 4294967295)
+       b_ModulNbr                              =(BYTE) CR_AREF(insn->chanspec);
+       b_PulseEncoderNbr               =(BYTE) data[0];
+       b_InputLevelSelection   =(BYTE) data[1];
+       b_TriggerOutputAction   =(BYTE) data[2];
+       ul_StartValue                   =(ULONG) data[3];
+       |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module is not a pulse encoder module            |
+|                    -3: Pulse encoder selection is wrong                    |
+|                    -4: Input level selection is wrong                      |
+|                    -5: Digital TRIGGER output action selection is wrong    |
+|                    -6: Pulse encoder start value is wrong                  |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_IntRegister;
+
+       BYTE b_ModulNbr;
+       BYTE b_PulseEncoderNbr;
+       BYTE b_InputLevelSelection;
+       BYTE b_TriggerOutputAction;
+       ULONG ul_StartValue;
+
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_PulseEncoderNbr = (BYTE) data[0];
+       b_InputLevelSelection = (BYTE) data[1];
+       b_TriggerOutputAction = (BYTE) data[2];
+       ul_StartValue = (ULONG) data[3];
+
+       i_ReturnValue = insn->n;
+
+       /***********************************/
+       /* Test the selected module number */
+       /***********************************/
+
+       if (b_ModulNbr <= 3) {
+          /*************************/
+               /* Test if pulse encoder */
+          /*************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               APCI1710_PULSE_ENCODER) ==
+                       APCI1710_PULSE_ENCODER) {
+             /******************************************/
+                       /* Test the selected pulse encoder number */
+             /******************************************/
+
+                       if (b_PulseEncoderNbr <= 3) {
+                /************************/
+                               /* Test the input level */
+                /************************/
+
+                               if ((b_InputLevelSelection == 0)
+                                       || (b_InputLevelSelection == 1)) {
+                   /*******************************************/
+                                       /* Test the ouput TRIGGER action selection */
+                   /*******************************************/
+
+                                       if ((b_TriggerOutputAction <= 2)
+                                               || (b_PulseEncoderNbr > 0)) {
+                                               if (ul_StartValue > 1) {
+
+                                                       dw_IntRegister =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               20 +
+                                                               (64 * b_ModulNbr));
+
+                         /***********************/
+                                                       /* Set the start value */
+                         /***********************/
+
+                                                       outl(ul_StartValue,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               (b_PulseEncoderNbr
+                                                                       * 4) +
+                                                               (64 * b_ModulNbr));
+
+                         /***********************/
+                                                       /* Set the input level */
+                         /***********************/
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_PulseEncoderModuleInfo.
+                                                               dw_SetRegister =
+                                                               (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_PulseEncoderModuleInfo.
+                                                               dw_SetRegister &
+                                                               (0xFFFFFFFFUL -
+                                                                       (1UL << (8 + b_PulseEncoderNbr)))) | ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr));
+
+                         /*******************************/
+                                                       /* Test if output trigger used */
+                         /*******************************/
+
+                                                       if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1)) {
+                            /****************************/
+                                                               /* Enable the output action */
+                            /****************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       | (1UL
+                                                                       << (4 + b_PulseEncoderNbr));
+
+                            /*********************************/
+                                                               /* Set the output TRIGGER action */
+                            /*********************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       =
+                                                                       (devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       &
+                                                                       (0xFFFFFFFFUL
+                                                                               -
+                                                                               (1UL << (12 + b_PulseEncoderNbr)))) | ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr));
+                                                       } else {
+                            /*****************************/
+                                                               /* Disable the output action */
+                            /*****************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       &
+                                                                       (0xFFFFFFFFUL
+                                                                       -
+                                                                       (1UL << (4 + b_PulseEncoderNbr)));
+                                                       }
+
+                         /*************************/
+                                                       /* Set the configuration */
+                         /*************************/
+
+                                                       outl(devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_PulseEncoderModuleInfo.
+                                                               dw_SetRegister,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               20 +
+                                                               (64 * b_ModulNbr));
+
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_PulseEncoderModuleInfo.
+                                                               s_PulseEncoderInfo
+                                                               [b_PulseEncoderNbr].
+                                                               b_PulseEncoderInit
+                                                               = 1;
+                                               } else {
+                         /**************************************/
+                                                       /* Pulse encoder start value is wrong */
+                         /**************************************/
+
+                                                       DPRINTK("Pulse encoder start value is wrong\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       } else {
+                      /****************************************************/
+                                               /* Digital TRIGGER output action selection is wrong */
+                      /****************************************************/
+
+                                               DPRINTK("Digital TRIGGER output action selection is wrong\n");
+                                               i_ReturnValue = -5;
+                                       }
+                               } else {
+                   /**********************************/
+                                       /* Input level selection is wrong */
+                   /**********************************/
+
+                                       DPRINTK("Input level selection is wrong\n");
+                                       i_ReturnValue = -4;
+                               }
+                       } else {
+                /************************************/
+                               /* Pulse encoder selection is wrong */
+                /************************************/
+
+                               DPRINTK("Pulse encoder selection is wrong\n");
+                               i_ReturnValue = -3;
+                       }
+               } else {
+             /********************************************/
+                       /* The module is not a pulse encoder module */
+             /********************************************/
+
+                       DPRINTK("The module is not a pulse encoder module\n");
+                       i_ReturnValue = -2;
+               }
+       } else {
+          /********************************************/
+               /* The module is not a pulse encoder module */
+          /********************************************/
+
+               DPRINTK("The module is not a pulse encoder module\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_EnablePulseEncoder                    |
+|                                       (BYTE_  b_BoardHandle,               |
+|                                        BYTE_  b_ModulNbr,                  |
+|                                        BYTE_  b_PulseEncoderNbr,           |
+|                                        BYTE_  b_CycleSelection,            |
+|                                        BYTE_  b_InterruptHandling)         |
++----------------------------------------------------------------------------+
+| Task              : Enableor disable  the selected pulse encoder (b_PulseEncoderNbr)  |
+|                     from selected module (b_ModulNbr). Each input pulse    |
+|                     decrement the pulse encoder counter value from 1.      |
+|                     If you enabled the interrupt (b_InterruptHandling), a  |
+|                     interrupt is generated when the pulse encoder has run  |
+|                     down.                                                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_   b_BoardHandle       : Handle of board APCI-1710|
+|                     BYTE_   b_ModulNbr          : Module number to         |
+|                                                   configure (0 to 3)       |
+|                     BYTE_   b_PulseEncoderNbr   : Pulse encoder selection  |
+|                                                   (0 to 3)                 |
+|                     BYTE_   b_CycleSelection    : APCI1710_CONTINUOUS:     |
+|                                                       Each time the        |
+|                                                       counting value is set|
+|                                                       on "0", the pulse    |
+|                                                       encoder load the     |
+|                                                       start value after    |
+|                                                       the next pulse.      |
+|                                                   APCI1710_SINGLE:         |
+|                                                       If the counter is set|
+|                                                       on "0", the pulse    |
+|                                                       encoder is stopped.  |
+|                     BYTE_   b_InterruptHandling : Interrupts can be        |
+|                                                   generated, when the pulse|
+|                                                   encoder has run down.    |
+|                                                   With this parameter the  |
+|                                                   user decides if          |
+|                                                   interrupts are used or   |
+|                                                   not.                     |
+|                                                     APCI1710_ENABLE:       |
+|                                                     Interrupts are enabled |
+|                                                     APCI1710_DISABLE:      |
+|                                                     Interrupts are disabled
+
+       b_ModulNbr                      =(BYTE) CR_AREF(insn->chanspec);
+       b_Action                        =(BYTE) data[0];
+       b_PulseEncoderNbr       =(BYTE) data[1];
+       b_CycleSelection        =(BYTE) data[2];
+       b_InterruptHandling     =(BYTE) data[3];|
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection is wrong                          |
+|                     -3: Pulse encoder selection is wrong                   |
+|                     -4: Pulse encoder not initialised.                     |
+|                         See function "i_APCI1710_InitPulseEncoder"         |
+|                     -5: Cycle selection mode is wrong                      |
+|                     -6: Interrupt handling mode is wrong                   |
+|                     -7: Interrupt routine not installed.                   |
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       BYTE b_ModulNbr;
+       BYTE b_PulseEncoderNbr;
+       BYTE b_CycleSelection;
+       BYTE b_InterruptHandling;
+       BYTE b_Action;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_Action = (BYTE) data[0];
+       b_PulseEncoderNbr = (BYTE) data[1];
+       b_CycleSelection = (BYTE) data[2];
+       b_InterruptHandling = (BYTE) data[3];
+
+       /***********************************/
+       /* Test the selected module number */
+       /***********************************/
+
+       if (b_ModulNbr <= 3) {
+          /******************************************/
+               /* Test the selected pulse encoder number */
+          /******************************************/
+
+               if (b_PulseEncoderNbr <= 3) {
+             /*************************************/
+                       /* Test if pulse encoder initialised */
+             /*************************************/
+
+                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_PulseEncoderModuleInfo.
+                               s_PulseEncoderInfo[b_PulseEncoderNbr].
+                               b_PulseEncoderInit == 1) {
+                               switch (b_Action) {
+
+                               case APCI1710_ENABLE:
+                /****************************/
+                                       /* Test the cycle selection */
+                /****************************/
+
+                                       if (b_CycleSelection ==
+                                               APCI1710_CONTINUOUS
+                                               || b_CycleSelection ==
+                                               APCI1710_SINGLE) {
+                   /*******************************/
+                                               /* Test the interrupt handling */
+                   /*******************************/
+
+                                               if (b_InterruptHandling ==
+                                                       APCI1710_ENABLE
+                                                       || b_InterruptHandling
+                                                       == APCI1710_DISABLE) {
+                      /******************************/
+                                                       /* Test if interrupt not used */
+                      /******************************/
+
+                                                       if (b_InterruptHandling
+                                                               ==
+                                                               APCI1710_DISABLE)
+                                                       {
+                         /*************************/
+                                                               /* Disable the interrupt */
+                         /*************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       &
+                                                                       (0xFFFFFFFFUL
+                                                                       -
+                                                                       (1UL << b_PulseEncoderNbr));
+                                                       } else {
+
+                            /************************/
+                                                               /* Enable the interrupt */
+                            /************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister
+                                                                       | (1UL
+                                                                       <<
+                                                                       b_PulseEncoderNbr);
+                                                               devpriv->tsk_Current = current; // Save the current process task structure
+
+                                                       }
+
+                                                       if (i_ReturnValue >= 0) {
+                         /***********************************/
+                                                               /* Enable or disable the interrupt */
+                         /***********************************/
+
+                                                               outl(devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_SetRegister,
+                                                                       devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 20 +
+                                                                       (64 * b_ModulNbr));
+
+                         /****************************/
+                                                               /* Enable the pulse encoder */
+                         /****************************/
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_ControlRegister
+                                                                       =
+                                                                       devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_ControlRegister
+                                                                       | (1UL
+                                                                       <<
+                                                                       b_PulseEncoderNbr);
+
+                         /**********************/
+                                                               /* Set the cycle mode */
+                         /**********************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_ControlRegister
+                                                                       =
+                                                                       (devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_ControlRegister
+                                                                       &
+                                                                       (0xFFFFFFFFUL
+                                                                               -
+                                                                               (1 << (b_PulseEncoderNbr + 4)))) | ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr));
+
+                         /****************************/
+                                                               /* Enable the pulse encoder */
+                         /****************************/
+
+                                                               outl(devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PulseEncoderModuleInfo.
+                                                                       dw_ControlRegister,
+                                                                       devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 16 +
+                                                                       (64 * b_ModulNbr));
+                                                       }
+                                               } else {
+                      /************************************/
+                                                       /* Interrupt handling mode is wrong */
+                      /************************************/
+
+                                                       DPRINTK("Interrupt handling mode is wrong\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       } else {
+                   /*********************************/
+                                               /* Cycle selection mode is wrong */
+                   /*********************************/
+
+                                               DPRINTK("Cycle selection mode is wrong\n");
+                                               i_ReturnValue = -5;
+                                       }
+                                       break;
+
+                               case APCI1710_DISABLE:
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_ControlRegister =
+                                               devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_ControlRegister &
+                                               (0xFFFFFFFFUL -
+                                               (1UL << b_PulseEncoderNbr));
+
+                /*****************************/
+                                       /* Disable the pulse encoder */
+                /*****************************/
+
+                                       outl(devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_ControlRegister,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 16 +
+                                               (64 * b_ModulNbr));
+
+                                       break;
+                               }       // switch End
+
+                       } else {
+                /*********************************/
+                               /* Pulse encoder not initialised */
+                /*********************************/
+
+                               DPRINTK("Pulse encoder not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /************************************/
+                       /* Pulse encoder selection is wrong */
+             /************************************/
+
+                       DPRINTK("Pulse encoder selection is wrong\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*****************************/
+               /* Module selection is wrong */
+          /*****************************/
+
+               DPRINTK("Module selection is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ReadPulseEncoderStatus                |
+|                                       (BYTE_  b_BoardHandle,               |
+|                                        BYTE_  b_ModulNbr,                  |
+|                                        BYTE_  b_PulseEncoderNbr,           |
+|                                        PBYTE_ pb_Status)                   |
++----------------------------------------------------------------------------+
+| Task    APCI1710_PULSEENCODER_READ          : Reads the pulse encoder status
+                                                                                       and valuefrom selected pulse     |
+|                     encoder (b_PulseEncoderNbr) from selected module       |
+|                     (b_ModulNbr).                                          |
++----------------------------------------------------------------------------+
+       BYTE   b_Type; data[0]
+   APCI1710_PULSEENCODER_WRITE
+ Writes a 32-bit value (ul_WriteValue) into the selected|
+|                     pulse encoder (b_PulseEncoderNbr) from selected module |
+|                     (b_ModulNbr). This operation set the new start pulse   |
+|                     encoder value.
+ APCI1710_PULSEENCODER_READ
+| Input Parameters  : BYTE_   b_BoardHandle       : Handle of board APCI-1710|
+|            CRAREF()         BYTE_   b_ModulNbr          : Module number to         |
+|                                                   configure (0 to 3)       |
+|              data[1]       BYTE_   b_PulseEncoderNbr   : Pulse encoder selection  |
+|                                                   (0 to 3)
+   APCI1710_PULSEENCODER_WRITE
+                               data[2]         ULONG_ ul_WriteValue        : 32-bit value to be       |
+|                                                   written             |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_Status            : Pulse encoder status.    |
+|                                                       0 : No overflow occur|
+|                                                       1 : Overflow occur
+                                               PULONG_ pul_ReadValue       : Pulse encoder value      |  |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection is wrong                          |
+|                     -3: Pulse encoder selection is wrong                   |
+|                     -4: Pulse encoder not initialised.                     |
+|                         See function "i_APCI1710_InitPulseEncoder"         |
++----------------------------------------------------------------------------+
+*/
+
+/*_INT_   i_APCI1710_ReadPulseEncoderStatus       (BYTE_   b_BoardHandle,
+                                                BYTE_   b_ModulNbr,
+                                                BYTE_   b_PulseEncoderNbr,
+
+                                                PBYTE_ pb_Status)
+                                                */
+INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusRegister;
+       BYTE b_ModulNbr;
+       BYTE b_PulseEncoderNbr;
+       PBYTE pb_Status;
+       BYTE b_Type;
+       PULONG pul_ReadValue;
+       ULONG ul_WriteValue;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_Type = (BYTE) data[0];
+       b_PulseEncoderNbr = (BYTE) data[1];
+       pb_Status = (PBYTE) & data[0];
+       pul_ReadValue = (PULONG) & data[1];
+
+       /***********************************/
+       /* Test the selected module number */
+       /***********************************/
+
+       if (b_ModulNbr <= 3) {
+          /******************************************/
+               /* Test the selected pulse encoder number */
+          /******************************************/
+
+               if (b_PulseEncoderNbr <= 3) {
+             /*************************************/
+                       /* Test if pulse encoder initialised */
+             /*************************************/
+
+                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_PulseEncoderModuleInfo.
+                               s_PulseEncoderInfo[b_PulseEncoderNbr].
+                               b_PulseEncoderInit == 1) {
+
+                               switch (b_Type) {
+                               case APCI1710_PULSEENCODER_READ:
+                /****************************/
+                                       /* Read the status register */
+                /****************************/
+
+                                       dw_StatusRegister =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 16 +
+                                               (64 * b_ModulNbr));
+
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_StatusRegister = devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_StatusRegister |
+                                               dw_StatusRegister;
+
+                                       *pb_Status =
+                                               (BYTE) (devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_StatusRegister >> (1 +
+                                                       b_PulseEncoderNbr)) & 1;
+
+                                       devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_StatusRegister =
+                                               devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_PulseEncoderModuleInfo.
+                                               dw_StatusRegister &
+                                               (0xFFFFFFFFUL - (1 << (1 +
+                                                               b_PulseEncoderNbr)));
+
+                /******************/
+                                       /* Read the value */
+                /******************/
+
+                                       *pul_ReadValue =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address +
+                                               (4 * b_PulseEncoderNbr) +
+                                               (64 * b_ModulNbr));
+                                       break;
+
+                               case APCI1710_PULSEENCODER_WRITE:
+                                       ul_WriteValue = (ULONG) data[2];
+                       /*******************/
+                                       /* Write the value */
+                       /*******************/
+
+                                       outl(ul_WriteValue,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address +
+                                               (4 * b_PulseEncoderNbr) +
+                                               (64 * b_ModulNbr));
+
+                               }       //end of switch
+                       } else {
+                /*********************************/
+                               /* Pulse encoder not initialised */
+                /*********************************/
+
+                               DPRINTK("Pulse encoder not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /************************************/
+                       /* Pulse encoder selection is wrong */
+             /************************************/
+
+                       DPRINTK("Pulse encoder selection is wrong\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*****************************/
+               /* Module selection is wrong */
+          /*****************************/
+
+               DPRINTK("Module selection is wrong\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+       data[0] = devpriv->s_InterruptParameters.
+               s_FIFOInterruptParameters[devpriv->
+               s_InterruptParameters.ui_Read].b_OldModuleMask;
+       data[1] = devpriv->s_InterruptParameters.
+               s_FIFOInterruptParameters[devpriv->
+               s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+       data[2] = devpriv->s_InterruptParameters.
+               s_FIFOInterruptParameters[devpriv->
+               s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+       /***************************/
+       /* Increment the read FIFO */
+       /***************************/
+
+       devpriv->s_InterruptParameters.
+               ui_Read = (devpriv->
+               s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+       return insn->n;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
new file mode 100644 (file)
index 0000000..c6d0775
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_SINGLE     0
+#define APCI1710_CONTINUOUS 1
+
+#define APCI1710_PULSEENCODER_READ             0
+#define APCI1710_PULSEENCODER_WRITE            1
+
+INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+/*
++----------------------------------------------------------------------------+
+|                       READ PULSE ENCODER FUNCTIONS                         |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*
++----------------------------------------------------------------------------+
+|                       WRITE PULSE ENCODER FUNCTIONS                        |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
new file mode 100644 (file)
index 0000000..a3b44b9
--- /dev/null
@@ -0,0 +1,3588 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : PWM.C           | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 Wulse wide modulation module                |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +-----------------------------------------------------------------------+
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Pwm.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT i_APCI1710_InsnConfigPWM(comedi_device *dev,
+comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                        |
++----------------------------------------------------------------------------+
+| Task              : Pwm Init and Get Pwm Initialisation                    |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigPWM(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_ConfigType;
+       INT i_ReturnValue = 0;
+       b_ConfigType = CR_CHAN(insn->chanspec);
+
+       switch (b_ConfigType) {
+       case APCI1710_PWM_INIT:
+               i_ReturnValue = i_APCI1710_InitPWM(dev, (BYTE) CR_AREF(insn->chanspec), //  b_ModulNbr
+                       (BYTE) data[0], //b_PWM
+                       (BYTE) data[1], // b_ClockSelection
+                       (BYTE) data[2], // b_TimingUnit
+                       (ULONG) data[3],        //ul_LowTiming
+                       (ULONG) data[4],        //ul_HighTiming
+                       (PULONG) & data[0],     //pul_RealLowTiming
+                       (PULONG) & data[1]      //pul_RealHighTiming
+                       );
+               break;
+
+       case APCI1710_PWM_GETINITDATA:
+               i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (BYTE) CR_AREF(insn->chanspec),    // b_ModulNbr
+                       (BYTE) data[0], //b_PWM
+                       (PBYTE) & data[0],      //pb_TimingUnit
+                       (PULONG) & data[1],     //pul_LowTiming
+                       (PULONG) & data[2],     //pul_HighTiming
+                       (PBYTE) & data[3],      // pb_StartLevel
+                       (PBYTE) & data[4],      // pb_StopMode
+                       (PBYTE) & data[5],      // pb_StopLevel
+                       (PBYTE) & data[6],      // pb_ExternGate
+                       (PBYTE) & data[7],      // pb_InterruptEnable
+                       (PBYTE) & data[8]       // pb_Enable
+                       );
+               break;
+
+       default:
+               printk(" Config Parameter Wrong\n");
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitPWM                               |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_PWM,                    |
+|                                        BYTE_     b_ClockSelection,         |
+|                                        BYTE_     b_TimingUnit,             |
+|                                        ULONG_   ul_LowTiming,              |
+|                                        ULONG_   ul_HighTiming,             |
+|                                        PULONG_ pul_RealLowTiming,          |
+|                                        PULONG_ pul_RealHighTiming)         |
++----------------------------------------------------------------------------+
+| Task              : Configure the selected PWM (b_PWM) from selected module|
+|                     (b_ModulNbr). The ul_LowTiming, ul_HighTiming and      |
+|                     ul_TimingUnit determine the low/high timing base for   |
+|                     the period. pul_RealLowTiming, pul_RealHighTiming      |
+|                     return the real timing value.                          |
+|                     You must calling this function be for you call any     |
+|                     other function witch access of the PWM.                |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_     b_BoardHandle    : Handle of board APCI-1710 |
+|                     BYTE_     b_ModulNbr       : Module number to configure|
+|                                                  (0 to 3)                  |
+|                     BYTE_     b_PWM            : Selected PWM (0 or 1).    |
+|                     BYTE_     b_ClockSelection : Selection from PCI bus    |
+|                                                  clock                     |
+|                                                   - APCI1710_30MHZ :       |
+|                                                     The PC have a 30 MHz   |
+|                                                     PCI bus clock          |
+|                                                   - APCI1710_33MHZ :       |
+|                                                     The PC have a 33 MHz   |
+|                                                     PCI bus clock          |
+|                                                   - APCI1710_40MHZ         |
+|                                                     The APCI-1710 have a   |
+|                                                     integrated 40Mhz       |
+|                                                     quartz.                |
+|                     BYTE_     b_TimingUnit     : Base timing Unit (0 to 4) |
+|                                                       0 : ns               |
+|                                                       1 : Ã¦s               |
+|                                                       2 : ms               |
+|                                                       3 : s                |
+|                                                       4 : mn               |
+|                     ULONG_    ul_LowTiming     : Low base timing value.    |
+|                     ULONG_    ul_HighTiming    : High base timing value.   |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pul_RealLowTiming  : Real low base timing     |
+|                                                   value.                   |
+|                     PULONG_  pul_RealHighTiming : Real high base timing    |
+|                                                   value.                   |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: The module is not a PWM module                      |
+|                    -4: PWM selection is wrong                              |
+|                    -5: The selected input clock is wrong                   |
+|                    -6: Timing Unit selection is wrong                      |
+|                    -7: Low base timing selection is wrong                  |
+|                    -8: High base timing selection is wrong                 |
+|                    -9: You can not used the 40MHz clock selection with     |
+|                        this board                                          |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitPWM(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM,
+       BYTE b_ClockSelection,
+       BYTE b_TimingUnit,
+       ULONG ul_LowTiming,
+       ULONG ul_HighTiming,
+       PULONG pul_RealLowTiming, PULONG pul_RealHighTiming)
+{
+       INT i_ReturnValue = 0;
+       ULONG ul_LowTimerValue = 0;
+       ULONG ul_HighTimerValue = 0;
+       DWORD dw_Command;
+       double d_RealLowTiming = 0;
+       double d_RealHighTiming = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***************/
+               /* Test if PWM */
+          /***************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_PWM) {
+             /**************************/
+                       /* Test the PWM selection */
+             /**************************/
+
+                       if (b_PWM <= 1) {
+                /******************/
+                               /* Test the clock */
+                /******************/
+
+                               if ((b_ClockSelection == APCI1710_30MHZ) ||
+                                       (b_ClockSelection == APCI1710_33MHZ) ||
+                                       (b_ClockSelection == APCI1710_40MHZ)) {
+                   /************************/
+                                       /* Test the timing unit */
+                   /************************/
+
+                                       if (b_TimingUnit <= 4) {
+                      /*********************************/
+                                               /* Test the low timing selection */
+                      /*********************************/
+
+                                               if (((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 0)
+                                                               && (ul_LowTiming
+                                                                       >= 266)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       0xFFFFFFFFUL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 1)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       571230650UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 2)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       571230UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 3)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       571UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 4)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <= 9UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 0)
+                                                               && (ul_LowTiming
+                                                                       >= 242)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       0xFFFFFFFFUL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 1)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       519691043UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 2)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       519691UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 3)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       520UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 4)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <= 8UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 0)
+                                                               && (ul_LowTiming
+                                                                       >= 200)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       0xFFFFFFFFUL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 1)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       429496729UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 2)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       429496UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 3)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       429UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 4)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       7UL))) {
+                         /**********************************/
+                                                       /* Test the High timing selection */
+                         /**********************************/
+
+                                                       if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
+                            /**************************/
+                                                               /* Test the board version */
+                            /**************************/
+
+                                                               if (((b_ClockSelection == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_ClockSelection != APCI1710_40MHZ)) {
+
+                               /************************************/
+                                                                       /* Calculate the low division fator */
+                               /************************************/
+
+                                                                       fpu_begin
+                                                                               ();
+
+                                                                       switch (b_TimingUnit) {
+                                  /******/
+                                                                               /* ns */
+                                  /******/
+
+                                                                       case 0:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTiming
+                                                                                       *
+                                                                                       (0.00025 * b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               ul_LowTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealLowTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTimerValue
+                                                                                       /
+                                                                                       (0.00025 * (double)b_ClockSelection));
+                                                                               d_RealLowTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_LowTimerValue
+                                                                                       /
+                                                                                       (0.00025
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+                                                                                       *pul_RealLowTiming
+                                                                                               =
+                                                                                               *pul_RealLowTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_LowTiming
+                                                                                       =
+                                                                                       ul_LowTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_LowTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* Ã¦s */
+                                  /******/
+
+                                                                       case 1:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTiming
+                                                                                       *
+                                                                                       (0.25 * b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               ul_LowTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealLowTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTimerValue
+                                                                                       /
+                                                                                       (0.25 * (double)b_ClockSelection));
+                                                                               d_RealLowTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_LowTimerValue
+                                                                                       /
+                                                                                       (
+                                                                                       (double)
+                                                                                       0.25
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+                                                                                       *pul_RealLowTiming
+                                                                                               =
+                                                                                               *pul_RealLowTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_LowTiming
+                                                                                       =
+                                                                                       ul_LowTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_LowTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* ms */
+                                  /******/
+
+                                                                       case 2:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTiming
+                                                                                       *
+                                                                                       (250.0
+                                                                                       *
+                                                                                       b_ClockSelection);
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               ul_LowTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealLowTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTimerValue
+                                                                                       /
+                                                                                       (250.0 * (double)b_ClockSelection));
+                                                                               d_RealLowTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_LowTimerValue
+                                                                                       /
+                                                                                       (250.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+                                                                                       *pul_RealLowTiming
+                                                                                               =
+                                                                                               *pul_RealLowTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_LowTiming
+                                                                                       =
+                                                                                       ul_LowTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_LowTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /*****/
+                                                                               /* s */
+                                  /*****/
+
+                                                                       case 3:
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTiming
+                                                                                       *
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               ul_LowTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealLowTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_ClockSelection));
+                                                                               d_RealLowTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_LowTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+                                                                                       *pul_RealLowTiming
+                                                                                               =
+                                                                                               *pul_RealLowTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_LowTiming
+                                                                                       =
+                                                                                       ul_LowTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_LowTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* mn */
+                                  /******/
+
+                                                                       case 4:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (ul_LowTiming
+                                                                                               *
+                                                                                               60)
+                                                                                       *
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               ul_LowTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealLowTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_LowTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_ClockSelection))
+                                                                                       /
+                                                                                       60;
+                                                                               d_RealLowTiming
+                                                                                       =
+                                                                                       (
+                                                                                       (double)
+                                                                                       ul_LowTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_ClockSelection))
+                                                                                       /
+                                                                                       60.0;
+
+                                                                               if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+                                                                                       *pul_RealLowTiming
+                                                                                               =
+                                                                                               *pul_RealLowTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_LowTiming
+                                                                                       =
+                                                                                       ul_LowTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_LowTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_LowTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+                                                                       }
+
+                               /*************************************/
+                                                                       /* Calculate the high division fator */
+                               /*************************************/
+
+                                                                       switch (b_TimingUnit) {
+                                  /******/
+                                                                               /* ns */
+                                  /******/
+
+                                                                       case 0:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTiming
+                                                                                       *
+                                                                                       (0.00025 * b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               ul_HighTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealHighTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTimerValue
+                                                                                       /
+                                                                                       (0.00025 * (double)b_ClockSelection));
+                                                                               d_RealHighTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_HighTimerValue
+                                                                                       /
+                                                                                       (0.00025
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+                                                                                       *pul_RealHighTiming
+                                                                                               =
+                                                                                               *pul_RealHighTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_HighTiming
+                                                                                       =
+                                                                                       ul_HighTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_HighTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* Ã¦s */
+                                  /******/
+
+                                                                       case 1:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTiming
+                                                                                       *
+                                                                                       (0.25 * b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               ul_HighTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealHighTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTimerValue
+                                                                                       /
+                                                                                       (0.25 * (double)b_ClockSelection));
+                                                                               d_RealHighTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_HighTimerValue
+                                                                                       /
+                                                                                       (
+                                                                                       (double)
+                                                                                       0.25
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+                                                                                       *pul_RealHighTiming
+                                                                                               =
+                                                                                               *pul_RealHighTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_HighTiming
+                                                                                       =
+                                                                                       ul_HighTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_HighTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* ms */
+                                  /******/
+
+                                                                       case 2:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTiming
+                                                                                       *
+                                                                                       (250.0
+                                                                                       *
+                                                                                       b_ClockSelection);
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               ul_HighTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealHighTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTimerValue
+                                                                                       /
+                                                                                       (250.0 * (double)b_ClockSelection));
+                                                                               d_RealHighTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_HighTimerValue
+                                                                                       /
+                                                                                       (250.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+                                                                                       *pul_RealHighTiming
+                                                                                               =
+                                                                                               *pul_RealHighTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_HighTiming
+                                                                                       =
+                                                                                       ul_HighTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_HighTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /*****/
+                                                                               /* s */
+                                  /*****/
+
+                                                                       case 3:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTiming
+                                                                                       *
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               ul_HighTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealHighTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_ClockSelection));
+                                                                               d_RealHighTiming
+                                                                                       =
+                                                                                       (double)
+                                                                                       ul_HighTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection);
+
+                                                                               if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+                                                                                       *pul_RealHighTiming
+                                                                                               =
+                                                                                               *pul_RealHighTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_HighTiming
+                                                                                       =
+                                                                                       ul_HighTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_HighTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+
+                                  /******/
+                                                                               /* mn */
+                                  /******/
+
+                                                                       case 4:
+
+                                          /******************/
+                                                                               /* Timer 0 factor */
+                                          /******************/
+
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (ul_HighTiming
+                                                                                               *
+                                                                                               60)
+                                                                                       *
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               b_ClockSelection));
+
+                                          /*******************/
+                                                                               /* Round the value */
+                                          /*******************/
+
+                                                                               if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               ul_HighTimerValue
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                          /*****************************/
+                                                                               /* Calculate the real timing */
+                                          /*****************************/
+
+                                                                               *pul_RealHighTiming
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (ul_HighTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_ClockSelection))
+                                                                                       /
+                                                                                       60;
+                                                                               d_RealHighTiming
+                                                                                       =
+                                                                                       (
+                                                                                       (double)
+                                                                                       ul_HighTimerValue
+                                                                                       /
+                                                                                       (250000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_ClockSelection))
+                                                                                       /
+                                                                                       60.0;
+
+                                                                               if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+                                                                                       *pul_RealHighTiming
+                                                                                               =
+                                                                                               *pul_RealHighTiming
+                                                                                               +
+                                                                                               1;
+                                                                               }
+
+                                                                               ul_HighTiming
+                                                                                       =
+                                                                                       ul_HighTiming
+                                                                                       -
+                                                                                       1;
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       -
+                                                                                       2;
+
+                                                                               if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                                       ul_HighTimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (double)
+                                                                                               (ul_HighTimerValue)
+                                                                                               *
+                                                                                               1.007752288);
+                                                                               }
+
+                                                                               break;
+                                                                       }
+
+                                                                       fpu_end();
+                               /****************************/
+                                                                       /* Save the clock selection */
+                               /****************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_PWMModuleInfo.
+                                                                               b_ClockSelection
+                                                                               =
+                                                                               b_ClockSelection;
+
+                               /************************/
+                                                                       /* Save the timing unit */
+                               /************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_PWMModuleInfo.
+                                                                               s_PWMInfo
+                                                                               [b_PWM].
+                                                                               b_TimingUnit
+                                                                               =
+                                                                               b_TimingUnit;
+
+                               /****************************/
+                                                                       /* Save the low base timing */
+                               /****************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_PWMModuleInfo.
+                                                                               s_PWMInfo
+                                                                               [b_PWM].
+                                                                               d_LowTiming
+                                                                               =
+                                                                               d_RealLowTiming;
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_PWMModuleInfo.
+                                                                               s_PWMInfo
+                                                                               [b_PWM].
+                                                                               ul_RealLowTiming
+                                                                               =
+                                                                               *pul_RealLowTiming;
+
+                               /****************************/
+                                                                       /* Save the high base timing */
+                               /****************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_PWMModuleInfo.
+                                                                               s_PWMInfo
+                                                                               [b_PWM].
+                                                                               d_HighTiming
+                                                                               =
+                                                                               d_RealHighTiming;
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_PWMModuleInfo.
+                                                                               s_PWMInfo
+                                                                               [b_PWM].
+                                                                               ul_RealHighTiming
+                                                                               =
+                                                                               *pul_RealHighTiming;
+
+                               /************************/
+                                                                       /* Write the low timing */
+                               /************************/
+
+                                                                       outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+                               /*************************/
+                                                                       /* Write the high timing */
+                               /*************************/
+
+                                                                       outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+                               /***************************/
+                                                                       /* Set the clock selection */
+                               /***************************/
+
+                                                                       dw_Command
+                                                                               =
+                                                                               inl
+                                                                               (devpriv->
+                                                                               s_BoardInfos.
+                                                                               ui_Address
+                                                                               +
+                                                                               8
+                                                                               +
+                                                                               (20 * b_PWM) + (64 * b_ModulNbr));
+
+                                                                       dw_Command
+                                                                               =
+                                                                               dw_Command
+                                                                               &
+                                                                               0x7F;
+
+                                                                       if (b_ClockSelection == APCI1710_40MHZ) {
+                                                                               dw_Command
+                                                                                       =
+                                                                                       dw_Command
+                                                                                       |
+                                                                                       0x80;
+                                                                       }
+
+                               /***************************/
+                                                                       /* Set the clock selection */
+                               /***************************/
+
+                                                                       outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+                               /*************/
+                                                                       /* PWM init. */
+                               /*************/
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_PWMModuleInfo.
+                                                                               s_PWMInfo
+                                                                               [b_PWM].
+                                                                               b_PWMInit
+                                                                               =
+                                                                               1;
+                                                               } else {
+                               /***************************************************/
+                                                                       /* You can not used the 40MHz clock selection with */
+                                                                       /* this board                                      */
+                               /***************************************************/
+                                                                       DPRINTK("You can not used the 40MHz clock selection with this board\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -9;
+                                                               }
+                                                       } else {
+                            /***************************************/
+                                                               /* High base timing selection is wrong */
+                            /***************************************/
+                                                               DPRINTK("High base timing selection is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -8;
+                                                       }
+                                               } else {
+                         /**************************************/
+                                                       /* Low base timing selection is wrong */
+                         /**************************************/
+                                                       DPRINTK("Low base timing selection is wrong\n");
+                                                       i_ReturnValue = -7;
+                                               }
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                                       else {
+                      /**********************************/
+                                               /* Timing unit selection is wrong */
+                      /**********************************/
+                                               DPRINTK("Timing unit selection is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                               }       // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ))
+                               else {
+                   /*******************************/
+                                       /* The selected clock is wrong */
+                   /*******************************/
+                                       DPRINTK("The selected clock is wrong\n");
+                                       i_ReturnValue = -5;
+                               }       // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ))
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+                       else {
+                /******************************/
+                               /* Tor PWM selection is wrong */
+                /******************************/
+                               DPRINTK("Tor PWM selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+               } else {
+             /**********************************/
+                       /* The module is not a PWM module */
+             /**********************************/
+                       DPRINTK("The module is not a PWM module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetPWMInitialisation                  |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_PWM,                    |
+|                                        PBYTE_   pb_TimingUnit,             |
+|                                        PULONG_ pul_LowTiming,              |
+|                                        PULONG_ pul_HighTiming,             |
+|                                        PBYTE_   pb_StartLevel,             |
+|                                        PBYTE_   pb_StopMode,               |
+|                                        PBYTE_   pb_StopLevel,              |
+|                                        PBYTE_   pb_ExternGate,             |
+|                                        PBYTE_   pb_InterruptEnable,        |
+|                                        PBYTE_   pb_Enable)                 |
++----------------------------------------------------------------------------+
+| Task              : Return the PWM (b_PWM) initialisation from selected    |
+|                     module (b_ModulNbr). You must calling the              |
+|                     "i_APCI1710_InitPWM" function be for you call this     |
+|                     function.                                              |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |
+|                     BYTE_ b_ModulNbr    : Selected module number (0 to 3)  |
+|                     BYTE_ b_PWM         : Selected PWM (0 or 1)            |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_  pb_TimingUnit      : Base timing Unit (0 to 4) |
+|                                                       0 : ns               |
+|                                                       1 : Ã¦s               |
+|                                                       2 : ms               |
+|                                                       3 : s                |
+|                                                       4 : mn               |
+|                     PULONG_ pul_LowTiming      : Low base timing value.    |
+|                     PULONG_ pul_HighTiming     : High base timing value.   |
+|                     PBYTE_  pb_StartLevel      : Start period level        |
+|                                                  selection                 |
+|                                                       0 : The period start |
+|                                                           with a low level |
+|                                                       1 : The period start |
+|                                                           with a high level|
+|                     PBYTE_  pb_StopMode        : Stop mode selection       |
+|                                                  0 : The PWM is stopped    |
+|                                                      directly after the    |
+|                                                     "i_APCI1710_DisablePWM"|
+|                                                      function and break the|
+|                                                      last period           |
+|                                                  1 : After the             |
+|                                                     "i_APCI1710_DisablePWM"|
+|                                                      function the PWM is   |
+|                                                      stopped at the end    |
+|                                                      from last period cycle|
+|                     PBYTE_  pb_StopLevel        : Stop PWM level selection |
+|                                                    0 : The output signal   |
+|                                                        keep the level after|
+|                                                        the                 |
+|                                                     "i_APCI1710_DisablePWM"|
+|                                                        function            |
+|                                                    1 : The output signal is|
+|                                                        set to low after the|
+|                                                     "i_APCI1710_DisablePWM"|
+|                                                        function            |
+|                                                    2 : The output signal is|
+|                                                        set to high after   |
+|                                                        the                 |
+|                                                     "i_APCI1710_DisablePWM"|
+|                                                        function            |
+|                     PBYTE_  pb_ExternGate      : Extern gate action        |
+|                                                  selection                 |
+|                                                   0 : Extern gate signal   |
+|                                                       not used.            |
+|                                                   1 : Extern gate signal   |
+|                                                       used.                |
+|                     PBYTE_  pb_InterruptEnable : Enable or disable the PWM |
+|                                                  interrupt.                |
+|                                                  - APCI1710_ENABLE :       |
+|                                                    Enable the PWM interrupt|
+|                                                    A interrupt occur after |
+|                                                    each period             |
+|                                                  - APCI1710_DISABLE :      |
+|                                                    Disable the PWM         |
+|                                                    interrupt               |
+|                     PBYTE_  pb_Enable          : Indicate if the PWM is    |
+|                                                  enabled or no             |
+|                                                       0 : PWM not enabled  |
+|                                                       1 : PWM enabled      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a PWM module                     |
+|                     -4: PWM selection is wrong                             |
+|                     -5: PWM not initialised see function                   |
+|                         "i_APCI1710_InitPWM"                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetPWMInitialisation(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM,
+       PBYTE pb_TimingUnit,
+       PULONG pul_LowTiming,
+       PULONG pul_HighTiming,
+       PBYTE pb_StartLevel,
+       PBYTE pb_StopMode,
+       PBYTE pb_StopLevel,
+       PBYTE pb_ExternGate, PBYTE pb_InterruptEnable, PBYTE pb_Enable)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+       DWORD dw_Command;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***************/
+               /* Test if PWM */
+          /***************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_PWM) {
+             /**************************/
+                       /* Test the PWM selection */
+             /**************************/
+
+                       if (b_PWM <= 1) {
+                /***************************/
+                               /* Test if PWM initialised */
+                /***************************/
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 12 + (20 * b_PWM) +
+                                       (64 * b_ModulNbr));
+
+                               if (dw_Status & 0x10) {
+                   /***********************/
+                                       /* Read the low timing */
+                   /***********************/
+
+                                       *pul_LowTiming =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 0 + (20 * b_PWM) +
+                                               (64 * b_ModulNbr));
+
+                   /************************/
+                                       /* Read the high timing */
+                   /************************/
+
+                                       *pul_HighTiming =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 4 + (20 * b_PWM) +
+                                               (64 * b_ModulNbr));
+
+                   /********************/
+                                       /* Read the command */
+                   /********************/
+
+                                       dw_Command = inl(devpriv->s_BoardInfos.
+                                               ui_Address + 8 + (20 * b_PWM) +
+                                               (64 * b_ModulNbr));
+
+                                       *pb_StartLevel =
+                                               (BYTE) ((dw_Command >> 5) & 1);
+                                       *pb_StopMode =
+                                               (BYTE) ((dw_Command >> 0) & 1);
+                                       *pb_StopLevel =
+                                               (BYTE) ((dw_Command >> 1) & 1);
+                                       *pb_ExternGate =
+                                               (BYTE) ((dw_Command >> 4) & 1);
+                                       *pb_InterruptEnable =
+                                               (BYTE) ((dw_Command >> 3) & 1);
+
+                                       if (*pb_StopLevel) {
+                                               *pb_StopLevel =
+                                                       *pb_StopLevel +
+                                                       (BYTE) ((dw_Command >>
+                                                               2) & 1);
+                                       }
+
+                   /********************/
+                                       /* Read the command */
+                   /********************/
+
+                                       dw_Command = inl(devpriv->s_BoardInfos.
+                                               ui_Address + 8 + (20 * b_PWM) +
+                                               (64 * b_ModulNbr));
+
+                                       *pb_Enable =
+                                               (BYTE) ((dw_Command >> 0) & 1);
+
+                                       *pb_TimingUnit = devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_PWMModuleInfo.
+                                               s_PWMInfo[b_PWM].b_TimingUnit;
+                               }       // if (dw_Status & 0x10)
+                               else {
+                   /***********************/
+                                       /* PWM not initialised */
+                   /***********************/
+                                       DPRINTK("PWM not initialised\n");
+                                       i_ReturnValue = -5;
+                               }       // if (dw_Status & 0x10)
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+                       else {
+                /******************************/
+                               /* Tor PWM selection is wrong */
+                /******************************/
+                               DPRINTK("Tor PWM selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+               } else {
+             /**********************************/
+                       /* The module is not a PWM module */
+             /**********************************/
+                       DPRINTK("The module is not a PWM module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT i_APCI1710_InsnWritePWM(comedi_device *dev,
+comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                        |
++----------------------------------------------------------------------------+
+| Task              : Pwm Enable Disable and Set New Timing                  |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWritePWM(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_WriteType;
+       INT i_ReturnValue = 0;
+       b_WriteType = CR_CHAN(insn->chanspec);
+
+       switch (b_WriteType) {
+       case APCI1710_PWM_ENABLE:
+               i_ReturnValue = i_APCI1710_EnablePWM(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) data[0],
+                       (BYTE) data[1],
+                       (BYTE) data[2],
+                       (BYTE) data[3], (BYTE) data[4], (BYTE) data[5]);
+               break;
+
+       case APCI1710_PWM_DISABLE:
+               i_ReturnValue = i_APCI1710_DisablePWM(dev,
+                       (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+               break;
+
+       case APCI1710_PWM_NEWTIMING:
+               i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev,
+                       (BYTE) CR_AREF(insn->chanspec),
+                       (BYTE) data[0],
+                       (BYTE) data[1], (ULONG) data[2], (ULONG) data[3]);
+               break;
+
+       default:
+               printk("Write Config Parameter Wrong\n");
+       }
+
+       if (i_ReturnValue >= 0)
+               i_ReturnValue = insn->n;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_EnablePWM                         |
+|                                       (BYTE_  b_BoardHandle,               |
+|                                        BYTE_  b_ModulNbr,                  |
+|                                        BYTE_  b_PWM,                       |
+|                                        BYTE_  b_StartLevel,                |
+|                                        BYTE_  b_StopMode,                  |
+|                                        BYTE_  b_StopLevel,                 |
+|                                        BYTE_  b_ExternGate,                |
+|                                        BYTE_  b_InterruptEnable)           |
++----------------------------------------------------------------------------+
+| Task              : Enable the selected PWM (b_PWM) from selected module   |
+|                     (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"|
+|                     function be for you call this function.                |
+|                     If you enable the PWM interrupt, the PWM generate a    |
+|                     interrupt after each period.                           |
+|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
+|                     Interrupt mask description chapter.                    |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |
+|                     BYTE_ b_ModulNbr        : Selected module number       |
+|                                               (0 to 3)                     |
+|                     BYTE_ b_PWM             : Selected PWM (0 or 1)        |
+|                     BYTE_ b_StartLevel      : Start period level selection |
+|                                                0 : The period start with a |
+|                                                    low level               |
+|                                                1 : The period start with a |
+|                                                    high level              |
+|                     BYTE_ b_StopMode        : Stop mode selection          |
+|                                                0 : The PWM is stopped      |
+|                                                    directly after the      |
+|                                                    "i_APCI1710_DisablePWM" |
+|                                                    function and break the  |
+|                                                    last period             |
+|                                                1 : After the               |
+|                                                    "i_APCI1710_DisablePWM" |
+|                                                     function the PWM is    |
+|                                                     stopped at the end from|
+|                                                     last period cycle.     |
+|                     BYTE_ b_StopLevel       : Stop PWM level selection     |
+|                                                0 : The output signal keep  |
+|                                                    the level after the     |
+|                                                    "i_APCI1710_DisablePWM" |
+|                                                    function                |
+|                                                1 : The output signal is set|
+|                                                    to low after the        |
+|                                                    "i_APCI1710_DisablePWM" |
+|                                                    function                |
+|                                                2 : The output signal is set|
+|                                                    to high after the       |
+|                                                    "i_APCI1710_DisablePWM" |
+|                                                    function                |
+|                     BYTE_ b_ExternGate      : Extern gate action selection |
+|                                                0 : Extern gate signal not  |
+|                                                    used.                   |
+|                                                1 : Extern gate signal used.|
+|                     BYTE_ b_InterruptEnable : Enable or disable the PWM    |
+|                                               interrupt.                   |
+|                                               - APCI1710_ENABLE :          |
+|                                                 Enable the PWM interrupt   |
+|                                                 A interrupt occur after    |
+|                                                 each period                |
+|                                               - APCI1710_DISABLE :         |
+|                                                 Disable the PWM interrupt  |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0:  No error                                           |
+|                    -1:  The handle parameter of the board is wrong         |
+|                    -2:  Module selection wrong                             |
+|                    -3:  The module is not a PWM module                     |
+|                    -4:  PWM selection is wrong                             |
+|                    -5:  PWM not initialised see function                   |
+|                         "i_APCI1710_InitPWM"                               |
+|                    -6:  PWM start level selection is wrong                 |
+|                    -7:  PWM stop mode selection is wrong                   |
+|                    -8:  PWM stop level selection is wrong                  |
+|                    -9:  Extern gate signal selection is wrong              |
+|                    -10: Interrupt parameter is wrong                       |
+|                    -11: Interrupt function not initialised.                |
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnablePWM(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM,
+       BYTE b_StartLevel,
+       BYTE b_StopMode,
+       BYTE b_StopLevel, BYTE b_ExternGate, BYTE b_InterruptEnable)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+       DWORD dw_Command;
+
+       devpriv->tsk_Current = current; // Save the current process task structure
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***************/
+               /* Test if PWM */
+          /***************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_PWM) {
+             /**************************/
+                       /* Test the PWM selection */
+             /**************************/
+
+                       if (b_PWM <= 1) {
+                /***************************/
+                               /* Test if PWM initialised */
+                /***************************/
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 12 + (20 * b_PWM) +
+                                       (64 * b_ModulNbr));
+
+                               if (dw_Status & 0x10) {
+                   /**********************************/
+                                       /* Test the start level selection */
+                   /**********************************/
+
+                                       if (b_StartLevel <= 1) {
+                      /**********************/
+                                               /* Test the stop mode */
+                      /**********************/
+
+                                               if (b_StopMode <= 1) {
+                         /***********************/
+                                                       /* Test the stop level */
+                         /***********************/
+
+                                                       if (b_StopLevel <= 2) {
+                            /*****************************/
+                                                               /* Test the extern gate mode */
+                            /*****************************/
+
+                                                               if (b_ExternGate
+                                                                       <= 1) {
+                               /*****************************/
+                                                                       /* Test the interrupt action */
+                               /*****************************/
+
+                                                                       if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) {
+                                  /******************************************/
+                                                                               /* Test if interrupt function initialised */
+                                  /******************************************/
+
+                                     /********************/
+                                                                               /* Read the command */
+                                     /********************/
+
+                                                                               dw_Command
+                                                                                       =
+                                                                                       inl
+                                                                                       (devpriv->
+                                                                                       s_BoardInfos.
+                                                                                       ui_Address
+                                                                                       +
+                                                                                       8
+                                                                                       +
+                                                                                       (20 * b_PWM) + (64 * b_ModulNbr));
+
+                                                                               dw_Command
+                                                                                       =
+                                                                                       dw_Command
+                                                                                       &
+                                                                                       0x80;
+
+                                     /********************/
+                                                                               /* Make the command */
+                                     /********************/
+
+                                                                               dw_Command
+                                                                                       =
+                                                                                       dw_Command
+                                                                                       |
+                                                                                       b_StopMode
+                                                                                       |
+                                                                                       (b_InterruptEnable
+                                                                                       <<
+                                                                                       3)
+                                                                                       |
+                                                                                       (b_ExternGate
+                                                                                       <<
+                                                                                       4)
+                                                                                       |
+                                                                                       (b_StartLevel
+                                                                                       <<
+                                                                                       5);
+
+                                                                               if (b_StopLevel & 3) {
+                                                                                       dw_Command
+                                                                                               =
+                                                                                               dw_Command
+                                                                                               |
+                                                                                               2;
+
+                                                                                       if (b_StopLevel & 2) {
+                                                                                               dw_Command
+                                                                                                       =
+                                                                                                       dw_Command
+                                                                                                       |
+                                                                                                       4;
+                                                                                       }
+                                                                               }
+
+                                                                               devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_PWMModuleInfo.
+                                                                                       s_PWMInfo
+                                                                                       [b_PWM].
+                                                                                       b_InterruptEnable
+                                                                                       =
+                                                                                       b_InterruptEnable;
+
+                                     /*******************/
+                                                                               /* Set the command */
+                                     /*******************/
+
+                                                                               outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+                                     /******************/
+                                                                               /* Enable the PWM */
+                                     /******************/
+                                                                               outl(1, devpriv->s_BoardInfos.ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr));
+                                                                       }       // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE)
+                                                                       else {
+                                  /********************************/
+                                                                               /* Interrupt parameter is wrong */
+                                  /********************************/
+                                                                               DPRINTK("Interrupt parameter is wrong\n");
+                                                                               i_ReturnValue
+                                                                                       =
+                                                                                       -10;
+                                                                       }       // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE)
+                                                               }       // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+                                                               else {
+                               /*****************************************/
+                                                                       /* Extern gate signal selection is wrong */
+                               /*****************************************/
+                                                                       DPRINTK("Extern gate signal selection is wrong\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -9;
+                                                               }       // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+                                                       }       // if (b_StopLevel >= 0 && b_StopLevel <= 2)
+                                                       else {
+                            /*************************************/
+                                                               /* PWM stop level selection is wrong */
+                            /*************************************/
+                                                               DPRINTK("PWM stop level selection is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -8;
+                                                       }       // if (b_StopLevel >= 0 && b_StopLevel <= 2)
+                                               }       // if (b_StopMode >= 0 && b_StopMode <= 1)
+                                               else {
+                         /************************************/
+                                                       /* PWM stop mode selection is wrong */
+                         /************************************/
+                                                       DPRINTK("PWM stop mode selection is wrong\n");
+                                                       i_ReturnValue = -7;
+                                               }       // if (b_StopMode >= 0 && b_StopMode <= 1)
+                                       }       // if (b_StartLevel >= 0 && b_StartLevel <= 1)
+                                       else {
+                      /**************************************/
+                                               /* PWM start level selection is wrong */
+                      /**************************************/
+                                               DPRINTK("PWM start level selection is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }       // if (b_StartLevel >= 0 && b_StartLevel <= 1)
+                               }       // if (dw_Status & 0x10)
+                               else {
+                   /***********************/
+                                       /* PWM not initialised */
+                   /***********************/
+                                       DPRINTK("PWM not initialised\n");
+                                       i_ReturnValue = -5;
+                               }       // if (dw_Status & 0x10)
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+                       else {
+                /******************************/
+                               /* Tor PWM selection is wrong */
+                /******************************/
+                               DPRINTK("Tor PWM selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+               } else {
+             /**********************************/
+                       /* The module is not a PWM module */
+             /**********************************/
+                       DPRINTK("The module is not a PWM module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_DisablePWM (BYTE_  b_BoardHandle,     |
+|                                                  BYTE_  b_ModulNbr,        |
+|                                                  BYTE_  b_PWM)             |
++----------------------------------------------------------------------------+
+| Task              : Disable the selected PWM (b_PWM) from selected module  |
+|                     (b_ModulNbr). The output signal level depend of the    |
+|                     initialisation by the "i_APCI1710_EnablePWM".          |
+|                     See the b_StartLevel, b_StopMode and b_StopLevel       |
+|                     parameters from this function.                         |
++----------------------------------------------------------------------------+
+| Input Parameters  :BYTE_ b_BoardHandle : Handle of board APCI-1710         |
+|                    BYTE_ b_ModulNbr    : Selected module number (0 to 3)   |
+|                    BYTE_ b_PWM         : Selected PWM (0 or 1)             |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a PWM module                     |
+|                     -4: PWM selection is wrong                             |
+|                     -5: PWM not initialised see function                   |
+|                         "i_APCI1710_InitPWM"                               |
+|                     -6: PWM not enabled see function                       |
+|                         "i_APCI1710_EnablePWM"                             |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisablePWM(comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***************/
+               /* Test if PWM */
+          /***************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_PWM) {
+             /**************************/
+                       /* Test the PWM selection */
+             /**************************/
+
+                       if (b_PWM <= 1) {
+                /***************************/
+                               /* Test if PWM initialised */
+                /***************************/
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 12 + (20 * b_PWM) +
+                                       (64 * b_ModulNbr));
+
+                               if (dw_Status & 0x10) {
+                   /***********************/
+                                       /* Test if PWM enabled */
+                   /***********************/
+
+                                       if (dw_Status & 0x1) {
+                      /*******************/
+                                               /* Disable the PWM */
+                      /*******************/
+                                               outl(0, devpriv->s_BoardInfos.
+                                                       ui_Address + 12 +
+                                                       (20 * b_PWM) +
+                                                       (64 * b_ModulNbr));
+                                       }       // if (dw_Status & 0x1)
+                                       else {
+                      /*******************/
+                                               /* PWM not enabled */
+                      /*******************/
+                                               DPRINTK("PWM not enabled\n");
+                                               i_ReturnValue = -6;
+                                       }       // if (dw_Status & 0x1)
+                               }       // if (dw_Status & 0x10)
+                               else {
+                   /***********************/
+                                       /* PWM not initialised */
+                   /***********************/
+                                       DPRINTK(" PWM not initialised\n");
+                                       i_ReturnValue = -5;
+                               }       // if (dw_Status & 0x10)
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+                       else {
+                /******************************/
+                               /* Tor PWM selection is wrong */
+                /******************************/
+                               DPRINTK("Tor PWM selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+               } else {
+             /**********************************/
+                       /* The module is not a PWM module */
+             /**********************************/
+                       DPRINTK("The module is not a PWM module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_SetNewPWMTiming                       |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_PWM,                    |
+|                                        BYTE_     b_ClockSelection,         |
+|                                        BYTE_     b_TimingUnit,             |
+|                                        ULONG_   ul_LowTiming,              |
+|                                        ULONG_   ul_HighTiming)             |
++----------------------------------------------------------------------------+
+| Task              : Set a new timing. The ul_LowTiming, ul_HighTiming and  |
+|                     ul_TimingUnit determine the low/high timing base for   |
+|                     the period.                                            |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_     b_BoardHandle    : Handle of board APCI-1710 |
+|                     BYTE_     b_ModulNbr       : Module number to configure|
+|                                                  (0 to 3)                  |
+|                     BYTE_     b_PWM            : Selected PWM (0 or 1).    |
+|                     BYTE_     b_TimingUnit     : Base timing Unit (0 to 4) |
+|                                                       0 : ns               |
+|                                                       1 : Ã¦s               |
+|                                                       2 : ms               |
+|                                                       3 : s                |
+|                                                       4 : mn               |
+|                     ULONG_    ul_LowTiming     : Low base timing value.    |
+|                     ULONG_    ul_HighTiming    : High base timing value.   |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: Module selection wrong                              |
+|                    -3: The module is not a PWM module                      |
+|                    -4: PWM selection is wrong                              |
+|                    -5: PWM not initialised                                 |
+|                    -6: Timing Unit selection is wrong                      |
+|                    -7: Low base timing selection is wrong                  |
+|                    -8: High base timing selection is wrong                 |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetNewPWMTiming(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM, BYTE b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming)
+{
+       BYTE b_ClockSelection;
+       INT i_ReturnValue = 0;
+       ULONG ul_LowTimerValue = 0;
+       ULONG ul_HighTimerValue = 0;
+       ULONG ul_RealLowTiming = 0;
+       ULONG ul_RealHighTiming = 0;
+       DWORD dw_Status;
+       DWORD dw_Command;
+       double d_RealLowTiming = 0;
+       double d_RealHighTiming = 0;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***************/
+               /* Test if PWM */
+          /***************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_PWM) {
+             /**************************/
+                       /* Test the PWM selection */
+             /**************************/
+
+                       if (b_PWM <= 1) {
+                /***************************/
+                               /* Test if PWM initialised */
+                /***************************/
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 12 + (20 * b_PWM) +
+                                       (64 * b_ModulNbr));
+
+                               if (dw_Status & 0x10) {
+                                       b_ClockSelection = devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_PWMModuleInfo.
+                                               b_ClockSelection;
+
+                   /************************/
+                                       /* Test the timing unit */
+                   /************************/
+
+                                       if (b_TimingUnit <= 4) {
+                      /*********************************/
+                                               /* Test the low timing selection */
+                      /*********************************/
+
+                                               if (((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 0)
+                                                               && (ul_LowTiming
+                                                                       >= 266)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       0xFFFFFFFFUL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 1)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       571230650UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 2)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       571230UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 3)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       571UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_30MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 4)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <= 9UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 0)
+                                                               && (ul_LowTiming
+                                                                       >= 242)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       0xFFFFFFFFUL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 1)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       519691043UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 2)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       519691UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 3)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       520UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_33MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 4)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <= 8UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 0)
+                                                               && (ul_LowTiming
+                                                                       >= 200)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       0xFFFFFFFFUL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 1)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       429496729UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 2)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       429496UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 3)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       429UL))
+                                                       || ((b_ClockSelection ==
+                                                                       APCI1710_40MHZ)
+                                                               && (b_TimingUnit
+                                                                       == 4)
+                                                               && (ul_LowTiming
+                                                                       >= 1)
+                                                               && (ul_LowTiming
+                                                                       <=
+                                                                       7UL))) {
+                         /**********************************/
+                                                       /* Test the High timing selection */
+                         /**********************************/
+
+                                                       if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
+                            /************************************/
+                                                               /* Calculate the low division fator */
+                            /************************************/
+
+                                                               fpu_begin();
+                                                               switch (b_TimingUnit) {
+                               /******/
+                                                                       /* ns */
+                               /******/
+
+                                                               case 0:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTiming
+                                                                               *
+                                                                               (0.00025 * b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealLowTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTimerValue
+                                                                               /
+                                                                               (0.00025 * (double)b_ClockSelection));
+                                                                       d_RealLowTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_LowTimerValue
+                                                                               /
+                                                                               (0.00025
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+                                                                               ul_RealLowTiming
+                                                                                       =
+                                                                                       ul_RealLowTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_LowTiming
+                                                                               =
+                                                                               ul_LowTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               ul_LowTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_LowTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /******/
+                                                                       /* Ã¦s */
+                               /******/
+
+                                                               case 1:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTiming
+                                                                               *
+                                                                               (0.25 * b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealLowTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTimerValue
+                                                                               /
+                                                                               (0.25 * (double)b_ClockSelection));
+                                                                       d_RealLowTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_LowTimerValue
+                                                                               /
+                                                                               (
+                                                                               (double)
+                                                                               0.25
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+                                                                               ul_RealLowTiming
+                                                                                       =
+                                                                                       ul_RealLowTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_LowTiming
+                                                                               =
+                                                                               ul_LowTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               ul_LowTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_LowTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /******/
+                                                                       /* ms */
+                               /******/
+
+                                                               case 2:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               ul_LowTiming
+                                                                               *
+                                                                               (250.0
+                                                                               *
+                                                                               b_ClockSelection);
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealLowTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTimerValue
+                                                                               /
+                                                                               (250.0 * (double)b_ClockSelection));
+                                                                       d_RealLowTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_LowTimerValue
+                                                                               /
+                                                                               (250.0
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+                                                                               ul_RealLowTiming
+                                                                                       =
+                                                                                       ul_RealLowTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_LowTiming
+                                                                               =
+                                                                               ul_LowTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               ul_LowTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_LowTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /*****/
+                                                                       /* s */
+                               /*****/
+
+                                                               case 3:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTiming
+                                                                               *
+                                                                               (250000.0
+                                                                                       *
+                                                                                       b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealLowTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection));
+                                                                       d_RealLowTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_LowTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+                                                                               ul_RealLowTiming
+                                                                                       =
+                                                                                       ul_RealLowTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_LowTiming
+                                                                               =
+                                                                               ul_LowTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               ul_LowTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_LowTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /******/
+                                                                       /* mn */
+                               /******/
+
+                                                               case 4:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (
+                                                                               (ul_LowTiming
+                                                                                       *
+                                                                                       60)
+                                                                               *
+                                                                               (250000.0
+                                                                                       *
+                                                                                       b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       ul_LowTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealLowTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_LowTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection))
+                                                                               /
+                                                                               60;
+                                                                       d_RealLowTiming
+                                                                               =
+                                                                               (
+                                                                               (double)
+                                                                               ul_LowTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection))
+                                                                               /
+                                                                               60.0;
+
+                                                                       if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealLowTiming + 0.5)) {
+                                                                               ul_RealLowTiming
+                                                                                       =
+                                                                                       ul_RealLowTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_LowTiming
+                                                                               =
+                                                                               ul_LowTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_LowTimerValue
+                                                                               =
+                                                                               ul_LowTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_LowTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_LowTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+                                                               }
+
+                            /*************************************/
+                                                               /* Calculate the high division fator */
+                            /*************************************/
+
+                                                               switch (b_TimingUnit) {
+                               /******/
+                                                                       /* ns */
+                               /******/
+
+                                                               case 0:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTiming
+                                                                               *
+                                                                               (0.00025 * b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealHighTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTimerValue
+                                                                               /
+                                                                               (0.00025 * (double)b_ClockSelection));
+                                                                       d_RealHighTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_HighTimerValue
+                                                                               /
+                                                                               (0.00025
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+                                                                               ul_RealHighTiming
+                                                                                       =
+                                                                                       ul_RealHighTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_HighTiming
+                                                                               =
+                                                                               ul_HighTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               ul_HighTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_HighTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /******/
+                                                                       /* Ã¦s */
+                               /******/
+
+                                                               case 1:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTiming
+                                                                               *
+                                                                               (0.25 * b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealHighTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTimerValue
+                                                                               /
+                                                                               (0.25 * (double)b_ClockSelection));
+                                                                       d_RealHighTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_HighTimerValue
+                                                                               /
+                                                                               (
+                                                                               (double)
+                                                                               0.25
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+                                                                               ul_RealHighTiming
+                                                                                       =
+                                                                                       ul_RealHighTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_HighTiming
+                                                                               =
+                                                                               ul_HighTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               ul_HighTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_HighTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /******/
+                                                                       /* ms */
+                               /******/
+
+                                                               case 2:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               ul_HighTiming
+                                                                               *
+                                                                               (250.0
+                                                                               *
+                                                                               b_ClockSelection);
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealHighTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTimerValue
+                                                                               /
+                                                                               (250.0 * (double)b_ClockSelection));
+                                                                       d_RealHighTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_HighTimerValue
+                                                                               /
+                                                                               (250.0
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+                                                                               ul_RealHighTiming
+                                                                                       =
+                                                                                       ul_RealHighTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_HighTiming
+                                                                               =
+                                                                               ul_HighTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               ul_HighTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_HighTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /*****/
+                                                                       /* s */
+                               /*****/
+
+                                                               case 3:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTiming
+                                                                               *
+                                                                               (250000.0
+                                                                                       *
+                                                                                       b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealHighTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection));
+                                                                       d_RealHighTiming
+                                                                               =
+                                                                               (double)
+                                                                               ul_HighTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                               *
+                                                                               (double)
+                                                                               b_ClockSelection);
+
+                                                                       if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+                                                                               ul_RealHighTiming
+                                                                                       =
+                                                                                       ul_RealHighTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_HighTiming
+                                                                               =
+                                                                               ul_HighTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               ul_HighTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_HighTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+
+                               /******/
+                                                                       /* mn */
+                               /******/
+
+                                                               case 4:
+
+                                       /******************/
+                                                                       /* Timer 0 factor */
+                                       /******************/
+
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               (ULONG)
+                                                                               (
+                                                                               (ul_HighTiming
+                                                                                       *
+                                                                                       60)
+                                                                               *
+                                                                               (250000.0
+                                                                                       *
+                                                                                       b_ClockSelection));
+
+                                       /*******************/
+                                                                       /* Round the value */
+                                       /*******************/
+
+                                                                       if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       ul_HighTimerValue
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                       /*****************************/
+                                                                       /* Calculate the real timing */
+                                       /*****************************/
+
+                                                                       ul_RealHighTiming
+                                                                               =
+                                                                               (ULONG)
+                                                                               (ul_HighTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection))
+                                                                               /
+                                                                               60;
+                                                                       d_RealHighTiming
+                                                                               =
+                                                                               (
+                                                                               (double)
+                                                                               ul_HighTimerValue
+                                                                               /
+                                                                               (250000.0
+                                                                                       *
+                                                                                       (double)
+                                                                                       b_ClockSelection))
+                                                                               /
+                                                                               60.0;
+
+                                                                       if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealHighTiming + 0.5)) {
+                                                                               ul_RealHighTiming
+                                                                                       =
+                                                                                       ul_RealHighTiming
+                                                                                       +
+                                                                                       1;
+                                                                       }
+
+                                                                       ul_HighTiming
+                                                                               =
+                                                                               ul_HighTiming
+                                                                               -
+                                                                               1;
+                                                                       ul_HighTimerValue
+                                                                               =
+                                                                               ul_HighTimerValue
+                                                                               -
+                                                                               2;
+
+                                                                       if (b_ClockSelection != APCI1710_40MHZ) {
+                                                                               ul_HighTimerValue
+                                                                                       =
+                                                                                       (ULONG)
+                                                                                       (
+                                                                                       (double)
+                                                                                       (ul_HighTimerValue)
+                                                                                       *
+                                                                                       1.007752288);
+                                                                       }
+
+                                                                       break;
+                                                               }
+
+                                                               fpu_end();
+
+                            /************************/
+                                                               /* Save the timing unit */
+                            /************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PWMModuleInfo.
+                                                                       s_PWMInfo
+                                                                       [b_PWM].
+                                                                       b_TimingUnit
+                                                                       =
+                                                                       b_TimingUnit;
+
+                            /****************************/
+                                                               /* Save the low base timing */
+                            /****************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PWMModuleInfo.
+                                                                       s_PWMInfo
+                                                                       [b_PWM].
+                                                                       d_LowTiming
+                                                                       =
+                                                                       d_RealLowTiming;
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PWMModuleInfo.
+                                                                       s_PWMInfo
+                                                                       [b_PWM].
+                                                                       ul_RealLowTiming
+                                                                       =
+                                                                       ul_RealLowTiming;
+
+                            /****************************/
+                                                               /* Save the high base timing */
+                            /****************************/
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PWMModuleInfo.
+                                                                       s_PWMInfo
+                                                                       [b_PWM].
+                                                                       d_HighTiming
+                                                                       =
+                                                                       d_RealHighTiming;
+
+                                                               devpriv->
+                                                                       s_ModuleInfo
+                                                                       [b_ModulNbr].
+                                                                       s_PWMModuleInfo.
+                                                                       s_PWMInfo
+                                                                       [b_PWM].
+                                                                       ul_RealHighTiming
+                                                                       =
+                                                                       ul_RealHighTiming;
+
+                            /************************/
+                                                               /* Write the low timing */
+                            /************************/
+
+                                                               outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+                            /*************************/
+                                                               /* Write the high timing */
+                            /*************************/
+
+                                                               outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+                            /***************************/
+                                                               /* Set the clock selection */
+                            /***************************/
+
+                                                               dw_Command =
+                                                                       inl
+                                                                       (devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 8 +
+                                                                       (20 * b_PWM) + (64 * b_ModulNbr));
+
+                                                               dw_Command =
+                                                                       dw_Command
+                                                                       & 0x7F;
+
+                                                               if (b_ClockSelection == APCI1710_40MHZ) {
+                                                                       dw_Command
+                                                                               =
+                                                                               dw_Command
+                                                                               |
+                                                                               0x80;
+                                                               }
+
+                            /***************************/
+                                                               /* Set the clock selection */
+                            /***************************/
+
+                                                               outl(dw_Command,
+                                                                       devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 8 +
+                                                                       (20 * b_PWM) + (64 * b_ModulNbr));
+                                                       } else {
+                            /***************************************/
+                                                               /* High base timing selection is wrong */
+                            /***************************************/
+                                                               DPRINTK("High base timing selection is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -8;
+                                                       }
+                                               } else {
+                         /**************************************/
+                                                       /* Low base timing selection is wrong */
+                         /**************************************/
+                                                       DPRINTK("Low base timing selection is wrong\n");
+                                                       i_ReturnValue = -7;
+                                               }
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                                       else {
+                      /**********************************/
+                                               /* Timing unit selection is wrong */
+                      /**********************************/
+                                               DPRINTK("Timing unit selection is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                               }       // if (dw_Status & 0x10)
+                               else {
+                   /***********************/
+                                       /* PWM not initialised */
+                   /***********************/
+                                       DPRINTK("PWM not initialised\n");
+                                       i_ReturnValue = -5;
+                               }       // if (dw_Status & 0x10)
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+                       else {
+                /******************************/
+                               /* Tor PWM selection is wrong */
+                /******************************/
+                               DPRINTK("Tor PWM selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+               } else {
+             /**********************************/
+                       /* The module is not a PWM module */
+             /**********************************/
+                       DPRINTK("The module is not a PWM module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetPWMStatus                          |
+|                               (BYTE_    b_BoardHandle,                     |
+|                                BYTE_    b_ModulNbr,                        |
+|                                BYTE_    b_PWM,                             |
+|                                PBYTE_  pb_PWMOutputStatus,                 |
+|                                PBYTE_  pb_ExternGateStatus)                |
++----------------------------------------------------------------------------+
+| Task              : Return the status from selected PWM (b_PWM) from       |
+|                     selected module (b_ModulNbr).                          |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_  b_BoardHandle : Handle of board APCI-1710       |
+|                     BYTE_  b_PWM         : Selected PWM (0 or 1)           |
+|                     BYTE_  b_ModulNbr    : Selected module number (0 to 3)
+       b_ModulNbr                      =(BYTE)  CR_AREF(insn->chanspec);
+       b_PWM                           =(BYTE)  data[0];
+
+ |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_  pb_PWMOutputStatus  : Return the PWM output    |
+|                                                   level status.            |
+|                                                    0 : The PWM output level|
+|                                                        is low.             |
+|                                                    1 : The PWM output level|
+|                                                        is high.            |
+|                     PBYTE_  pb_ExternGateStatus : Return the extern gate   |
+|                                                   level status.            |
+|                                                    0 : The extern gate is  |
+|                                                        low.                |
+|                                                    1 : The extern gate is  |
+|                                                        high.
+    pb_PWMOutputStatus =(PBYTE) data[0];
+       pb_ExternGateStatus =(PBYTE) data[1];             |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a PWM module                     |
+|                     -4: PWM selection is wrong                             |
+|                     -5: PWM not initialised see function                   |
+|                         "i_APCI1710_InitPWM"                               |
+|                     -6: PWM not enabled see function "i_APCI1710_EnablePWM"|
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadGetPWMStatus(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+
+       BYTE b_ModulNbr;
+       BYTE b_PWM;
+       PBYTE pb_PWMOutputStatus;
+       PBYTE pb_ExternGateStatus;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_PWM = (BYTE) CR_CHAN(insn->chanspec);
+       pb_PWMOutputStatus = (PBYTE) & data[0];
+       pb_ExternGateStatus = (PBYTE) & data[1];
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***************/
+               /* Test if PWM */
+          /***************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_PWM) {
+             /**************************/
+                       /* Test the PWM selection */
+             /**************************/
+
+                       if (b_PWM <= 1) {
+                /***************************/
+                               /* Test if PWM initialised */
+                /***************************/
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 12 + (20 * b_PWM) +
+                                       (64 * b_ModulNbr));
+
+                               if (dw_Status & 0x10) {
+                   /***********************/
+                                       /* Test if PWM enabled */
+                   /***********************/
+
+                                       if (dw_Status & 0x1) {
+                                               *pb_PWMOutputStatus =
+                                                       (BYTE) ((dw_Status >> 7)
+                                                       & 1);
+                                               *pb_ExternGateStatus =
+                                                       (BYTE) ((dw_Status >> 6)
+                                                       & 1);
+                                       }       // if (dw_Status & 0x1)
+                                       else {
+                      /*******************/
+                                               /* PWM not enabled */
+                      /*******************/
+
+                                               DPRINTK("PWM not enabled \n");
+                                               i_ReturnValue = -6;
+                                       }       // if (dw_Status & 0x1)
+                               }       // if (dw_Status & 0x10)
+                               else {
+                   /***********************/
+                                       /* PWM not initialised */
+                   /***********************/
+
+                                       DPRINTK("PWM not initialised\n");
+                                       i_ReturnValue = -5;
+                               }       // if (dw_Status & 0x10)
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+                       else {
+                /******************************/
+                               /* Tor PWM selection is wrong */
+                /******************************/
+
+                               DPRINTK("Tor PWM selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_PWM >= 0 && b_PWM <= 1)
+               } else {
+             /**********************************/
+                       /* The module is not a PWM module */
+             /**********************************/
+
+                       DPRINTK("The module is not a PWM module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       data[0] = devpriv->s_InterruptParameters.
+               s_FIFOInterruptParameters[devpriv->
+               s_InterruptParameters.ui_Read].b_OldModuleMask;
+       data[1] = devpriv->s_InterruptParameters.
+               s_FIFOInterruptParameters[devpriv->
+               s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+       data[2] = devpriv->s_InterruptParameters.
+               s_FIFOInterruptParameters[devpriv->
+               s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+                            /**************************/
+       /* Increment the read FIFO */
+                            /***************************/
+
+       devpriv->
+               s_InterruptParameters.
+               ui_Read = (devpriv->
+               s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+       return insn->n;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
new file mode 100644 (file)
index 0000000..d72fbf4
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_30MHZ           30
+#define APCI1710_33MHZ           33
+#define APCI1710_40MHZ           40
+
+#define APCI1710_PWM_INIT                      0
+#define APCI1710_PWM_GETINITDATA       1
+
+#define APCI1710_PWM_DISABLE        0
+#define APCI1710_PWM_ENABLE                    1
+#define APCI1710_PWM_NEWTIMING      2
+
+INT i_APCI1710_InsnConfigPWM(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InitPWM(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM,
+       BYTE b_ClockSelection,
+       BYTE b_TimingUnit,
+       ULONG ul_LowTiming,
+       ULONG ul_HighTiming,
+       PULONG pul_RealLowTiming, PULONG pul_RealHighTiming);
+
+INT i_APCI1710_GetPWMInitialisation(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM,
+       PBYTE pb_TimingUnit,
+       PULONG pul_LowTiming,
+       PULONG pul_HighTiming,
+       PBYTE pb_StartLevel,
+       PBYTE pb_StopMode,
+       PBYTE pb_StopLevel,
+       PBYTE pb_ExternGate, PBYTE pb_InterruptEnable, PBYTE pb_Enable);
+
+INT i_APCI1710_InsnWritePWM(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_EnablePWM(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM,
+       BYTE b_StartLevel,
+       BYTE b_StopMode,
+       BYTE b_StopLevel, BYTE b_ExternGate, BYTE b_InterruptEnable);
+
+INT i_APCI1710_SetNewPWMTiming(comedi_device * dev,
+       BYTE b_ModulNbr,
+       BYTE b_PWM, BYTE b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming);
+
+INT i_APCI1710_DisablePWM(comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM);
+
+INT i_APCI1710_InsnReadGetPWMStatus(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
new file mode 100644 (file)
index 0000000..4972336
--- /dev/null
@@ -0,0 +1,848 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : SSI.C           | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 SSI counter module                          |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 13/05/98 | S. Weber  | SSI digital input / output implementation      |
+  |----------|-----------|------------------------------------------------|
+  | 22/03/00 | C.Guinot  | 0100/0226 -> 0200/0227                         |
+  |          |           | Ã„nderung in InitSSI Funktion                   |
+  |          |           | b_SSIProfile >= 2 anstatt b_SSIProfile > 2     |
+  |          |           |                                                |
+  +-----------------------------------------------------------------------+
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Ssi.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitSSI                               |
+|                               (BYTE_    b_BoardHandle,                     |
+|                                BYTE_    b_ModulNbr,                        |
+|                                BYTE_    b_SSIProfile,                      |
+|                                BYTE_    b_PositionTurnLength,              |
+|                                BYTE_    b_TurnCptLength,                   |
+|                                BYTE_    b_PCIInputClock,                   |
+|                                ULONG_  ul_SSIOutputClock,                  |
+|                                BYTE_    b_SSICountingMode)                 |
++----------------------------------------------------------------------------+
+| Task              : Configure the SSI operating mode from selected module  |
+|                     (b_ModulNbr). You must calling this function be for you|
+|                     call any other function witch access of SSI.           |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr            : Module number to         |
+|                                                   configure (0 to 3)       |
+|                     BYTE_  b_SSIProfile         : Selection from SSI       |
+|                                                   profile length (2 to 32).|
+|                     BYTE_  b_PositionTurnLength : Selection from SSI       |
+|                                                   position data length     |
+|                                                   (1 to 31).               |
+|                     BYTE_  b_TurnCptLength      : Selection from SSI turn  |
+|                                                   counter data length      |
+|                                                   (1 to 31).               |
+|                     BYTE   b_PCIInputClock      : Selection from PCI bus   |
+|                                                   clock                    |
+|                                                 - APCI1710_30MHZ :         |
+|                                                   The PC have a PCI bus    |
+|                                                   clock from 30 MHz        |
+|                                                 - APCI1710_33MHZ :         |
+|                                                   The PC have a PCI bus    |
+|                                                   clock from 33 MHz        |
+|                     ULONG_ ul_SSIOutputClock    : Selection from SSI output|
+|                                                   clock.                   |
+|                                                   From  229 to 5 000 000 Hz|
+|                                                   for 30 MHz selection.    |
+|                                                   From  252 to 5 000 000 Hz|
+|                                                   for 33 MHz selection.    |
+|                     BYTE   b_SSICountingMode    : SSI counting mode        |
+|                                                   selection                |
+|                                                 - APCI1710_BINARY_MODE :   |
+|                                                    Binary counting mode.   |
+|                                                 - APCI1710_GRAY_MODE :     |
+|                                                    Gray counting mode.
+
+       b_ModulNbr                      = CR_AREF(insn->chanspec);
+       b_SSIProfile            = (BYTE) data[0];
+       b_PositionTurnLength= (BYTE) data[1];
+       b_TurnCptLength         = (BYTE) data[2];
+       b_PCIInputClock         = (BYTE) data[3];
+       ul_SSIOutputClock       = (ULONG) data[4];
+       b_SSICountingMode       = (BYTE)  data[5];     |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a SSI module                      |
+|                    -4: The selected SSI profile length is wrong            |
+|                    -5: The selected SSI position data length is wrong      |
+|                    -6: The selected SSI turn counter data length is wrong  |
+|                    -7: The selected PCI input clock is wrong               |
+|                    -8: The selected SSI output clock is wrong              |
+|                    -9: The selected SSI counting mode parameter is wrong   |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitSSI(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       UINT ui_TimerValue;
+       BYTE b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
+               b_PCIInputClock, b_SSICountingMode;
+       ULONG ul_SSIOutputClock;
+
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_SSIProfile = (BYTE) data[0];
+       b_PositionTurnLength = (BYTE) data[1];
+       b_TurnCptLength = (BYTE) data[2];
+       b_PCIInputClock = (BYTE) data[3];
+       ul_SSIOutputClock = (ULONG) data[4];
+       b_SSICountingMode = (BYTE) data[5];
+
+       i_ReturnValue = insn->n;
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if SSI counter */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
+             /*******************************/
+                       /* Test the SSI profile length */
+             /*******************************/
+
+                       // CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2
+                       if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
+                /*************************************/
+                               /* Test the SSI position data length */
+                /*************************************/
+
+                               if (b_PositionTurnLength > 0
+                                       && b_PositionTurnLength < 32) {
+                   /*****************************************/
+                                       /* Test the SSI turn counter data length */
+                   /*****************************************/
+
+                                       if (b_TurnCptLength > 0
+                                               && b_TurnCptLength < 32) {
+                      /***************************/
+                                               /* Test the profile length */
+                      /***************************/
+
+                                               if ((b_TurnCptLength +
+                                                               b_PositionTurnLength)
+                                                       <= b_SSIProfile) {
+                         /****************************/
+                                                       /* Test the PCI input clock */
+                         /****************************/
+
+                                                       if (b_PCIInputClock ==
+                                                               APCI1710_30MHZ
+                                                               ||
+                                                               b_PCIInputClock
+                                                               ==
+                                                               APCI1710_33MHZ)
+                                                       {
+                            /*************************/
+                                                               /* Test the output clock */
+                            /*************************/
+
+                                                               if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) {
+                                                                       if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) {
+                                  /**********************/
+                                                                               /* Save configuration */
+                                  /**********************/
+                                                                               devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_SSICounterInfo.
+                                                                                       b_SSIProfile
+                                                                                       =
+                                                                                       b_SSIProfile;
+
+                                                                               devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_SSICounterInfo.
+                                                                                       b_PositionTurnLength
+                                                                                       =
+                                                                                       b_PositionTurnLength;
+
+                                                                               devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_SSICounterInfo.
+                                                                                       b_TurnCptLength
+                                                                                       =
+                                                                                       b_TurnCptLength;
+
+                                  /*********************************/
+                                                                               /* Initialise the profile length */
+                                  /*********************************/
+
+                                                                               if (b_SSICountingMode == APCI1710_BINARY_MODE) {
+
+                                                                                       outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
+                                                                               } else {
+
+                                                                                       outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
+                                                                               }
+
+                                  /******************************/
+                                                                               /* Calculate the output clock */
+                                  /******************************/
+
+                                                                               ui_TimerValue
+                                                                                       =
+                                                                                       (UINT)
+                                                                                       (
+                                                                                       ((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
+
+                                  /************************/
+                                                                               /* Initialise the timer */
+                                  /************************/
+
+                                                                               outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
+
+                                  /********************************/
+                                                                               /* Initialise the counting mode */
+                                  /********************************/
+
+                                                                               outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
+
+                                                                               devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_SSICounterInfo.
+                                                                                       b_SSIInit
+                                                                                       =
+                                                                                       1;
+                                                                       } else {
+                                  /*****************************************************/
+                                                                               /* The selected SSI counting mode parameter is wrong */
+                                  /*****************************************************/
+
+                                                                               DPRINTK("The selected SSI counting mode parameter is wrong\n");
+                                                                               i_ReturnValue
+                                                                                       =
+                                                                                       -9;
+                                                                       }
+                                                               } else {
+                               /******************************************/
+                                                                       /* The selected SSI output clock is wrong */
+                               /******************************************/
+
+                                                                       DPRINTK("The selected SSI output clock is wrong\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -8;
+                                                               }
+                                                       } else {
+                            /*****************************************/
+                                                               /* The selected PCI input clock is wrong */
+                            /*****************************************/
+
+                                                               DPRINTK("The selected PCI input clock is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }
+                                               } else {
+                         /********************************************/
+                                                       /* The selected SSI profile length is wrong */
+                         /********************************************/
+
+                                                       DPRINTK("The selected SSI profile length is wrong\n");
+                                                       i_ReturnValue = -4;
+                                               }
+                                       } else {
+                      /******************************************************/
+                                               /* The selected SSI turn counter data length is wrong */
+                      /******************************************************/
+
+                                               DPRINTK("The selected SSI turn counter data length is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }
+                               } else {
+                   /**************************************************/
+                                       /* The selected SSI position data length is wrong */
+                   /**************************************************/
+
+                                       DPRINTK("The selected SSI position data length is wrong\n");
+                                       i_ReturnValue = -5;
+                               }
+                       } else {
+                /********************************************/
+                               /* The selected SSI profile length is wrong */
+                /********************************************/
+
+                               DPRINTK("The selected SSI profile length is wrong\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /**********************************/
+                       /* The module is not a SSI module */
+             /**********************************/
+
+                       DPRINTK("The module is not a SSI module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_  i_APCI1710_Read1SSIValue                        |
+|                               (BYTE_     b_BoardHandle,                    |
+|                                BYTE_     b_ModulNbr,                       |
+|                                BYTE_     b_SelectedSSI,                    |
+|                                PULONG_ pul_Position,                       |
+|                                PULONG_ pul_TurnCpt)
+ INT i_APCI1710_ReadSSIValue(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)                       |
++----------------------------------------------------------------------------+
+| Task              :
+
+
+                                               Read the selected SSI counter (b_SelectedSSI) from     |
+|                     selected module (b_ModulNbr).
+                                               or Read all SSI counter (b_SelectedSSI) from              |
+|                     selected module (b_ModulNbr).                            |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr            : Module number to         |
+|                                                   configure (0 to 3)       |
+|                     BYTE_ b_SelectedSSI         : Selection from SSI       |
+|                                                   counter (0 to 2)
+
+    b_ModulNbr         =   (BYTE) CR_AREF(insn->chanspec);
+       b_SelectedSSI   =       (BYTE) CR_CHAN(insn->chanspec); (in case of single ssi)
+       b_ReadType              =       (BYTE) CR_RANGE(insn->chanspec);
+|
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pul_Position       : SSI position in the turn |
+|                     PULONG_  pul_TurnCpt        : Number of turns
+
+pul_Position   =       (PULONG) &data[0];
+       pul_TurnCpt             =       (PULONG) &data[1];         |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a SSI module                      |
+|                    -4: SSI not initialised see function                    |
+|                        "i_APCI1710_InitSSI"                                |
+|                    -5: The selected SSI is wrong                           |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadSSIValue(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       BYTE b_Cpt;
+       BYTE b_Length;
+       BYTE b_Schift;
+       BYTE b_SSICpt;
+       DWORD dw_And;
+       DWORD dw_And1;
+       DWORD dw_And2;
+       DWORD dw_StatusReg;
+       DWORD dw_CounterValue;
+       BYTE b_ModulNbr;
+       BYTE b_SelectedSSI;
+       BYTE b_ReadType;
+       PULONG pul_Position;
+       PULONG pul_TurnCpt;
+       PULONG pul_Position1;
+       PULONG pul_TurnCpt1;
+
+       i_ReturnValue = insn->n;
+       pul_Position1 = (PULONG) & data[0];
+// For Read1
+       pul_TurnCpt1 = (PULONG) & data[1];
+// For Read all
+       pul_Position = (PULONG) & data[0];      //0-2
+       pul_TurnCpt = (PULONG) & data[3];       //3-5
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec);
+       b_ReadType = (BYTE) CR_RANGE(insn->chanspec);
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if SSI counter */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
+             /***************************/
+                       /* Test if SSI initialised */
+             /***************************/
+
+                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_SSICounterInfo.b_SSIInit == 1) {
+
+                               switch (b_ReadType) {
+
+                               case APCI1710_SSI_READ1VALUE:
+                /****************************************/
+                                       /* Test the selected SSI counter number */
+                /****************************************/
+
+                                       if (b_SelectedSSI < 3) {
+                   /************************/
+                                               /* Start the conversion */
+                   /************************/
+
+                                               outl(0, devpriv->s_BoardInfos.
+                                                       ui_Address + 8 +
+                                                       (64 * b_ModulNbr));
+
+                                               do {
+                      /*******************/
+                                                       /* Read the status */
+                      /*******************/
+
+                                                       dw_StatusReg =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               (64 * b_ModulNbr));
+                                               }
+                                               while ((dw_StatusReg & 0x1) !=
+                                                       0);
+
+                   /******************************/
+                                               /* Read the SSI counter value */
+                   /******************************/
+
+                                               dw_CounterValue =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address + 4 +
+                                                       (b_SelectedSSI * 4) +
+                                                       (64 * b_ModulNbr));
+
+                                               b_Length =
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_SSIProfile / 2;
+
+                                               if ((b_Length * 2) !=
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_SSIProfile) {
+                                                       b_Length++;
+                                               }
+
+                                               b_Schift =
+                                                       b_Length -
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_PositionTurnLength;
+
+                                               *pul_Position1 =
+                                                       dw_CounterValue >>
+                                                       b_Schift;
+
+                                               dw_And = 1;
+
+                                               for (b_Cpt = 0;
+                                                       b_Cpt <
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_PositionTurnLength;
+                                                       b_Cpt++) {
+                                                       dw_And = dw_And * 2;
+                                               }
+
+                                               *pul_Position1 =
+                                                       *pul_Position1 &
+                                                       ((dw_And) - 1);
+
+                                               *pul_TurnCpt1 =
+                                                       dw_CounterValue >>
+                                                       b_Length;
+
+                                               dw_And = 1;
+
+                                               for (b_Cpt = 0;
+                                                       b_Cpt <
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_TurnCptLength;
+                                                       b_Cpt++) {
+                                                       dw_And = dw_And * 2;
+                                               }
+
+                                               *pul_TurnCpt1 =
+                                                       *pul_TurnCpt1 &
+                                                       ((dw_And) - 1);
+                                       } else {
+                   /*****************************/
+                                               /* The selected SSI is wrong */
+                   /*****************************/
+
+                                               DPRINTK("The selected SSI is wrong\n");
+                                               i_ReturnValue = -5;
+                                       }
+                                       break;
+
+                               case APCI1710_SSI_READALLVALUE:
+                                       dw_And1 = 1;
+
+                                       for (b_Cpt = 0;
+                                               b_Cpt <
+                                               devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SSICounterInfo.
+                                               b_PositionTurnLength; b_Cpt++) {
+                                               dw_And1 = dw_And1 * 2;
+                                       }
+
+                                       dw_And2 = 1;
+
+                                       for (b_Cpt = 0;
+                                               b_Cpt <
+                                               devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_SSICounterInfo.
+                                               b_TurnCptLength; b_Cpt++) {
+                                               dw_And2 = dw_And2 * 2;
+                                       }
+
+                /************************/
+                                       /* Start the conversion */
+                /************************/
+
+                                       outl(0, devpriv->s_BoardInfos.
+                                               ui_Address + 8 +
+                                               (64 * b_ModulNbr));
+
+                                       do {
+                   /*******************/
+                                               /* Read the status */
+                   /*******************/
+
+                                               dw_StatusReg =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address +
+                                                       (64 * b_ModulNbr));
+                                       }
+                                       while ((dw_StatusReg & 0x1) != 0);
+
+                                       for (b_SSICpt = 0; b_SSICpt < 3;
+                                               b_SSICpt++) {
+                   /******************************/
+                                               /* Read the SSI counter value */
+                   /******************************/
+
+                                               dw_CounterValue =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address + 4 +
+                                                       (b_SSICpt * 4) +
+                                                       (64 * b_ModulNbr));
+
+                                               b_Length =
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_SSIProfile / 2;
+
+                                               if ((b_Length * 2) !=
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_SSIProfile) {
+                                                       b_Length++;
+                                               }
+
+                                               b_Schift =
+                                                       b_Length -
+                                                       devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_SSICounterInfo.
+                                                       b_PositionTurnLength;
+
+                                               pul_Position[b_SSICpt] =
+                                                       dw_CounterValue >>
+                                                       b_Schift;
+                                               pul_Position[b_SSICpt] =
+                                                       pul_Position[b_SSICpt] &
+                                                       ((dw_And1) - 1);
+
+                                               pul_TurnCpt[b_SSICpt] =
+                                                       dw_CounterValue >>
+                                                       b_Length;
+                                               pul_TurnCpt[b_SSICpt] =
+                                                       pul_TurnCpt[b_SSICpt] &
+                                                       ((dw_And2) - 1);
+                                       }
+                                       break;
+
+                               default:
+                                       printk("Read Type Inputs Wrong\n");
+
+                               }       // switch  ending
+
+                       } else {
+                /***********************/
+                               /* SSI not initialised */
+                /***********************/
+
+                               DPRINTK("SSI not initialised\n");
+                               i_ReturnValue = -4;
+                       }
+               } else {
+             /**********************************/
+                       /* The module is not a SSI module */
+             /**********************************/
+
+                       DPRINTK("The module is not a SSI module\n");
+                       i_ReturnValue = -3;
+
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_   i_APCI1710_ReadSSI1DigitalInput                |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_InputChannel,           |
+|                                        PBYTE_   pb_ChannelStatus)          |
++----------------------------------------------------------------------------+
+| Task              :
+                                       (0) Set the digital output from selected SSI moule         |
+|                     (b_ModuleNbr) ON
+                    (1) Set the digital output from selected SSI moule         |
+|                     (b_ModuleNbr) OFF
+                                       (2)Read the status from selected SSI digital input        |
+|                     (b_InputChannel)
+                    (3)Read the status from all SSI digital inputs from       |
+|                     selected SSI module (b_ModulNbr)                   |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr    CR_AREF        : Module number to         |
+|                                                   configure (0 to 3)       |
+|                     BYTE_ b_InputChannel CR_CHAN       : Selection from digital   |
+|                        data[0] which IOTYPE                           input ( 0 to 2)          |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_  pb_ChannelStatus    : Digital input channel    |
+|                                 data[0]                  status                   |
+|                                                   0 : Channle is not active|
+|                                                   1 : Channle is active    |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a SSI module                      |
+|                    -4: The selected SSI digital input is wrong             |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg;
+       BYTE b_ModulNbr;
+       BYTE b_InputChannel;
+       PBYTE pb_ChannelStatus;
+       PBYTE pb_InputStatus;
+       BYTE b_IOType;
+       i_ReturnValue = insn->n;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_IOType = (BYTE) data[0];
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if SSI counter */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
+                       switch (b_IOType) {
+                       case APCI1710_SSI_SET_CHANNELON:
+                                       /*****************************/
+                               /* Set the digital output ON */
+                                       /*****************************/
+
+                               outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
+                                       (64 * b_ModulNbr));
+                               break;
+
+                       case APCI1710_SSI_SET_CHANNELOFF:
+                                       /******************************/
+                               /* Set the digital output OFF */
+                                       /******************************/
+
+                               outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
+                                       (64 * b_ModulNbr));
+                               break;
+
+                       case APCI1710_SSI_READ_1CHANNEL:
+                                  /******************************************/
+                               /* Test the digital imnput channel number */
+                                  /******************************************/
+
+                               b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
+                               pb_ChannelStatus = (PBYTE) & data[0];
+
+                               if (b_InputChannel <= 2) {
+                                       /**************************/
+                                       /* Read all digital input */
+                                       /**************************/
+
+                                       dw_StatusReg =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + (64 * b_ModulNbr));
+                                       *pb_ChannelStatus =
+                                               (BYTE) (((~dw_StatusReg) >> (4 +
+                                                               b_InputChannel))
+                                               & 1);
+                               } else {
+                                       /********************************/
+                                       /* Selected digital input error */
+                                       /********************************/
+
+                                       DPRINTK("Selected digital input error\n");
+                                       i_ReturnValue = -4;
+                               }
+                               break;
+
+                       case APCI1710_SSI_READ_ALLCHANNEL:
+                                       /**************************/
+                               /* Read all digital input */
+                                       /**************************/
+                               pb_InputStatus = (PBYTE) & data[0];
+
+                               dw_StatusReg =
+                                       inl(devpriv->s_BoardInfos.ui_Address +
+                                       (64 * b_ModulNbr));
+                               *pb_InputStatus =
+                                       (BYTE) (((~dw_StatusReg) >> 4) & 7);
+                               break;
+
+                       default:
+                               printk("IO type wrong\n");
+
+                       }       //switch end
+               } else {
+             /**********************************/
+                       /* The module is not a SSI module */
+             /**********************************/
+
+                       DPRINTK("The module is not a SSI module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
new file mode 100644 (file)
index 0000000..a2aea95
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_30MHZ           30
+#define APCI1710_33MHZ           33
+#define APCI1710_40MHZ           40
+
+#define APCI1710_BINARY_MODE     0x1
+#define APCI1710_GRAY_MODE       0x0
+
+#define APCI1710_SSI_READ1VALUE                                1
+#define APCI1710_SSI_READALLVALUE                      2
+
+#define APCI1710_SSI_SET_CHANNELON       0
+#define APCI1710_SSI_SET_CHANNELOFF            1
+#define APCI1710_SSI_READ_1CHANNEL             2
+#define APCI1710_SSI_READ_ALLCHANNEL           3
+
+/*
++----------------------------------------------------------------------------+
+|                       SSI INISIALISATION FUNCTION                          |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_InsnConfigInitSSI(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnReadSSIValue(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
new file mode 100644 (file)
index 0000000..aa45d0a
--- /dev/null
@@ -0,0 +1,2049 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : TOR.C           | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 tor counter module                          |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 27/01/99 | S. Weber  | 40 MHz implementation                          |
+  +-----------------------------------------------------------------------+
+  | 28/04/00 | S. Weber  | Simple,double and quadruple mode implementation|
+  |          |           | Extern clock implementation                    |
+  +-----------------------------------------------------------------------+
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Tor.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_     i_APCI1710_InitTorCounter                    |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_TorCounter,             |
+|                                        BYTE_     b_PCIInputClock,          |
+|                                        BYTE_     b_TimingUnit,             |
+|                                        ULONG_   ul_TimingInterval,         |
+|                                        PULONG_ pul_RealTimingInterval)     |
++----------------------------------------------------------------------------+
+| Task              : Configure the selected tor counter (b_TorCounter)      |
+|                     from selected module (b_ModulNbr).                     |
+|                     The ul_TimingInterval and ul_TimingUnit determine the  |
+|                     timing base for the measurement.                       |
+|                     The pul_RealTimingInterval return the real timing      |
+|                     value. You must calling this function be for you call  |
+|                     any other function witch access of the tor counter.    |
+|                                                                            |
++----------------------------------------------------------------------------+
+| Input Parameters  :    |
+|
+               CR_AREF BYTE_   b_ModulNbr       : Module number to configure  |
+|                                                (0 to 3)                    |
+|           data[0] BYTE_   b_TorCounter     : Tor counter selection       |
+|                                                (0 or 1).                   |
+|           data[1] BYTE_   b_PCIInputClock  : Selection from PCI bus clock|
+|                                                - APCI1710_30MHZ :          |
+|                                                  The PC have a PCI bus     |
+|                                                  clock from 30 MHz         |
+|                                                - APCI1710_33MHZ :          |
+|                                                  The PC have a PCI bus     |
+|                                                  clock from 33 MHz         |
+|                                                - APCI1710_40MHZ            |
+|                                                  The APCI-1710 have a      |
+|                                                  integrated 40Mhz          |
+|                                                  quartz.                   |
+|                                                - APCI1710_GATE_INPUT       |
+|                                                  Used the gate input for   |
+|                                                 the base clock. If you    |
+|                                                 have selected this option,|
+|                                                 than it is not possibl to |
+|                                                 used the gate input for   |
+|                                                 enabled the acquisition   |
+|           data[2] BYTE_   b_TimingUnit    : Base timing unit (0 to 4)    |
+|                                                 0 : ns                     |
+|                                                 1 : Âµs                     |
+|                                                 2 : ms                     |
+|                                                 3 : s                      |
+|                                                 4 : mn                     |
+|           data[3]          ULONG_ ul_TimingInterval : Base timing value.          |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pul_RealTimingInterval : Real  base timing    |
+|                     data[0]                                  value.               |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a tor counter module             |
+|                     -4: Tor counter selection is wrong                     |
+|                     -5: The selected PCI input clock is wrong              |
+|                     -6: Timing unit selection is wrong                     |
+|                     -7: Base timing selection is wrong                     |
+|                     -8: You can not used the 40MHz clock selection wich    |
+|                         this board                                         |
+|                     -9: You can not used the 40MHz clock selection wich    |
+|                         this TOR version                                   |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTorCounter(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       ULONG ul_TimerValue = 0;
+       DWORD dw_Command;
+       double d_RealTimingInterval = 0;
+       BYTE b_ModulNbr;
+       BYTE b_TorCounter;
+       BYTE b_PCIInputClock;
+       BYTE b_TimingUnit;
+       ULONG ul_TimingInterval;
+       ULONG ul_RealTimingInterval = 0;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+
+       b_TorCounter = (BYTE) data[0];
+       b_PCIInputClock = (BYTE) data[1];
+       b_TimingUnit = (BYTE) data[2];
+       ul_TimingInterval = (ULONG) data[3];
+       printk("INPUT clock %d\n", b_PCIInputClock);
+
+               /**************************/
+       /* Test the module number */
+               /**************************/
+
+       if (b_ModulNbr < 4) {
+               /***********************/
+               /* Test if tor counter */
+               /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+             /**********************************/
+                       /* Test the tor counter selection */
+             /**********************************/
+
+                       if (b_TorCounter <= 1) {
+                /**************************/
+                               /* Test the PCI bus clock */
+                /**************************/
+
+                               if ((b_PCIInputClock == APCI1710_30MHZ) ||
+                                       (b_PCIInputClock == APCI1710_33MHZ) ||
+                                       (b_PCIInputClock == APCI1710_40MHZ) ||
+                                       (b_PCIInputClock ==
+                                               APCI1710_GATE_INPUT)) {
+                   /************************/
+                                       /* Test the timing unit */
+                   /************************/
+
+                                       if ((b_TimingUnit <= 4)
+                                               || (b_PCIInputClock ==
+                                                       APCI1710_GATE_INPUT)) {
+                      /**********************************/
+                                               /* Test the base timing selection */
+                      /**********************************/
+
+                                               if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 133) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230650UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 9UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 121) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691043UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 520UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 8UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 100) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496729UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 7UL)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && (ul_TimingInterval >= 2))) {
+                               /**************************/
+                                                       /* Test the board version */
+                               /**************************/
+
+                                                       if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) {
+                            /************************/
+                                                               /* Test the TOR version */
+                            /************************/
+
+                                                               if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3132)) || (b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) {
+                               /*********************************/
+                                                                       /* Test if not extern clock used */
+                               /*********************************/
+
+                                                                       if (b_PCIInputClock != APCI1710_GATE_INPUT) {
+                                                                               fpu_begin
+                                                                                       ();
+                                  /****************************************/
+                                                                               /* Calculate the timer 0 division fator */
+                                  /****************************************/
+
+                                                                               switch (b_TimingUnit) {
+                                     /******/
+                                                                                       /* ns */
+                                     /******/
+
+                                                                               case 0:
+
+                                             /******************/
+                                                                                       /* Timer 0 factor */
+                                             /******************/
+
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimingInterval
+                                                                                               *
+                                                                                               (0.00025 * b_PCIInputClock));
+
+                                             /*******************/
+                                                                                       /* Round the value */
+                                             /*******************/
+
+                                                                                       if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       ul_TimerValue
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                             /*****************************/
+                                                                                       /* Calculate the real timing */
+                                             /*****************************/
+
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimerValue
+                                                                                               /
+                                                                                               (0.00025 * (double)b_PCIInputClock));
+                                                                                       d_RealTimingInterval
+                                                                                               =
+                                                                                               (double)
+                                                                                               ul_TimerValue
+                                                                                               /
+                                                                                               (0.00025
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_PCIInputClock);
+
+                                                                                       if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                               ul_RealTimingInterval
+                                                                                                       =
+                                                                                                       ul_RealTimingInterval
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                                                                       ul_TimingInterval
+                                                                                               =
+                                                                                               ul_TimingInterval
+                                                                                               -
+                                                                                               1;
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               -
+                                                                                               2;
+
+                                                                                       if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       (ULONG)
+                                                                                                       (
+                                                                                                       (double)
+                                                                                                       (ul_TimerValue)
+                                                                                                       *
+                                                                                                       1.007752288);
+                                                                                       }
+
+                                                                                       break;
+
+                                     /******/
+                                                                                       /* Ã¦s */
+                                     /******/
+
+                                                                               case 1:
+
+                                             /******************/
+                                                                                       /* Timer 0 factor */
+                                             /******************/
+
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimingInterval
+                                                                                               *
+                                                                                               (0.25 * b_PCIInputClock));
+
+                                             /*******************/
+                                                                                       /* Round the value */
+                                             /*******************/
+
+                                                                                       if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       ul_TimerValue
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                             /*****************************/
+                                                                                       /* Calculate the real timing */
+                                             /*****************************/
+
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimerValue
+                                                                                               /
+                                                                                               (0.25 * (double)b_PCIInputClock));
+                                                                                       d_RealTimingInterval
+                                                                                               =
+                                                                                               (double)
+                                                                                               ul_TimerValue
+                                                                                               /
+                                                                                               (
+                                                                                               (double)
+                                                                                               0.25
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_PCIInputClock);
+
+                                                                                       if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                               ul_RealTimingInterval
+                                                                                                       =
+                                                                                                       ul_RealTimingInterval
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                                                                       ul_TimingInterval
+                                                                                               =
+                                                                                               ul_TimingInterval
+                                                                                               -
+                                                                                               1;
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               -
+                                                                                               2;
+
+                                                                                       if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       (ULONG)
+                                                                                                       (
+                                                                                                       (double)
+                                                                                                       (ul_TimerValue)
+                                                                                                       *
+                                                                                                       1.007752288);
+                                                                                       }
+
+                                                                                       break;
+
+                                     /******/
+                                                                                       /* ms */
+                                     /******/
+
+                                                                               case 2:
+
+                                             /******************/
+                                                                                       /* Timer 0 factor */
+                                             /******************/
+
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimingInterval
+                                                                                               *
+                                                                                               (250.0
+                                                                                               *
+                                                                                               b_PCIInputClock);
+
+                                             /*******************/
+                                                                                       /* Round the value */
+                                             /*******************/
+
+                                                                                       if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       ul_TimerValue
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                             /*****************************/
+                                                                                       /* Calculate the real timing */
+                                             /*****************************/
+
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimerValue
+                                                                                               /
+                                                                                               (250.0 * (double)b_PCIInputClock));
+                                                                                       d_RealTimingInterval
+                                                                                               =
+                                                                                               (double)
+                                                                                               ul_TimerValue
+                                                                                               /
+                                                                                               (250.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_PCIInputClock);
+
+                                                                                       if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                               ul_RealTimingInterval
+                                                                                                       =
+                                                                                                       ul_RealTimingInterval
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                                                                       ul_TimingInterval
+                                                                                               =
+                                                                                               ul_TimingInterval
+                                                                                               -
+                                                                                               1;
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               -
+                                                                                               2;
+
+                                                                                       if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       (ULONG)
+                                                                                                       (
+                                                                                                       (double)
+                                                                                                       (ul_TimerValue)
+                                                                                                       *
+                                                                                                       1.007752288);
+                                                                                       }
+
+                                                                                       break;
+
+                                     /*****/
+                                                                                       /* s */
+                                     /*****/
+
+                                                                               case 3:
+
+                                             /******************/
+                                                                                       /* Timer 0 factor */
+                                             /******************/
+
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimingInterval
+                                                                                               *
+                                                                                               (250000.0
+                                                                                                       *
+                                                                                                       b_PCIInputClock));
+
+                                             /*******************/
+                                                                                       /* Round the value */
+                                             /*******************/
+
+                                                                                       if ((double)((double)ul_TimingInterval * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       ul_TimerValue
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                             /*****************************/
+                                                                                       /* Calculate the real timing */
+                                             /*****************************/
+
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimerValue
+                                                                                               /
+                                                                                               (250000.0
+                                                                                                       *
+                                                                                                       (double)
+                                                                                                       b_PCIInputClock));
+                                                                                       d_RealTimingInterval
+                                                                                               =
+                                                                                               (double)
+                                                                                               ul_TimerValue
+                                                                                               /
+                                                                                               (250000.0
+                                                                                               *
+                                                                                               (double)
+                                                                                               b_PCIInputClock);
+
+                                                                                       if ((double)((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                               ul_RealTimingInterval
+                                                                                                       =
+                                                                                                       ul_RealTimingInterval
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                                                                       ul_TimingInterval
+                                                                                               =
+                                                                                               ul_TimingInterval
+                                                                                               -
+                                                                                               1;
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               -
+                                                                                               2;
+
+                                                                                       if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       (ULONG)
+                                                                                                       (
+                                                                                                       (double)
+                                                                                                       (ul_TimerValue)
+                                                                                                       *
+                                                                                                       1.007752288);
+                                                                                       }
+
+                                                                                       break;
+
+                                     /******/
+                                                                                       /* mn */
+                                     /******/
+
+                                                                               case 4:
+
+                                             /******************/
+                                                                                       /* Timer 0 factor */
+                                             /******************/
+
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (
+                                                                                               (ul_TimingInterval
+                                                                                                       *
+                                                                                                       60)
+                                                                                               *
+                                                                                               (250000.0
+                                                                                                       *
+                                                                                                       b_PCIInputClock));
+
+                                             /*******************/
+                                                                                       /* Round the value */
+                                             /*******************/
+
+                                                                                       if ((double)((double)(ul_TimingInterval * 60.0) * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       ul_TimerValue
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                             /*****************************/
+                                                                                       /* Calculate the real timing */
+                                             /*****************************/
+
+                                                                                       ul_RealTimingInterval
+                                                                                               =
+                                                                                               (ULONG)
+                                                                                               (ul_TimerValue
+                                                                                               /
+                                                                                               (250000.0
+                                                                                                       *
+                                                                                                       (double)
+                                                                                                       b_PCIInputClock))
+                                                                                               /
+                                                                                               60;
+                                                                                       d_RealTimingInterval
+                                                                                               =
+                                                                                               (
+                                                                                               (double)
+                                                                                               ul_TimerValue
+                                                                                               /
+                                                                                               (250000.0
+                                                                                                       *
+                                                                                                       (double)
+                                                                                                       b_PCIInputClock))
+                                                                                               /
+                                                                                               60.0;
+
+                                                                                       if ((double)(((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+                                                                                               ul_RealTimingInterval
+                                                                                                       =
+                                                                                                       ul_RealTimingInterval
+                                                                                                       +
+                                                                                                       1;
+                                                                                       }
+
+                                                                                       ul_TimingInterval
+                                                                                               =
+                                                                                               ul_TimingInterval
+                                                                                               -
+                                                                                               1;
+                                                                                       ul_TimerValue
+                                                                                               =
+                                                                                               ul_TimerValue
+                                                                                               -
+                                                                                               2;
+
+                                                                                       if (b_PCIInputClock != APCI1710_40MHZ) {
+                                                                                               ul_TimerValue
+                                                                                                       =
+                                                                                                       (ULONG)
+                                                                                                       (
+                                                                                                       (double)
+                                                                                                       (ul_TimerValue)
+                                                                                                       *
+                                                                                                       1.007752288);
+                                                                                       }
+
+                                                                                       break;
+                                                                               }
+
+                                                                               fpu_end();
+                                                                       }       // if (b_PCIInputClock != APCI1710_GATE_INPUT)
+                                                                       else {
+                                  /*************************************************************/
+                                                                               /* 2 Clock used for the overflow and the reload from counter */
+                                  /*************************************************************/
+
+                                                                               ul_TimerValue
+                                                                                       =
+                                                                                       ul_TimingInterval
+                                                                                       -
+                                                                                       2;
+                                                                       }       // if (b_PCIInputClock != APCI1710_GATE_INPUT)
+
+                               /****************************/
+                                                                       /* Save the PCI input clock */
+                               /****************************/
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TorCounterModuleInfo.
+                                                                               b_PCIInputClock
+                                                                               =
+                                                                               b_PCIInputClock;
+
+                               /************************/
+                                                                       /* Save the timing unit */
+                               /************************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TorCounterModuleInfo.
+                                                                               s_TorCounterInfo
+                                                                               [b_TorCounter].
+                                                                               b_TimingUnit
+                                                                               =
+                                                                               b_TimingUnit;
+
+                               /************************/
+                                                                       /* Save the base timing */
+                               /************************/
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TorCounterModuleInfo.
+                                                                               s_TorCounterInfo
+                                                                               [b_TorCounter].
+                                                                               d_TimingInterval
+                                                                               =
+                                                                               d_RealTimingInterval;
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TorCounterModuleInfo.
+                                                                               s_TorCounterInfo
+                                                                               [b_TorCounter].
+                                                                               ul_RealTimingInterval
+                                                                               =
+                                                                               ul_RealTimingInterval;
+
+                               /*******************/
+                                                                       /* Get the command */
+                               /*******************/
+
+                                                                       dw_Command
+                                                                               =
+                                                                               inl
+                                                                               (devpriv->
+                                                                               s_BoardInfos.
+                                                                               ui_Address
+                                                                               +
+                                                                               4
+                                                                               +
+                                                                               (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                                                       dw_Command
+                                                                               =
+                                                                               (dw_Command
+                                                                               >>
+                                                                               4)
+                                                                               &
+                                                                               0xF;
+
+                               /******************/
+                                                                       /* Test if 40 MHz */
+                               /******************/
+
+                                                                       if (b_PCIInputClock == APCI1710_40MHZ) {
+                                  /****************************/
+                                                                               /* Set the 40 MHz selection */
+                                  /****************************/
+
+                                                                               dw_Command
+                                                                                       =
+                                                                                       dw_Command
+                                                                                       |
+                                                                                       0x10;
+                                                                       }
+
+                               /*****************************/
+                                                                       /* Test if extern clock used */
+                               /*****************************/
+
+                                                                       if (b_PCIInputClock == APCI1710_GATE_INPUT) {
+                                  /****************************/
+                                                                               /* Set the 40 MHz selection */
+                                  /****************************/
+
+                                                                               dw_Command
+                                                                                       =
+                                                                                       dw_Command
+                                                                                       |
+                                                                                       0x20;
+                                                                       }
+
+                               /*************************/
+                                                                       /* Write the new command */
+                               /*************************/
+
+                                                                       outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                               /*******************/
+                                                                       /* Disable the tor */
+                               /*******************/
+
+                                                                       outl(0, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+                               /*************************/
+                                                                       /* Set the timer 1 value */
+                               /*************************/
+
+                                                                       outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                               /*********************/
+                                                                       /* Tor counter init. */
+                               /*********************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TorCounterModuleInfo.
+                                                                               s_TorCounterInfo
+                                                                               [b_TorCounter].
+                                                                               b_TorCounterInit
+                                                                               =
+                                                                               1;
+                                                               } else {
+                               /***********************************************/
+                                                                       /* TOR version error for 40MHz clock selection */
+                               /***********************************************/
+
+                                                                       DPRINTK("TOR version error for 40MHz clock selection\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -9;
+                                                               }
+                                                       } else {
+                            /**************************************************************/
+                                                               /* You can not used the 40MHz clock selection wich this board */
+                            /**************************************************************/
+
+                                                               DPRINTK("You can not used the 40MHz clock selection wich this board\n");
+                                                               i_ReturnValue =
+                                                                       -8;
+                                                       }
+                                               } else {
+                         /**********************************/
+                                                       /* Base timing selection is wrong */
+                         /**********************************/
+
+                                                       DPRINTK("Base timing selection is wrong\n");
+                                                       i_ReturnValue = -7;
+                                               }
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                                       else {
+                      /**********************************/
+                                               /* Timing unit selection is wrong */
+                      /**********************************/
+
+                                               DPRINTK("Timing unit selection is wrong\n");
+                                               i_ReturnValue = -6;
+                                       }       // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+                               }       // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+                               else {
+                   /*****************************************/
+                                       /* The selected PCI input clock is wrong */
+                   /*****************************************/
+
+                                       DPRINTK("The selected PCI input clock is wrong\n");
+                                       i_ReturnValue = -5;
+                               }       // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+                       }       // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)
+                       else {
+                /**********************************/
+                               /* Tor Counter selection is wrong */
+                /**********************************/
+
+                               DPRINTK("Tor Counter selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)
+               } else {
+             /******************************************/
+                       /* The module is not a tor counter module */
+             /******************************************/
+
+                       DPRINTK("The module is not a tor counter module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+       data[0] = (UINT) ul_RealTimingInterval;
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_EnableTorCounter                      |
+|                                               (BYTE_ b_BoardHandle,        |
+|                                                BYTE_ b_ModulNbr,           |
+|                                               BYTE_ b_TorCounter,         |
+|                                               BYTE_ b_InputMode,          |
+|                                               BYTE_ b_ExternGate,         |
+|                                                BYTE_ b_CycleMode,          |
+|                                                BYTE_ b_InterruptEnable)    |
++----------------------------------------------------------------------------+
+| Task              : Enable the tor counter (b_TorCounter) from selected    |
+|                    module (b_ModulNbr). You must calling the              |
+|                     "i_APCI1710_InitTorCounter" function be for you call   |
+|                    this function.                                         |
+|                     If you enable the tor counter interrupt, the           |
+|                     tor counter generate a interrupt after the timing cycle|
+|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
+|                     Interrupt mask description chapter from this manual.   |
+|                     The b_CycleMode parameter determine if you will        |
+|                     measured a single or more cycle.                       |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1). |
+|                    BYTE_ b_InputMode    : Input signal level selection    |
+|                                              0 : Tor count each low level |
+|                                              1 : Tor count each high level|
+|                    BYTE_ b_ExternGate   : Extern gate action selection    |
+|                                              0 : Extern gate signal not   |
+|                                                  used                     |
+|                                              1 : Extern gate signal used. |
+|                                                  If you selected the      |
+|                                                  single mode, each high   |
+|                                                  level signal start the   |
+|                                                  counter.                 |
+|                                                  If you selected the      |
+|                                                  continuous mode, the     |
+|                                                  first high level signal  |
+|                                                  start the tor counter    |
+|                                                                           |
+|                                            APCI1710_TOR_QUADRUPLE _MODE : |
+|                                            In the quadruple mode, the edge|
+|                                            analysis circuit generates a   |
+|                                            counting pulse from each edge  |
+|                                            of 2 signals which are phase   |
+|                                            shifted in relation to each    |
+|                                            other.                         |
+|                                            The gate input is used for the |
+|                                            signal B                       |
+|                                                                           |
+|                                            APCI1710_TOR_DOUBLE_MODE:      |
+|                                            Functions in the same way as   |
+|                                            the quadruple mode, except that|
+|                                            only two of the four edges are |
+|                                            analysed per period.           |
+|                                            The gate input is used for the |
+|                                            signal B                       |
+|                                                                           |
+|                                            APCI1710_TOR_SIMPLE_MODE:      |
+|                                            Functions in the same way as   |
+|                                            the quadruple mode, except that|
+|                                            only one of the four edges is  |
+|                                            analysed per period.           |
+|                                            The gate input is used for the |
+|                                            signal B                       |
+|                                                                           |
+|                     BYTE_ b_CycleMode    : Selected the tor counter        |
+|                                            acquisition mode                |
+|                     BYTE_ b_InterruptEnable : Enable or disable the        |
+|                                               tor counter interrupt.       |
+|                                               APCI1710_ENABLE:             |
+|                                               Enable the tor counter       |
+|                                               interrupt                    |
+|                                               APCI1710_DISABLE:            |
+|                                               Disable the tor counter      |
+|                                               interrupt                    |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a tor counter module             |
+|                     -4: Tor counter selection is wrong                     |
+|                     -5: Tor counter not initialised see function           |
+|                         "i_APCI1710_InitTorCounter"                        |
+|                     -6: Tor input signal selection is wrong                |
+|                     -7: Extern gate signal mode is wrong                   |
+|                     -8: Tor counter acquisition mode cycle is wrong        |
+|                     -9: Interrupt parameter is wrong                       |
+|                     -10:Interrupt function not initialised.                |
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |
++----------------------------------------------------------------------------+
+*/
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_DisableTorCounter                     |
+|                                               (BYTE_  b_BoardHandle,       |
+|                                                BYTE_  b_ModulNbr,          |
+|                                               BYTE_  b_TorCounter)        |
++----------------------------------------------------------------------------+
+| Task              : Disable the tor counter (b_TorCounter) from selected   |
+|                    module (b_ModulNbr). If you disable the tor counter    |
+|                    after a start cycle occur and you restart the tor      |
+|                    counter witch the " i_APCI1710_EnableTorCounter"       |
+|                    function, the status register is cleared               |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1). |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a tor counter module             |
+|                     -4: Tor counter selection is wrong                     |
+|                     -5: Tor counter not initialised see function           |
+|                         "i_APCI1710_InitTorCounter"                        |
+|                     -6: Tor counter not enabled see function               |
+|                         "i_APCI1710_EnableTorCounter"                      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+       DWORD dw_DummyRead;
+       DWORD dw_ConfigReg;
+       BYTE b_ModulNbr, b_Action;
+       BYTE b_TorCounter;
+       BYTE b_InputMode;
+       BYTE b_ExternGate;
+       BYTE b_CycleMode;
+       BYTE b_InterruptEnable;
+
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_Action = (BYTE) data[0];      // enable or disable
+       b_TorCounter = (BYTE) data[1];
+       b_InputMode = (BYTE) data[2];
+       b_ExternGate = (BYTE) data[3];
+       b_CycleMode = (BYTE) data[4];
+       b_InterruptEnable = (BYTE) data[5];
+       i_ReturnValue = insn->n;;
+       devpriv->tsk_Current = current; // Save the current process task structure
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if tor counter */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+             /**********************************/
+                       /* Test the tor counter selection */
+             /**********************************/
+
+                       if (b_TorCounter <= 1) {
+                               switch (b_Action)       // Enable or Disable
+                               {
+                               case APCI1710_ENABLE:
+                /***********************************/
+                                       /* Test if tor counter initialised */
+                /***********************************/
+
+                                       dw_Status =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 8 +
+                                               (16 * b_TorCounter) +
+                                               (64 * b_ModulNbr));
+
+                                       if (dw_Status & 0x10) {
+                   /******************************/
+                                               /* Test the input signal mode */
+                   /******************************/
+
+                                               if (b_InputMode == 0 ||
+                                                       b_InputMode == 1 ||
+                                                       b_InputMode ==
+                                                       APCI1710_TOR_SIMPLE_MODE
+                                                       || b_InputMode ==
+                                                       APCI1710_TOR_DOUBLE_MODE
+                                                       || b_InputMode ==
+                                                       APCI1710_TOR_QUADRUPLE_MODE)
+                                               {
+                      /************************************/
+                                                       /* Test the extern gate signal mode */
+                      /************************************/
+
+                                                       if (b_ExternGate == 0
+                                                               || b_ExternGate
+                                                               == 1
+                                                               || b_InputMode >
+                                                               1) {
+                         /*********************************/
+                                                               /* Test the cycle mode parameter */
+                         /*********************************/
+
+                                                               if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) {
+                            /***************************/
+                                                                       /* Test the interrupt flag */
+                            /***************************/
+
+                                                                       if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) {
+
+                                  /***************************/
+                                                                               /* Save the interrupt mode */
+                                  /***************************/
+
+                                                                               devpriv->
+                                                                                       s_ModuleInfo
+                                                                                       [b_ModulNbr].
+                                                                                       s_TorCounterModuleInfo.
+                                                                                       s_TorCounterInfo
+                                                                                       [b_TorCounter].
+                                                                                       b_InterruptEnable
+                                                                                       =
+                                                                                       b_InterruptEnable;
+
+                                  /*******************/
+                                                                               /* Get the command */
+                                  /*******************/
+
+                                                                               dw_ConfigReg
+                                                                                       =
+                                                                                       inl
+                                                                                       (devpriv->
+                                                                                       s_BoardInfos.
+                                                                                       ui_Address
+                                                                                       +
+                                                                                       4
+                                                                                       +
+                                                                                       (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                                                               dw_ConfigReg
+                                                                                       =
+                                                                                       (dw_ConfigReg
+                                                                                       >>
+                                                                                       4)
+                                                                                       &
+                                                                                       0x30;
+
+                                  /********************************/
+                                                                               /* Test if not direct mode used */
+                                  /********************************/
+
+                                                                               if (b_InputMode > 1) {
+                                     /*******************************/
+                                                                                       /* Extern gate can not be used */
+                                     /*******************************/
+
+                                                                                       b_ExternGate
+                                                                                               =
+                                                                                               0;
+
+                                     /*******************************************/
+                                                                                       /* Enable the extern gate for the Signal B */
+                                     /*******************************************/
+
+                                                                                       dw_ConfigReg
+                                                                                               =
+                                                                                               dw_ConfigReg
+                                                                                               |
+                                                                                               0x40;
+
+                                     /***********************/
+                                                                                       /* Test if simple mode */
+                                     /***********************/
+
+                                                                                       if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) {
+                                        /**************************/
+                                                                                               /* Enable the sinple mode */
+                                        /**************************/
+
+                                                                                               dw_ConfigReg
+                                                                                                       =
+                                                                                                       dw_ConfigReg
+                                                                                                       |
+                                                                                                       0x780;
+
+                                                                                       }       // if (b_InputMode == APCI1710_TOR_SIMPLE_MODE)
+
+                                     /***********************/
+                                                                                       /* Test if double mode */
+                                     /***********************/
+
+                                                                                       if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) {
+                                        /**************************/
+                                                                                               /* Enable the double mode */
+                                        /**************************/
+
+                                                                                               dw_ConfigReg
+                                                                                                       =
+                                                                                                       dw_ConfigReg
+                                                                                                       |
+                                                                                                       0x180;
+
+                                                                                       }       // if (b_InputMode == APCI1710_TOR_DOUBLE_MODE)
+
+                                                                                       b_InputMode
+                                                                                               =
+                                                                                               0;
+                                                                               }       // if (b_InputMode > 1)
+
+                                  /*******************/
+                                                                               /* Set the command */
+                                  /*******************/
+
+                                                                               dw_ConfigReg
+                                                                                       =
+                                                                                       dw_ConfigReg
+                                                                                       |
+                                                                                       b_CycleMode
+                                                                                       |
+                                                                                       (b_InterruptEnable
+                                                                                       *
+                                                                                       2)
+                                                                                       |
+                                                                                       (b_InputMode
+                                                                                       *
+                                                                                       4)
+                                                                                       |
+                                                                                       (b_ExternGate
+                                                                                       *
+                                                                                       8);
+
+                                  /*****************************/
+                                                                               /* Clear the status register */
+                                  /*****************************/
+
+                                                                               dw_DummyRead
+                                                                                       =
+                                                                                       inl
+                                                                                       (devpriv->
+                                                                                       s_BoardInfos.
+                                                                                       ui_Address
+                                                                                       +
+                                                                                       0
+                                                                                       +
+                                                                                       (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                  /***************************************/
+                                                                               /* Clear the interrupt status register */
+                                  /***************************************/
+
+                                                                               dw_DummyRead
+                                                                                       =
+                                                                                       inl
+                                                                                       (devpriv->
+                                                                                       s_BoardInfos.
+                                                                                       ui_Address
+                                                                                       +
+                                                                                       12
+                                                                                       +
+                                                                                       (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                  /********************/
+                                                                               /* Set the commando */
+                                  /********************/
+
+                                                                               outl(dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                  /****************/
+                                                                               /* Set the gate */
+                                  /****************/
+
+                                                                               outl(1, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                                                       }       // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+                                                                       else {
+                               /********************************/
+                                                                               /* Interrupt parameter is wrong */
+                               /********************************/
+
+                                                                               DPRINTK("Interrupt parameter is wrong\n");
+                                                                               i_ReturnValue
+                                                                                       =
+                                                                                       -9;
+                                                                       }       // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+                                                               }       // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+                                                               else {
+                            /***********************************************/
+                                                                       /* Tor counter acquisition mode cycle is wrong */
+                            /***********************************************/
+
+                                                                       DPRINTK("Tor counter acquisition mode cycle is wrong\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -8;
+                                                               }       // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+                                                       }       // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+                                                       else {
+                         /***********************************/
+                                                               /* Extern gate input mode is wrong */
+                         /***********************************/
+
+                                                               DPRINTK("Extern gate input mode is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }       // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+                                               }       // if (b_InputMode >= 0 && b_InputMode <= 1)
+                                               else {
+                      /***************************************/
+                                                       /* Tor input signal selection is wrong */
+                      /***************************************/
+
+                                                       DPRINTK("Tor input signal selection is wrong\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       } else {
+                   /*******************************/
+                                               /* Tor counter not initialised */
+                   /*******************************/
+
+                                               DPRINTK("Tor counter not initialised\n");
+                                               i_ReturnValue = -5;
+                                       }
+                                       break;
+
+                               case APCI1710_DISABLE:
+                        /***********************************/
+                                       /* Test if tor counter initialised */
+                /***********************************/
+
+                                       dw_Status = inl(devpriv->s_BoardInfos.
+                                               ui_Address + 8 +
+                                               (16 * b_TorCounter) +
+                                               (64 * b_ModulNbr));
+
+                /*******************************/
+                                       /* Test if counter initialised */
+                /*******************************/
+
+                                       if (dw_Status & 0x10) {
+                   /***************************/
+                                               /* Test if counter enabled */
+                   /***************************/
+
+                                               if (dw_Status & 0x1) {
+                      /****************************/
+                                                       /* Clear the interrupt mode */
+                      /****************************/
+                                                       devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_TorCounterModuleInfo.
+                                                               s_TorCounterInfo
+                                                               [b_TorCounter].
+                                                               b_InterruptEnable
+                                                               =
+                                                               APCI1710_DISABLE;
+
+                      /******************/
+                                                       /* Clear the gate */
+                      /******************/
+
+                                                       outl(0, devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address + 8 +
+                                                               (16 * b_TorCounter) + (64 * b_ModulNbr));
+                                               }       // if (dw_Status & 0x1)
+                                               else {
+                      /***************************/
+                                                       /* Tor counter not enabled */
+                      /***************************/
+
+                                                       DPRINTK("Tor counter not enabled \n");
+                                                       i_ReturnValue = -6;
+                                               }       // if (dw_Status & 0x1)
+                                       }       // if (dw_Status & 0x10)
+                                       else {
+                   /*******************************/
+                                               /* Tor counter not initialised */
+                   /*******************************/
+
+                                               DPRINTK("Tor counter not initialised\n");
+                                               i_ReturnValue = -5;
+                                       }       // // if (dw_Status & 0x10)
+
+                               }       // switch
+                       }       // if (b_TorCounter <= 1)
+                       else {
+                /**********************************/
+                               /* Tor counter selection is wrong */
+                /**********************************/
+
+                               DPRINTK("Tor counter selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_TorCounter <= 1)
+               } else {
+             /******************************************/
+                       /* The module is not a tor counter module */
+             /******************************************/
+
+                       DPRINTK("The module is not a tor counter module \n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error \n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_GetTorCounterInitialisation           |
+|                                               (BYTE_     b_BoardHandle,    |
+|                                                BYTE_     b_ModulNbr,       |
+|                                               BYTE_     b_TorCounter,     |
+|                                               PBYTE_   pb_TimingUnit,     |
+|                                               PULONG_ pul_TimingInterval, |
+|                                               PBYTE_   pb_InputMode,      |
+|                                               PBYTE_   pb_ExternGate,     |
+|                                                PBYTE_   pb_CycleMode,      |
+|                                               PBYTE_   pb_Enable,         |
+|                                                PBYTE_   pb_InterruptEnable)|
++----------------------------------------------------------------------------+
+| Task              : Enable the tor counter (b_TorCounter) from selected    |
+|                    module (b_ModulNbr). You must calling the              |
+|                     "i_APCI1710_InitTorCounter" function be for you call   |
+|                    this function.                                         |
+|                     If you enable the tor counter interrupt, the           |
+|                     tor counter generate a interrupt after the timing cycle|
+|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |
+|                     Interrupt mask description chapter from this manual.   |
+|                     The b_CycleMode parameter determine if you will        |
+|                     measured a single or more cycle.                       |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1)
+
+       b_ModulNbr                      =       CR_AREF(insn->chanspec);
+       b_TorCounter            =       CR_CHAN(insn->chanspec);
+. |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_  pb_TimingUnit    : Base timing unit (0 to 4)   |
+|                                                 0 : ns                     |
+|                                                 1 : Âµs                     |
+|                                                 2 : ms                     |
+|                                                 3 : s                      |
+|                                                 4 : mn                     |
+|                     PULONG_ pul_TimingInterval : Base timing value.        |
+|                    PBYTE_ pb_InputMode        : Input signal level        |
+|                                                 selection                 |
+|                                              0 : Tor count each low level |
+|                                              1 : Tor count each high level|
+|                    PBYTE_ pb_ExternGate      : Extern gate action         |
+|                                                selection                  |
+|                                                0 : Extern gate signal not |
+|                                                    used                   |
+|                                                1 : Extern gate signal used|
+|                     PBYTE_ pb_CycleMode       : Tor counter acquisition    |
+|                                                mode                       |
+|                    PBYTE_ pb_Enable          : Indicate if the tor counter|
+|                                                is enabled or no           |
+|                                                0 : Tor counter disabled   |
+|                                                1 : Tor counter enabled    |
+|                     PBYTE_ pb_InterruptEnable : Enable or disable the      |
+|                                                 tor counter interrupt.     |
+|                                                 APCI1710_ENABLE:           |
+|                                                 Enable the tor counter     |
+|                                                 interrupt                  |
+|                                                 APCI1710_DISABLE:          |
+|                                                 Disable the tor counter    |
+|                                                 interrupt
+       pb_TimingUnit           =       (PBYTE) &data[0];
+       pul_TimingInterval      =  (PULONG) &data[1];
+       pb_InputMode            =       (PBYTE) &data[2];
+       pb_ExternGate           =       (PBYTE) &data[3];
+       pb_CycleMode            =       (PBYTE) &data[4];
+       pb_Enable                       =       (PBYTE) &data[5];
+       pb_InterruptEnable      =       (PBYTE) &data[6];
+                 |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a tor counter module             |
+|                     -4: Tor counter selection is wrong                     |
+|                     -5: Tor counter not initialised see function           |
+|                         "i_APCI1710_InitTorCounter"                        |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+       BYTE b_ModulNbr;
+       BYTE b_TorCounter;
+       PBYTE pb_TimingUnit;
+       PULONG pul_TimingInterval;
+       PBYTE pb_InputMode;
+       PBYTE pb_ExternGate;
+       PBYTE pb_CycleMode;
+       PBYTE pb_Enable;
+       PBYTE pb_InterruptEnable;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_TorCounter = CR_CHAN(insn->chanspec);
+
+       pb_TimingUnit = (PBYTE) & data[0];
+       pul_TimingInterval = (PULONG) & data[1];
+       pb_InputMode = (PBYTE) & data[2];
+       pb_ExternGate = (PBYTE) & data[3];
+       pb_CycleMode = (PBYTE) & data[4];
+       pb_Enable = (PBYTE) & data[5];
+       pb_InterruptEnable = (PBYTE) & data[6];
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if tor counter */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+             /**********************************/
+                       /* Test the tor counter selection */
+             /**********************************/
+
+                       if (b_TorCounter <= 1) {
+
+                /***********************************/
+                               /* Test if tor counter initialised */
+                /***********************************/
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 8 + (16 * b_TorCounter) +
+                                       (64 * b_ModulNbr));
+
+                               if (dw_Status & 0x10) {
+                                       *pb_Enable = dw_Status & 1;
+
+                   /********************/
+                                       /* Get the commando */
+                   /********************/
+
+                                       dw_Status = inl(devpriv->s_BoardInfos.
+                                               ui_Address + 4 +
+                                               (16 * b_TorCounter) +
+                                               (64 * b_ModulNbr));
+
+                                       *pb_CycleMode =
+                                               (BYTE) ((dw_Status >> 4) & 1);
+                                       *pb_InterruptEnable =
+                                               (BYTE) ((dw_Status >> 5) & 1);
+
+                   /******************************************************/
+                                       /* Test if extern gate used for clock or for signal B */
+                   /******************************************************/
+
+                                       if (dw_Status & 0x600) {
+                      /*****************************************/
+                                               /* Test if extern gate used for signal B */
+                      /*****************************************/
+
+                                               if (dw_Status & 0x400) {
+                         /***********************/
+                                                       /* Test if simple mode */
+                         /***********************/
+
+                                                       if ((dw_Status & 0x7800)
+                                                               == 0x7800) {
+                                                               *pb_InputMode =
+                                                                       APCI1710_TOR_SIMPLE_MODE;
+                                                       }
+
+                         /***********************/
+                                                       /* Test if double mode */
+                         /***********************/
+
+                                                       if ((dw_Status & 0x7800)
+                                                               == 0x1800) {
+                                                               *pb_InputMode =
+                                                                       APCI1710_TOR_DOUBLE_MODE;
+                                                       }
+
+                         /**************************/
+                                                       /* Test if quadruple mode */
+                         /**************************/
+
+                                                       if ((dw_Status & 0x7800)
+                                                               == 0x0000) {
+                                                               *pb_InputMode =
+                                                                       APCI1710_TOR_QUADRUPLE_MODE;
+                                                       }
+                                               }       // if (dw_Status & 0x400)
+                                               else {
+                                                       *pb_InputMode = 1;
+                                               }       // // if (dw_Status & 0x400)
+
+                      /************************/
+                                               /* Extern gate not used */
+                      /************************/
+
+                                               *pb_ExternGate = 0;
+                                       }       // if (dw_Status & 0x600)
+                                       else {
+                                               *pb_InputMode =
+                                                       (BYTE) ((dw_Status >> 6)
+                                                       & 1);
+                                               *pb_ExternGate =
+                                                       (BYTE) ((dw_Status >> 7)
+                                                       & 1);
+                                       }       // if (dw_Status & 0x600)
+
+                                       *pb_TimingUnit =
+                                               devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_TorCounterModuleInfo.
+                                               s_TorCounterInfo[b_TorCounter].
+                                               b_TimingUnit;
+
+                                       *pul_TimingInterval =
+                                               devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_TorCounterModuleInfo.
+                                               s_TorCounterInfo[b_TorCounter].
+                                               ul_RealTimingInterval;
+                               } else {
+                   /*******************************/
+                                       /* Tor counter not initialised */
+                   /*******************************/
+
+                                       DPRINTK("Tor counter not initialised\n");
+                                       i_ReturnValue = -5;
+                               }
+
+                       }       // if (b_TorCounter <= 1)
+                       else {
+                /**********************************/
+                               /* Tor counter selection is wrong */
+                /**********************************/
+
+                               DPRINTK("Tor counter selection is wrong \n");
+                               i_ReturnValue = -4;
+                       }       // if (b_TorCounter <= 1)
+               } else {
+             /******************************************/
+                       /* The module is not a tor counter module */
+             /******************************************/
+
+                       DPRINTK("The module is not a tor counter module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_ReadTorCounterValue                   |
+|                               (BYTE_     b_BoardHandle,                    |
+|                                BYTE_     b_ModulNbr,                       |
+|                               BYTE_     b_TorCounter,                     |
+|                                UINT_    ui_TimeOut,                        |
+|                                PBYTE_   pb_TorCounterStatus,               |
+|                                PULONG_ pul_TorCounterValue)                |
++----------------------------------------------------------------------------+
+| Task         case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter
+(b_TorCounter) status (pb_TorCounterStatus) from selected tor counter        |
+|                    module (b_ModulNbr).
+
+                                case APCI1710_TOR_GETCOUNTERVALUE :
+  Return the tor counter (b_TorCounter) status           |
+|                    (pb_TorCounterStatus) and the timing value             |
+|                    (pul_TorCounterValue) after a conting cycle stop       |
+|                     from selected tor counter module (b_ModulNbr).         |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1).
+       b_ModulNbr    = CR_AREF(insn->chanspec);
+       b_ReadType    = (BYTE) data[0];
+       b_TorCounter  = (BYTE) data[1];
+       ui_TimeOut        = (UINT) data[2]; |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_  pb_TorCounterStatus : Return the tor counter   |
+|                                                    status.                 |
+|                                               0 : Conting cycle not started|
+|                                                   Software gate not set.   |
+|                                               1 : Conting cycle started.   |
+|                                                   Software gate set.       |
+|                                               2 : Conting cycle stopped.   |
+|                                                   The conting cycle is     |
+|                                                   terminate.               |
+|                                               3 : A overflow occur. You    |
+|                                                   must change the base     |
+|                                                   timing witch the         |
+|                                                   function                 |
+|                                                 "i_APCI1710_InitTorCounter"|
+|                                              4 : Timeeout occur           |
+|                     PULONG  pul_TorCounterValue  : Tor counter value.
+       pb_TorCounterStatus=(PBYTE) &data[0];
+       pul_TorCounterValue=(PULONG) &data[1];    |
++----------------------------------------------------------------------------+
+| Return Value      :  0: No error                                           |
+|                     -1: The handle parameter of the board is wrong         |
+|                     -2: Module selection wrong                             |
+|                     -3: The module is not a tor counter module             |
+|                     -4: Tor counter selection is wrong                     |
+|                     -5: Tor counter not initialised see function           |
+|                         "i_APCI1710_InitTorCounter"                        |
+|                     -6: Tor counter not enabled see function               |
+|                         "i_APCI1710_EnableTorCounter"                      |
+|                     -7: Timeout parameter is wrong (0 to 65535)            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_Status;
+       DWORD dw_TimeOut = 0;
+
+       BYTE b_ModulNbr;
+       BYTE b_TorCounter;
+       BYTE b_ReadType;
+       UINT ui_TimeOut;
+       PBYTE pb_TorCounterStatus;
+       PULONG pul_TorCounterValue;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_ReadType = (BYTE) data[0];
+       b_TorCounter = (BYTE) data[1];
+       ui_TimeOut = (UINT) data[2];
+       pb_TorCounterStatus = (PBYTE) & data[0];
+       pul_TorCounterValue = (PULONG) & data[1];
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ReadType == APCI1710_TOR_READINTERRUPT) {
+
+               data[0] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].b_OldModuleMask;
+               data[1] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+               data[2] = devpriv->s_InterruptParameters.
+                       s_FIFOInterruptParameters[devpriv->
+                       s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+                          /**************************/
+               /* Increment the read FIFO */
+                          /***************************/
+
+               devpriv->
+                       s_InterruptParameters.
+                       ui_Read = (devpriv->
+                       s_InterruptParameters.
+                       ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+               return insn->n;
+       }
+
+       if (b_ModulNbr < 4) {
+          /***********************/
+               /* Test if tor counter */
+          /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+             /**********************************/
+                       /* Test the tor counter selection */
+             /**********************************/
+
+                       if (b_TorCounter <= 1) {
+                /***********************************/
+                               /* Test if tor counter initialised */
+                /***********************************/
+
+                               dw_Status = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 8 + (16 * b_TorCounter) +
+                                       (64 * b_ModulNbr));
+
+                /*******************************/
+                               /* Test if counter initialised */
+                /*******************************/
+
+                               if (dw_Status & 0x10) {
+                   /***************************/
+                                       /* Test if counter enabled */
+                   /***************************/
+
+                                       if (dw_Status & 0x1) {
+
+                                               switch (b_ReadType) {
+
+                                               case APCI1710_TOR_GETPROGRESSSTATUS:
+                      /*******************/
+                                                       /* Read the status */
+                      /*******************/
+
+                                                       dw_Status =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address + 4 +
+                                                               (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                                       dw_Status =
+                                                               dw_Status & 0xF;
+
+                      /*****************/
+                                                       /* Test if start */
+                      /*****************/
+
+                                                       if (dw_Status & 1) {
+                                                               if (dw_Status &
+                                                                       2) {
+                                                                       if (dw_Status & 4) {
+                               /************************/
+                                                                               /* Tor counter owerflow */
+                               /************************/
+
+                                                                               *pb_TorCounterStatus
+                                                                                       =
+                                                                                       3;
+                                                                       } else {
+                               /***********************/
+                                                                               /* Tor counter started */
+                               /***********************/
+
+                                                                               *pb_TorCounterStatus
+                                                                                       =
+                                                                                       2;
+                                                                       }
+                                                               } else {
+                            /***********************/
+                                                                       /* Tor counter started */
+                            /***********************/
+
+                                                                       *pb_TorCounterStatus
+                                                                               =
+                                                                               1;
+                                                               }
+                                                       } else {
+                         /***************************/
+                                                               /* Tor counter not started */
+                         /***************************/
+
+                                                               *pb_TorCounterStatus
+                                                                       = 0;
+                                                       }
+                                                       break;
+
+                                               case APCI1710_TOR_GETCOUNTERVALUE:
+
+                      /*****************************/
+                                                       /* Test the timout parameter */
+                      /*****************************/
+
+                                                       if ((ui_TimeOut >= 0)
+                                                               && (ui_TimeOut
+                                                                       <=
+                                                                       65535UL))
+                                                       {
+                                                               for (;;) {
+                            /*******************/
+                                                                       /* Read the status */
+                            /*******************/
+
+                                                                       dw_Status
+                                                                               =
+                                                                               inl
+                                                                               (devpriv->
+                                                                               s_BoardInfos.
+                                                                               ui_Address
+                                                                               +
+                                                                               4
+                                                                               +
+                                                                               (16 * b_TorCounter) + (64 * b_ModulNbr));
+                            /********************/
+                                                                       /* Test if overflow */
+                            /********************/
+
+                                                                       if ((dw_Status & 4) == 4) {
+                               /******************/
+                                                                               /* Overflow occur */
+                               /******************/
+
+                                                                               *pb_TorCounterStatus
+                                                                                       =
+                                                                                       3;
+
+                               /******************/
+                                                                               /* Read the value */
+                               /******************/
+
+                                                                               *pul_TorCounterValue
+                                                                                       =
+                                                                                       inl
+                                                                                       (devpriv->
+                                                                                       s_BoardInfos.
+                                                                                       ui_Address
+                                                                                       +
+                                                                                       0
+                                                                                       +
+                                                                                       (16 * b_TorCounter) + (64 * b_ModulNbr));
+                                                                               break;
+                                                                       }       // if ((dw_Status & 4) == 4)
+                                                                       else {
+                               /*******************************/
+                                                                               /* Test if measurement stopped */
+                               /*******************************/
+
+                                                                               if ((dw_Status & 2) == 2) {
+                                  /***********************/
+                                                                                       /* A stop signal occur */
+                                  /***********************/
+
+                                                                                       *pb_TorCounterStatus
+                                                                                               =
+                                                                                               2;
+
+                                  /******************/
+                                                                                       /* Read the value */
+                                  /******************/
+
+                                                                                       *pul_TorCounterValue
+                                                                                               =
+                                                                                               inl
+                                                                                               (devpriv->
+                                                                                               s_BoardInfos.
+                                                                                               ui_Address
+                                                                                               +
+                                                                                               0
+                                                                                               +
+                                                                                               (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+                                                                                       break;
+                                                                               }       // if ((dw_Status & 2) == 2)
+                                                                               else {
+                                  /*******************************/
+                                                                                       /* Test if measurement started */
+                                  /*******************************/
+
+                                                                                       if ((dw_Status & 1) == 1) {
+                                     /************************/
+                                                                                               /* A start signal occur */
+                                     /************************/
+
+                                                                                               *pb_TorCounterStatus
+                                                                                                       =
+                                                                                                       1;
+                                                                                       }       // if ((dw_Status & 1) == 1)
+                                                                                       else {
+                                     /***************************/
+                                                                                               /* Measurement not started */
+                                     /***************************/
+
+                                                                                               *pb_TorCounterStatus
+                                                                                                       =
+                                                                                                       0;
+                                                                                       }       // if ((dw_Status & 1) == 1)
+                                                                               }       // if ((dw_Status & 2) == 2)
+                                                                       }       // if ((dw_Status & 8) == 8)
+
+                                                                       if (dw_TimeOut == ui_TimeOut) {
+                               /*****************/
+                                                                               /* Timeout occur */
+                               /*****************/
+
+                                                                               break;
+                                                                       } else {
+                               /*************************/
+                                                                               /* Increment the timeout */
+                               /*************************/
+
+                                                                               dw_TimeOut
+                                                                                       =
+                                                                                       dw_TimeOut
+                                                                                       +
+                                                                                       1;
+
+                                                                               mdelay(1000);
+                                                                       }
+                                                               }       // for (;;)
+
+                         /*************************/
+                                                               /* Test if timeout occur */
+                         /*************************/
+
+                                                               if ((*pb_TorCounterStatus != 3) && (dw_TimeOut == ui_TimeOut) && (ui_TimeOut != 0)) {
+                            /*****************/
+                                                                       /* Timeout occur */
+                            /*****************/
+
+                                                                       *pb_TorCounterStatus
+                                                                               =
+                                                                               4;
+                                                               }
+                                                       } else {
+                         /******************************/
+                                                               /* Timeout parameter is wrong */
+                         /******************************/
+
+                                                               DPRINTK("Timeout parameter is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }
+                                                       break;
+
+                                               default:
+                                                       printk("Inputs wrong\n");
+                                               }       // switch end
+                                       }       // if (dw_Status & 0x1)
+                                       else {
+                      /***************************/
+                                               /* Tor counter not enabled */
+                      /***************************/
+
+                                               DPRINTK("Tor counter not enabled\n");
+                                               i_ReturnValue = -6;
+                                       }       // if (dw_Status & 0x1)
+                               } else {
+                   /*******************************/
+                                       /* Tor counter not initialised */
+                   /*******************************/
+
+                                       DPRINTK("Tor counter not initialised\n");
+                                       i_ReturnValue = -5;
+                               }
+                       }       // if (b_TorCounter <= 1)
+                       else {
+                /**********************************/
+                               /* Tor counter selection is wrong */
+                /**********************************/
+
+                               DPRINTK("Tor counter selection is wrong\n");
+                               i_ReturnValue = -4;
+                       }       // if (b_TorCounter <= 1)
+               } else {
+             /******************************************/
+                       /* The module is not a tor counter module */
+             /******************************************/
+
+                       DPRINTK("The module is not a tor counter module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
new file mode 100644 (file)
index 0000000..7670f57
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_30MHZ           30
+#define APCI1710_33MHZ           33
+#define APCI1710_40MHZ           40
+
+#define APCI1710_GATE_INPUT 10
+
+#define APCI1710_TOR_SIMPLE_MODE    2
+#define APCI1710_TOR_DOUBLE_MODE    3
+#define APCI1710_TOR_QUADRUPLE_MODE 4
+
+#define APCI1710_SINGLE     0
+#define APCI1710_CONTINUOUS 1
+
+#define APCI1710_TOR_GETPROGRESSSTATUS 0
+#define APCI1710_TOR_GETCOUNTERVALUE   1
+#define APCI1710_TOR_READINTERRUPT      2
+
+/*
++----------------------------------------------------------------------------+
+|                       TOR_COUNTER INISIALISATION FUNCTION                  |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTorCounter(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnWriteEnableDisableTorCounter(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+/*
++----------------------------------------------------------------------------+
+|                       TOR_COUNTER READ FUNCTION                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
new file mode 100644 (file)
index 0000000..cd78179
--- /dev/null
@@ -0,0 +1,1038 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1710    | Compiler : gcc                        |
+  | Module name : TTL.C           | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-1710 TTL I/O module                              |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 13/05/98 | S. Weber  | TTL digital input / output implementation      |
+  |----------|-----------|------------------------------------------------|
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |
+  |          |           |   available                                    |
+  +-----------------------------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Ttl.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_InitTTLIODirection                    |
+|                               (BYTE_    b_BoardHandle,                     |
+|                               BYTE_    b_ModulNbr,                        |
+|                               BYTE_    b_PortAMode,                       |
+|                               BYTE_    b_PortBMode,                       |
+|                               BYTE_    b_PortCMode,                       |
+|                               BYTE_    b_PortDMode)                       |
++----------------------------------------------------------------------------+
+| Task           APCI1710_TTL_INIT (using defaults)   : Configure the TTL I/O operating mode from selected     |
+|                     module  (b_ModulNbr). You must calling this function be|
+|                     for you call any other function witch access of TTL.   |
+                                APCI1710_TTL_INITDIRECTION(user inputs for direction)
+
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr            : Module number to         |
+|                                                   configure (0 to 3)
+               b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+               b_InitType = (BYTE) data[0];
+               b_PortAMode     = (BYTE) data[1];
+               b_PortBMode = (BYTE) data[2];
+               b_PortCMode = (BYTE) data[3];
+               b_PortDMode     = (BYTE) data[4];|
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a TTL module                      |
+|                   -4: Function not available for this version             |
+|                   -5: Port A mode selection is wrong                      |
+|                   -6: Port B mode selection is wrong                      |
+|                   -7: Port C mode selection is wrong                      |
+|                   -8: Port D mode selection is wrong                      |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTTLIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       BYTE b_ModulNbr;
+       BYTE b_InitType;
+       BYTE b_PortAMode;
+       BYTE b_PortBMode;
+       BYTE b_PortCMode;
+       BYTE b_PortDMode;
+
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       b_InitType = (BYTE) data[0];
+       i_ReturnValue = insn->n;
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /**************************/
+               /* Test if TTL I/O module */
+          /**************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TTL_IO) {
+                       switch (b_InitType) {
+                       case APCI1710_TTL_INIT:
+
+                               devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_TTLIOInfo.b_TTLInit = 1;
+
+             /***************************/
+                               /* Set TTL port A to input */
+             /***************************/
+
+                               devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_TTLIOInfo.b_PortConfiguration[0] = 0;
+
+             /***************************/
+                               /* Set TTL port B to input */
+             /***************************/
+
+                               devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_TTLIOInfo.b_PortConfiguration[1] = 0;
+
+             /***************************/
+                               /* Set TTL port C to input */
+             /***************************/
+
+                               devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_TTLIOInfo.b_PortConfiguration[2] = 0;
+
+             /****************************/
+                               /* Set TTL port D to output */
+             /****************************/
+
+                               devpriv->s_ModuleInfo[b_ModulNbr].
+                                       s_TTLIOInfo.b_PortConfiguration[3] = 1;
+
+             /*************************/
+                               /* Set the configuration */
+             /*************************/
+
+                               outl(0x8,
+                                       devpriv->s_BoardInfos.ui_Address + 20 +
+                                       (64 * b_ModulNbr));
+                               break;
+
+                       case APCI1710_TTL_INITDIRECTION:
+
+                               b_PortAMode = (BYTE) data[1];
+                               b_PortBMode = (BYTE) data[2];
+                               b_PortCMode = (BYTE) data[3];
+                               b_PortDMode = (BYTE) data[4];
+
+             /********************/
+                               /* Test the version */
+             /********************/
+
+                               if ((devpriv->s_BoardInfos.
+                                               dw_MolduleConfiguration
+                                               [b_ModulNbr] & 0xFFFF) >=
+                                       0x3230) {
+                /************************/
+                                       /* Test the port A mode */
+                /************************/
+
+                                       if ((b_PortAMode == 0)
+                                               || (b_PortAMode == 1)) {
+                   /************************/
+                                               /* Test the port B mode */
+                   /************************/
+
+                                               if ((b_PortBMode == 0)
+                                                       || (b_PortBMode == 1)) {
+                      /************************/
+                                                       /* Test the port C mode */
+                      /************************/
+
+                                                       if ((b_PortCMode == 0)
+                                                               || (b_PortCMode
+                                                                       == 1)) {
+                         /************************/
+                                                               /* Test the port D mode */
+                         /************************/
+
+                                                               if ((b_PortDMode == 0) || (b_PortDMode == 1)) {
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TTLIOInfo.
+                                                                               b_TTLInit
+                                                                               =
+                                                                               1;
+
+                            /***********************/
+                                                                       /* Set TTL port A mode */
+                            /***********************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TTLIOInfo.
+                                                                               b_PortConfiguration
+                                                                               [0]
+                                                                               =
+                                                                               b_PortAMode;
+
+                            /***********************/
+                                                                       /* Set TTL port B mode */
+                            /***********************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TTLIOInfo.
+                                                                               b_PortConfiguration
+                                                                               [1]
+                                                                               =
+                                                                               b_PortBMode;
+
+                            /***********************/
+                                                                       /* Set TTL port C mode */
+                            /***********************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TTLIOInfo.
+                                                                               b_PortConfiguration
+                                                                               [2]
+                                                                               =
+                                                                               b_PortCMode;
+
+                            /***********************/
+                                                                       /* Set TTL port D mode */
+                            /***********************/
+
+                                                                       devpriv->
+                                                                               s_ModuleInfo
+                                                                               [b_ModulNbr].
+                                                                               s_TTLIOInfo.
+                                                                               b_PortConfiguration
+                                                                               [3]
+                                                                               =
+                                                                               b_PortDMode;
+
+                            /*************************/
+                                                                       /* Set the configuration */
+                            /*************************/
+
+                                                                       outl((b_PortAMode << 0) | (b_PortBMode << 1) | (b_PortCMode << 2) | (b_PortDMode << 3), devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr));
+                                                               } else {
+                            /**********************************/
+                                                                       /* Port D mode selection is wrong */
+                            /**********************************/
+
+                                                                       DPRINTK("Port D mode selection is wrong\n");
+                                                                       i_ReturnValue
+                                                                               =
+                                                                               -8;
+                                                               }
+                                                       } else {
+                         /**********************************/
+                                                               /* Port C mode selection is wrong */
+                         /**********************************/
+
+                                                               DPRINTK("Port C mode selection is wrong\n");
+                                                               i_ReturnValue =
+                                                                       -7;
+                                                       }
+                                               } else {
+                      /**********************************/
+                                                       /* Port B mode selection is wrong */
+                      /**********************************/
+
+                                                       DPRINTK("Port B mode selection is wrong\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       } else {
+                   /**********************************/
+                                               /* Port A mode selection is wrong */
+                   /**********************************/
+
+                                               DPRINTK("Port A mode selection is wrong\n");
+                                               i_ReturnValue = -5;
+                                       }
+                               } else {
+                /*******************************************/
+                                       /* Function not available for this version */
+                /*******************************************/
+
+                                       DPRINTK("Function not available for this version\n");
+                                       i_ReturnValue = -4;
+                               }
+                               break;
+
+                               DPRINTK("\n");
+                       default:
+                               printk("Bad Config Type\n");
+                       }       // switch end
+               } else {
+             /**********************************/
+                       /* The module is not a TTL module */
+             /**********************************/
+
+                       DPRINTK("The module is not a TTL module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            INPUT FUNCTIONS                                 |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_   i_APCI1710_ReadTTLIOChannelValue               |
+|                                       (BYTE_     b_BoardHandle,            |
+|                                        BYTE_     b_ModulNbr,               |
+|                                        BYTE_     b_SelectedPort,           |
+|                                        BYTE_     b_InputChannel,           |
+|                                        PBYTE_   pb_ChannelStatus)          |
++----------------------------------------------------------------------------+
+| Task              : Read the status from selected TTL digital input        |
+|                     (b_InputChannel)
++----------------------------------------------------------------------------+
+| Task              : Read the status from digital input port                |
+|                     (b_SelectedPort) from selected TTL module (b_ModulNbr) |
++----------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr            : Module number to         |
+|                                                   configure (0 to 7)       |
+|                     BYTE_ b_SelectedPort,       : Selection from TTL I/O   |
+|                                                   port (0 to 2)            |
+|                                                      0 : Port A selection  |
+|                                                      1 : Port B selection  |
+|                                                      2 : Port C selection  |
+|                                                      3 : Port D selection  |
+|                     BYTE_ b_InputChannel        : Selection from digital   |
+|                                                   input ( 0 to 2)
+APCI1710_TTL_READCHANNEL
+       b_ModulNbr        = CR_AREF(insn->chanspec);
+       b_SelectedPort= CR_RANGE(insn->chanspec);
+       b_InputChannel= CR_CHAN(insn->chanspec);
+       b_ReadType        = (BYTE) data[0];
+
+ APCI1710_TTL_READPORT|
+       b_ModulNbr        = CR_AREF(insn->chanspec);
+       b_SelectedPort= CR_RANGE(insn->chanspec);
+       b_ReadType        = (BYTE) data[0];
+
++----------------------------------------------------------------------------+
+| Output Parameters : data[0]
+
+       PBYTE_  pb_ChannelStatus    : Digital input channel    |
+|                                                   status                   |
+|                                                   0 : Channle is not active|
+|                                                   1 : Channle is active    |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a TTL module                      |
+|                    -4: The selected TTL input port is wrong                |
+|                    -5: The selected TTL digital input is wrong             |
+|                    -6: TTL I/O not initialised                             |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsReadTTLIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg;
+       BYTE b_ModulNbr;
+       BYTE b_SelectedPort;
+       BYTE b_InputChannel;
+       BYTE b_ReadType;
+       PBYTE pb_ChannelStatus;
+       PBYTE pb_PortValue;
+
+       i_ReturnValue = insn->n;
+       b_ReadType = (BYTE) data[0];
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_SelectedPort = CR_RANGE(insn->chanspec);
+       b_InputChannel = CR_CHAN(insn->chanspec);
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /**************************/
+               /* Test if TTL I/O module */
+          /**************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TTL_IO) {
+                       switch (b_ReadType) {
+
+                       case APCI1710_TTL_READCHANNEL:
+                               pb_ChannelStatus = (PBYTE) & data[0];
+             /********************************/
+                               /* Test the TTL I/O port number */
+             /********************************/
+
+                               if (((b_SelectedPort <= 2)
+                                               && ((devpriv->s_BoardInfos.
+                                                               dw_MolduleConfiguration
+                                                               [b_ModulNbr] &
+                                                               0xFFFF) ==
+                                                       0x3130))
+                                       || ((b_SelectedPort <= 3)
+                                               && ((devpriv->s_BoardInfos.
+                                                               dw_MolduleConfiguration
+                                                               [b_ModulNbr] &
+                                                               0xFFFF) >=
+                                                       0x3230))) {
+                /******************************************/
+                                       /* Test the digital imnput channel number */
+                /******************************************/
+
+                                       if (((b_InputChannel <= 7)
+                                                       && (b_SelectedPort < 3))
+                                               || ((b_InputChannel <= 1)
+                                                       && (b_SelectedPort ==
+                                                               3))) {
+                   /******************************************/
+                                               /* Test if the TTL I/O module initialised */
+                   /******************************************/
+
+                                               if (devpriv->
+                                                       s_ModuleInfo
+                                                       [b_ModulNbr].
+                                                       s_TTLIOInfo.b_TTLInit ==
+                                                       1) {
+                      /***********************************/
+                                                       /* Test if TTL port used for input */
+                      /***********************************/
+
+                                                       if (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) == 0x3130) || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) {
+                         /**************************/
+                                                               /* Read all digital input */
+                         /**************************/
+
+                                                               dw_StatusReg =
+                                                                       inl
+                                                                       (devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       +
+                                                                       (64 * b_ModulNbr));
+
+                                                               *pb_ChannelStatus
+                                                                       =
+                                                                       (BYTE) (
+                                                                       (dw_StatusReg
+                                                                               >>
+                                                                               (8 * b_SelectedPort)) >> b_InputChannel) & 1;
+                                                       } else {
+                         /*******************************/
+                                                               /* Selected TTL I/O port error */
+                         /*******************************/
+
+                                                               DPRINTK("Selected TTL I/O port error\n");
+                                                               i_ReturnValue =
+                                                                       -4;
+                                                       }
+                                               } else {
+                      /***************************/
+                                                       /* TTL I/O not initialised */
+                      /***************************/
+
+                                                       DPRINTK("TTL I/O not initialised\n");
+                                                       i_ReturnValue = -6;
+                                               }
+                                       } else {
+                   /********************************/
+                                               /* Selected digital input error */
+                   /********************************/
+
+                                               DPRINTK("Selected digital input error\n");
+                                               i_ReturnValue = -5;
+                                       }
+                               } else {
+                /*******************************/
+                                       /* Selected TTL I/O port error */
+                /*******************************/
+
+                                       DPRINTK("Selected TTL I/O port error\n");
+                                       i_ReturnValue = -4;
+                               }
+                               break;
+
+                       case APCI1710_TTL_READPORT:
+                               pb_PortValue = (PBYTE) & data[0];
+                         /********************************/
+                               /* Test the TTL I/O port number */
+                         /********************************/
+
+                               if (((b_SelectedPort <= 2)
+                                               && ((devpriv->s_BoardInfos.
+                                                               dw_MolduleConfiguration
+                                                               [b_ModulNbr] &
+                                                               0xFFFF) ==
+                                                       0x3130))
+                                       || ((b_SelectedPort <= 3)
+                                               && ((devpriv->s_BoardInfos.
+                                                               dw_MolduleConfiguration
+                                                               [b_ModulNbr] &
+                                                               0xFFFF) >=
+                                                       0x3230))) {
+                /******************************************/
+                                       /* Test if the TTL I/O module initialised */
+                /******************************************/
+
+                                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_TTLIOInfo.b_TTLInit == 1) {
+                   /***********************************/
+                                               /* Test if TTL port used for input */
+                   /***********************************/
+
+                                               if (((devpriv->s_BoardInfos.
+                                                                       dw_MolduleConfiguration
+                                                                       [b_ModulNbr]
+                                                                       &
+                                                                       0xFFFF)
+                                                               == 0x3130)
+                                                       || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) {
+                      /**************************/
+                                                       /* Read all digital input */
+                      /**************************/
+
+                                                       dw_StatusReg =
+                                                               inl(devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               (64 * b_ModulNbr));
+
+                                                       *pb_PortValue =
+                                                               (BYTE) (
+                                                               (dw_StatusReg >>
+                                                                       (8 * b_SelectedPort)) & 0xFF);
+                                               } else {
+                      /*******************************/
+                                                       /* Selected TTL I/O port error */
+                      /*******************************/
+
+                                                       DPRINTK("Selected TTL I/O port error\n");
+                                                       i_ReturnValue = -4;
+                                               }
+                                       } else {
+                   /***************************/
+                                               /* TTL I/O not initialised */
+                   /***************************/
+
+                                               DPRINTK("TTL I/O not initialised\n");
+                                               i_ReturnValue = -5;
+                                       }
+                               } else {
+                /*******************************/
+                                       /* Selected TTL I/O port error */
+                /*******************************/
+
+                                       DPRINTK("Selected TTL I/O port error\n");
+                                       i_ReturnValue = -4;
+                               }
+                               break;
+
+                       default:
+                               printk("Bad ReadType\n");
+
+                       }       //End Switch
+               } else {
+             /**********************************/
+                       /* The module is not a TTL module */
+             /**********************************/
+
+                       DPRINTK("The module is not a TTL module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
+*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)              |
++----------------------------------------------------------------------------+
+| Task              : Read the status from all digital input ports           |
+|                     (port A, port B and port C) from selected TTL          |
+|                    module (b_ModulNbr)                                    |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|
+|                     BYTE_ b_ModulNbr            : Module number to         |
+|                                                   configure (0 to 3)       |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_  pul_PortValue      : Digital TTL inputs port  |
+|                                                   status                   |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a TTL module                      |
+|                    -4: TTL I/O not initialised                             |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg;
+       BYTE b_ModulNbr;
+       PULONG pul_PortValue;
+
+       b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+       i_ReturnValue = insn->n;
+       pul_PortValue = (PULONG) & data[0];
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /**************************/
+               /* Test if TTL I/O module */
+          /**************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TTL_IO) {
+             /******************************************/
+                       /* Test if the TTL I/O module initialised */
+             /******************************************/
+
+                       if (devpriv->
+                               s_ModuleInfo[b_ModulNbr].
+                               s_TTLIOInfo.b_TTLInit == 1) {
+                /**************************/
+                               /* Read all digital input */
+                /**************************/
+
+                               dw_StatusReg = inl(devpriv->s_BoardInfos.
+                                       ui_Address + (64 * b_ModulNbr));
+
+                /**********************/
+                               /* Test if TTL Rev1.0 */
+                /**********************/
+
+                               if ((devpriv->s_BoardInfos.
+                                               dw_MolduleConfiguration
+                                               [b_ModulNbr] & 0xFFFF) ==
+                                       0x3130) {
+                                       *pul_PortValue =
+                                               dw_StatusReg & 0xFFFFFFUL;
+                               } else {
+                   /**************************************/
+                                       /* Test if port A not used for output */
+                   /**************************************/
+
+                                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                                               s_TTLIOInfo.
+                                               b_PortConfiguration[0] == 1) {
+                                               *pul_PortValue =
+                                                       dw_StatusReg &
+                                                       0x3FFFF00UL;
+                                       }
+
+                   /**************************************/
+                                       /* Test if port B not used for output */
+                   /**************************************/
+
+                                       if (devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_TTLIOInfo.
+                                               b_PortConfiguration[1] == 1) {
+                                               *pul_PortValue =
+                                                       dw_StatusReg &
+                                                       0x3FF00FFUL;
+                                       }
+
+                   /**************************************/
+                                       /* Test if port C not used for output */
+                   /**************************************/
+
+                                       if (devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_TTLIOInfo.
+                                               b_PortConfiguration[2] == 1) {
+                                               *pul_PortValue =
+                                                       dw_StatusReg &
+                                                       0x300FFFFUL;
+                                       }
+
+                   /**************************************/
+                                       /* Test if port D not used for output */
+                   /**************************************/
+
+                                       if (devpriv->
+                                               s_ModuleInfo[b_ModulNbr].
+                                               s_TTLIOInfo.
+                                               b_PortConfiguration[3] == 1) {
+                                               *pul_PortValue =
+                                                       dw_StatusReg &
+                                                       0xFFFFFFUL;
+                                       }
+                               }
+                       } else {
+                /***************************/
+                               /* TTL I/O not initialised */
+                /***************************/
+                               DPRINTK("TTL I/O not initialised\n");
+                               i_ReturnValue = -5;
+                       }
+               } else {
+             /**********************************/
+                       /* The module is not a TTL module */
+             /**********************************/
+                       DPRINTK("The module is not a TTL module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            OUTPUT FUNCTIONS                                |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : _INT_ i_APCI1710_SetTTLIOChlOn                         |
+|                               (BYTE_           b_BoardHandle,              |
+|                                BYTE_           b_ModulNbr,                 |
+|                                BYTE_           b_OutputChannel)
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)           |
++----------------------------------------------------------------------------+
+| Task              : Sets or resets  the output witch has been passed with the         |
+|                     parameter b_Channel. Setting an output means setting   |
+|                     an ouput high.                                         |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|
+|                     BYTE_ b_OutputChannel : Selection from digital output  |
+|                                             channel (0 or 1)               |
+|                                                0      : PD0                |
+|                                                1      : PD1                |
+|                                               2 to 9 : PA                 |
+|                                              10 to 17: PB                 |
+|                                              18 to 25: PC                 |
+
+  b_ModulNbr      = CR_AREF(insn->chanspec);
+       b_OutputChannel= CR_CHAN(insn->chanspec);
+       ui_State           = data[0]; // ON or OFF
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -1: The handle parameter of the board is wrong          |
+|                    -2: The module parameter is wrong                       |
+|                    -3: The module is not a TTL I/O module                  |
+|                    -4: The selected digital output is wrong                |
+|                    -5: TTL I/O not initialised see function                |
+|                        " i_APCI1710_InitTTLIO"
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = 0;
+       DWORD dw_StatusReg = 0;
+       BYTE b_ModulNbr;
+       BYTE b_OutputChannel;
+       UINT ui_State;
+
+       i_ReturnValue = insn->n;
+       b_ModulNbr = CR_AREF(insn->chanspec);
+       b_OutputChannel = CR_CHAN(insn->chanspec);
+       ui_State = data[0];     // ON or OFF
+
+       /**************************/
+       /* Test the module number */
+       /**************************/
+
+       if (b_ModulNbr < 4) {
+          /**************************/
+               /* Test if TTL I/O module */
+          /**************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModulNbr] &
+                               0xFFFF0000UL) == APCI1710_TTL_IO) {
+             /******************************************/
+                       /* Test if the TTL I/O module initialised */
+             /******************************************/
+
+                       if (devpriv->s_ModuleInfo[b_ModulNbr].
+                               s_TTLIOInfo.b_TTLInit == 1) {
+                /***********************************/
+                               /* Test the TTL I/O channel number */
+                /***********************************/
+
+                               if (((b_OutputChannel <= 1)
+                                               && ((devpriv->s_BoardInfos.
+                                                               dw_MolduleConfiguration
+                                                               [b_ModulNbr] &
+                                                               0xFFFF) ==
+                                                       0x3130))
+                                       || ((b_OutputChannel <= 25)
+                                               && ((devpriv->s_BoardInfos.
+                                                               dw_MolduleConfiguration
+                                                               [b_ModulNbr] &
+                                                               0xFFFF) >=
+                                                       0x3230))) {
+                   /****************************************************/
+                                       /* Test if the selected channel is a output channel */
+                   /****************************************************/
+
+                                       if (((b_OutputChannel <= 1)
+                                                       && (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_TTLIOInfo.
+                                                               b_PortConfiguration
+                                                               [3] == 1))
+                                               || ((b_OutputChannel >= 2)
+                                                       && (b_OutputChannel <=
+                                                               9)
+                                                       && (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_TTLIOInfo.
+                                                               b_PortConfiguration
+                                                               [0] == 1))
+                                               || ((b_OutputChannel >= 10)
+                                                       && (b_OutputChannel <=
+                                                               17)
+                                                       && (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_TTLIOInfo.
+                                                               b_PortConfiguration
+                                                               [1] == 1))
+                                               || ((b_OutputChannel >= 18)
+                                                       && (b_OutputChannel <=
+                                                               25)
+                                                       && (devpriv->
+                                                               s_ModuleInfo
+                                                               [b_ModulNbr].
+                                                               s_TTLIOInfo.
+                                                               b_PortConfiguration
+                                                               [2] == 1))) {
+                      /************************/
+                                               /* Test if PD0 selected */
+                      /************************/
+
+                                               if (b_OutputChannel == 0) {
+
+                                                       outl(ui_State,
+                                                               devpriv->
+                                                               s_BoardInfos.
+                                                               ui_Address +
+                                                               (64 * b_ModulNbr));
+                                               } else {
+                         /************************/
+                                                       /* Test if PD1 selected */
+                         /************************/
+
+                                                       if (b_OutputChannel ==
+                                                               1) {
+
+                                                               outl(ui_State,
+                                                                       devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       + 4 +
+                                                                       (64 * b_ModulNbr));
+                                                       } else {
+                                                               b_OutputChannel
+                                                                       =
+                                                                       b_OutputChannel
+                                                                       - 2;
+
+                            /********************/
+                                                               /* Read all channel */
+                            /********************/
+
+                                                               dw_StatusReg =
+                                                                       inl
+                                                                       (devpriv->
+                                                                       s_BoardInfos.
+                                                                       ui_Address
+                                                                       +
+                                                                       (64 * b_ModulNbr));
+                                                               if (ui_State)   // ON
+                                                               {
+                                                                       dw_StatusReg
+                                                                               =
+                                                                               (dw_StatusReg
+                                                                               >>
+                                                                               ((b_OutputChannel / 8) * 8)) & 0xFF;
+                                                                       dw_StatusReg
+                                                                               =
+                                                                               dw_StatusReg
+                                                                               |
+                                                                               (1
+                                                                               <<
+                                                                               (b_OutputChannel
+                                                                                       %
+                                                                                       8));
+                                                               } else  // Off
+                                                               {
+                                                                       dw_StatusReg
+                                                                               =
+                                                                               (dw_StatusReg
+                                                                               >>
+                                                                               ((b_OutputChannel / 8) * 8)) & 0xFF;
+                                                                       dw_StatusReg
+                                                                               =
+                                                                               dw_StatusReg
+                                                                               &
+                                                                               (0xFF
+                                                                               -
+                                                                               (1 << (b_OutputChannel % 8)));
+
+                                                               }
+
+                            /****************************/
+                                                               /* Set the new output value */
+                            /****************************/
+
+                                                               outl(dw_StatusReg, devpriv->s_BoardInfos.ui_Address + 8 + ((b_OutputChannel / 8) * 4) + (64 * b_ModulNbr));
+                                                       }
+                                               }
+                                       } else {
+                      /************************************/
+                                               /* The selected TTL output is wrong */
+                      /************************************/
+
+                                               DPRINTK(" The selected TTL output is wrong\n");
+                                               i_ReturnValue = -4;
+                                       }
+                               } else {
+                   /************************************/
+                                       /* The selected TTL output is wrong */
+                   /************************************/
+
+                                       DPRINTK("The selected TTL output is wrong\n");
+                                       i_ReturnValue = -4;
+                               }
+                       } else {
+                /***************************/
+                               /* TTL I/O not initialised */
+                /***************************/
+
+                               DPRINTK("TTL I/O not initialised\n");
+                               i_ReturnValue = -5;
+                       }
+               } else {
+             /**************************************/
+                       /* The module is not a TTL I/O module */
+             /**************************************/
+
+                       DPRINTK("The module is not a TTL I/O module\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /***********************/
+               /* Module number error */
+          /***********************/
+
+               DPRINTK("Module number error\n");
+               i_ReturnValue = -2;
+       }
+
+       return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
new file mode 100644 (file)
index 0000000..ed3e5c5
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define APCI1710_TTL_INIT                      0
+#define APCI1710_TTL_INITDIRECTION  1
+
+#define APCI1710_TTL_READCHANNEL       0
+#define APCI1710_TTL_READPORT          1
+
+/*
++----------------------------------------------------------------------------+
+|                       TTL INISIALISATION FUNCTION                          |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTTLIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+/*
++----------------------------------------------------------------------------+
+|                       TTL INPUT FUNCTION                                   |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsReadTTLIO(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+/*
++----------------------------------------------------------------------------+
+|                            TTL OUTPUT FUNCTIONS                            |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
new file mode 100644 (file)
index 0000000..b0907ec
--- /dev/null
@@ -0,0 +1,203 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project : ADDI HEADER READ WRITER |     Compiler   : Visual C++       |
+  | Module name : S5920.cpp           |     Version    : 6.0              |
+  +-------------------------------+---------------------------------------+
+  | Author : E. LIBS                      Date : 02/05/2002               |
+  +-----------------------------------------------------------------------+
+  | Description   : DLL with the S5920 PCI Controller functions           |
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 28/08/02 | LIBS Eric | Add return codes each time a function of the   |
+  |          |           | Addi Library is called                         |
+  +-----------------------------------------------------------------------+
+  | 31/07/03 | KRAUTH J. | Changes for the MSX-Box                        |
+  +-----------------------------------------------------------------------+
+*/
+
+#include "addi_amcc_S5920.h"
+
+/*+----------------------------------------------------------------------------+*/
+/*| Function   Name   : INT i_AddiHeaderRW_ReadEeprom                          |*/
+/*|                               (INT    i_NbOfWordsToRead,                   |*/
+/*|                                DWORD dw_PCIBoardEepromAddress,             |*/
+/*|                                WORD   w_EepromStartAddress,                |*/
+/*|                                PWORD pw_DataRead)                          |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Task              : Read word from the 5920 eeprom.                        |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Input Parameters  : INT    i_NbOfWordsToRead : Nbr. of word to read        |*/
+/*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+/*|                     WORD   w_EepromStartAddress : Eeprom strat address     |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Output Parameters : PWORD pw_DataRead : Read data                          |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Return Value      : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+
+INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+       DWORD dw_PCIBoardEepromAddress,
+       WORD w_EepromStartAddress, PWORD pw_DataRead)
+{
+       DWORD dw_eeprom_busy = 0;
+       INT i_Counter = 0;
+       INT i_WordCounter;
+       INT i;
+       BYTE pb_ReadByte[1];
+       BYTE b_ReadLowByte = 0;
+       BYTE b_ReadHighByte = 0;
+       BYTE b_SelectedAddressLow = 0;
+       BYTE b_SelectedAddressHigh = 0;
+       WORD w_ReadWord = 0;
+
+       for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+               i_WordCounter++) {
+               do {
+                       dw_eeprom_busy =
+                               inl(dw_PCIBoardEepromAddress +
+                               AMCC_OP_REG_MCSR);
+                       dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+               }
+               while (dw_eeprom_busy == EEPROM_BUSY);
+
+               for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+                       b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;        //Read the low 8 bit part
+                       b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256;       //Read the high 8 bit part
+
+                       //Select the load low address mode
+                       outb(NVCMD_LOAD_LOW,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Load the low address
+                       outb(b_SelectedAddressLow,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the load high address mode
+                       outb(NVCMD_LOAD_HIGH,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Load the high address
+                       outb(b_SelectedAddressHigh,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the READ mode
+                       outb(NVCMD_BEGIN_READ,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Read data into the EEPROM
+                       *pb_ReadByte =
+                               inb(dw_PCIBoardEepromAddress +
+                               AMCC_OP_REG_MCSR + 2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the upper address part
+                       if (i_Counter == 0) {
+                               b_ReadLowByte = pb_ReadByte[0];
+                       } else {
+                               b_ReadHighByte = pb_ReadByte[0];
+                       }
+
+                       //Sleep
+                       for (i = 0; i < 10000; i++) ;
+
+               }
+               w_ReadWord =
+                       (b_ReadLowByte | (((unsigned short)b_ReadHighByte) *
+                               256));
+
+               pw_DataRead[i_WordCounter] = w_ReadWord;
+
+               w_EepromStartAddress += 2;      // to read the next word
+
+       }                       // for (...) i_NbOfWordsToRead
+       return (0);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
new file mode 100644 (file)
index 0000000..e4fa569
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+#define VOID           void
+#define INT            int
+#define UINT           unsigned int
+#define SHORT          short
+#define USHORT         unsigned short
+#define CHAR           char
+#define BYTE           unsigned char
+#define WORD           unsigned int
+#define LONG           long
+#define ULONG          unsigned long
+#define DWORD          unsigned long
+#define DOUBLE         double
+#define PINT           int *
+#define PUINT          unsigned int *
+#define PSHORT         short *
+#define PUSHORT        unsigned short *
+#define PCHAR          char *
+#define PBYTE          unsigned char *
+#define PWORD          unsigned int *
+#define PLONG          long *
+#define PULONG         unsigned long *
+#define PDWORD         unsigned long *
+#define PDOUBLE        double *
+*/
+
+#define AMCC_OP_REG_MCSR         0x3c
+#define EEPROM_BUSY   0x80000000
+#define NVCMD_LOAD_LOW  (0x4 << 5 )    // nvRam load low command
+#define NVCMD_LOAD_HIGH (0x5 << 5 )    // nvRam load high command
+#define NVCMD_BEGIN_READ (0x7 << 5 )   // nvRam begin read command
+#define NVCMD_BEGIN_WRITE  (0x6 << 5)  //EEPROM begin write command
+
+INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+       DWORD dw_PCIBoardEepromAddress,
+       WORD w_EepromStartAddress, PWORD pw_DataRead);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
new file mode 100644 (file)
index 0000000..75c9301
--- /dev/null
@@ -0,0 +1,490 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project   : ADDI DATA         | Compiler : GCC                                   |
+  | Modulname : addi_amcc_s5933.h | Version  : 2.96  Redhat Linux         |
+  |                               |                    kernel-2.4.2       |
+  +-------------------------------+---------------------------------------+
+  | Author    :                          | Date     :                                    |
+  +-----------------------------------------------------------------------+
+  | Description :|Header file for AMCC  s 5933                            |
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |                          |                                                                                                |
+  |          |           |                                                                                               |
+  |          |           |                                                           |
+  |          |           |                                                                                               |
+  |          |           |                                                                   |
+  +----------+-----------+------------------------------------------------+
+  |         |                   |                                                                        |
+  |          |           |                                                                                               |
+  |          |           |                                                                               |
+  +----------+-----------+------------------------------------------------+
+*/
+
+#ifndef _AMCC_S5933_H_
+#define _AMCC_S5933_H_
+
+#include "../../comedidev.h"
+
+#include "../comedi_pci.h"
+
+#ifdef PCI_SUPPORT_VER1
+#error     No support for 2.1.55 and older
+#endif
+
+#define FIFO_ADVANCE_ON_BYTE_2     0x20000000  // written on base0
+
+#define AMWEN_ENABLE                     0x02  // added for step 6 dma written on base2
+#define A2P_FIFO_WRITE_ENABLE            0x01
+
+#define AGCSTS_TC_ENABLE                  0x10000000   // for transfer count enable bit
+
+//  ADDON RELATED ADDITIONS
+// Constant
+#define     APCI3120_ENABLE_TRANSFER_ADD_ON_LOW       0x00
+#define     APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH      0x1200
+#define     APCI3120_A2P_FIFO_MANAGEMENT              0x04000400L
+#define     APCI3120_AMWEN_ENABLE                     0x02
+#define     APCI3120_A2P_FIFO_WRITE_ENABLE            0x01
+#define     APCI3120_FIFO_ADVANCE_ON_BYTE_2           0x20000000L
+#define     APCI3120_ENABLE_WRITE_TC_INT              0x00004000L
+#define     APCI3120_CLEAR_WRITE_TC_INT               0x00040000L
+#define     APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
+#define     APCI3120_DISABLE_BUS_MASTER_ADD_ON        0x0
+#define     APCI3120_DISABLE_BUS_MASTER_PCI           0x0
+
+ // ADD_ON ::: this needed since apci supports 16 bit interface to add on
+#define     APCI3120_ADD_ON_AGCSTS_LOW       0x3C
+#define     APCI3120_ADD_ON_AGCSTS_HIGH      APCI3120_ADD_ON_AGCSTS_LOW + 2
+#define     APCI3120_ADD_ON_MWAR_LOW         0x24
+#define     APCI3120_ADD_ON_MWAR_HIGH        APCI3120_ADD_ON_MWAR_LOW + 2
+#define     APCI3120_ADD_ON_MWTC_LOW         0x058
+#define     APCI3120_ADD_ON_MWTC_HIGH        APCI3120_ADD_ON_MWTC_LOW + 2
+
+// AMCC
+#define     APCI3120_AMCC_OP_MCSR            0x3C
+#define     APCI3120_AMCC_OP_REG_INTCSR      0x38
+
+/****************************************************************************/
+/* AMCC Operation Register Offsets - PCI                                    */
+/****************************************************************************/
+
+#define AMCC_OP_REG_OMB1         0x00
+#define AMCC_OP_REG_OMB2         0x04
+#define AMCC_OP_REG_OMB3         0x08
+#define AMCC_OP_REG_OMB4         0x0c
+#define AMCC_OP_REG_IMB1         0x10
+#define AMCC_OP_REG_IMB2         0x14
+#define AMCC_OP_REG_IMB3         0x18
+#define AMCC_OP_REG_IMB4         0x1c
+#define AMCC_OP_REG_FIFO         0x20
+#define AMCC_OP_REG_MWAR         0x24
+#define AMCC_OP_REG_MWTC         0x28
+#define AMCC_OP_REG_MRAR         0x2c
+#define AMCC_OP_REG_MRTC         0x30
+#define AMCC_OP_REG_MBEF         0x34
+#define AMCC_OP_REG_INTCSR       0x38
+#define  AMCC_OP_REG_INTCSR_SRC  (AMCC_OP_REG_INTCSR + 2)      /* INT source */
+#define  AMCC_OP_REG_INTCSR_FEC  (AMCC_OP_REG_INTCSR + 3)      /* FIFO ctrl */
+#define AMCC_OP_REG_MCSR         0x3c
+#define  AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2)        /* Data in byte 2 */
+#define  AMCC_OP_REG_MCSR_NVCMD  (AMCC_OP_REG_MCSR + 3)        /* Command in byte 3 */
+
+#define AMCC_FIFO_DEPTH_DWORD  8
+#define AMCC_FIFO_DEPTH_BYTES  (8 * sizeof (u32))
+
+/****************************************************************************/
+/* AMCC Operation Registers Size - PCI                                      */
+/****************************************************************************/
+
+#define AMCC_OP_REG_SIZE        64     /* in bytes */
+
+/****************************************************************************/
+/* AMCC Operation Register Offsets - Add-on                                 */
+/****************************************************************************/
+
+#define AMCC_OP_REG_AIMB1         0x00
+#define AMCC_OP_REG_AIMB2         0x04
+#define AMCC_OP_REG_AIMB3         0x08
+#define AMCC_OP_REG_AIMB4         0x0c
+#define AMCC_OP_REG_AOMB1         0x10
+#define AMCC_OP_REG_AOMB2         0x14
+#define AMCC_OP_REG_AOMB3         0x18
+#define AMCC_OP_REG_AOMB4         0x1c
+#define AMCC_OP_REG_AFIFO         0x20
+#define AMCC_OP_REG_AMWAR         0x24
+#define AMCC_OP_REG_APTA          0x28
+#define AMCC_OP_REG_APTD          0x2c
+#define AMCC_OP_REG_AMRAR         0x30
+#define AMCC_OP_REG_AMBEF         0x34
+#define AMCC_OP_REG_AINT          0x38
+#define AMCC_OP_REG_AGCSTS        0x3c
+#define AMCC_OP_REG_AMWTC         0x58
+#define AMCC_OP_REG_AMRTC         0x5c
+
+/****************************************************************************/
+/* AMCC - Add-on General Control/Status Register                            */
+/****************************************************************************/
+
+#define AGCSTS_CONTROL_MASK    0xfffff000
+#define  AGCSTS_NV_ACC_MASK    0xe0000000
+#define  AGCSTS_RESET_MASK     0x0e000000
+#define  AGCSTS_NV_DA_MASK     0x00ff0000
+#define  AGCSTS_BIST_MASK      0x0000f000
+#define AGCSTS_STATUS_MASK     0x000000ff
+#define  AGCSTS_TCZERO_MASK    0x000000c0
+#define  AGCSTS_FIFO_ST_MASK   0x0000003f
+
+#define AGCSTS_RESET_MBFLAGS   0x08000000
+#define AGCSTS_RESET_P2A_FIFO  0x04000000
+#define AGCSTS_RESET_A2P_FIFO  0x02000000
+#define AGCSTS_RESET_FIFOS     (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
+
+#define AGCSTS_A2P_TCOUNT      0x00000080
+#define AGCSTS_P2A_TCOUNT      0x00000040
+
+#define AGCSTS_FS_P2A_EMPTY    0x00000020
+#define AGCSTS_FS_P2A_HALF     0x00000010
+#define AGCSTS_FS_P2A_FULL     0x00000008
+
+#define AGCSTS_FS_A2P_EMPTY    0x00000004
+#define AGCSTS_FS_A2P_HALF     0x00000002
+#define AGCSTS_FS_A2P_FULL     0x00000001
+
+/****************************************************************************/
+/* AMCC - Add-on Interrupt Control/Status Register                            */
+/****************************************************************************/
+
+#define AINT_INT_MASK          0x00ff0000
+#define AINT_SEL_MASK          0x0000ffff
+#define  AINT_IS_ENSEL_MASK    0x00001f1f
+
+#define AINT_INT_ASSERTED      0x00800000
+#define AINT_BM_ERROR          0x00200000
+#define AINT_BIST_INT          0x00100000
+
+#define AINT_RT_COMPLETE       0x00080000
+#define AINT_WT_COMPLETE       0x00040000
+
+#define AINT_OUT_MB_INT                0x00020000
+#define AINT_IN_MB_INT         0x00010000
+
+#define AINT_READ_COMPL                0x00008000
+#define AINT_WRITE_COMPL       0x00004000
+
+#define AINT_OMB_ENABLE        0x00001000
+#define AINT_OMB_SELECT        0x00000c00
+#define AINT_OMB_BYTE          0x00000300
+
+#define AINT_IMB_ENABLE        0x00000010
+#define AINT_IMB_SELECT        0x0000000c
+#define AINT_IMB_BYTE          0x00000003
+
+/* Enable Bus Mastering */
+#define EN_A2P_TRANSFERS       0x00000400
+/* FIFO Flag Reset */
+#define RESET_A2P_FLAGS                0x04000000L
+/* FIFO Relative Priority */
+#define A2P_HI_PRIORITY                0x00000100L
+/* Identify Interrupt Sources */
+#define ANY_S593X_INT          0x00800000L
+#define READ_TC_INT            0x00080000L
+#define WRITE_TC_INT           0x00040000L
+#define IN_MB_INT              0x00020000L
+#define MASTER_ABORT_INT       0x00100000L
+#define TARGET_ABORT_INT       0x00200000L
+#define BUS_MASTER_INT         0x00200000L
+
+/****************************************************************************/
+
+struct pcilst_struct {
+       struct pcilst_struct *next;
+       int used;
+       struct pci_dev *pcidev;
+       unsigned short vendor;
+       unsigned short device;
+       unsigned char pci_bus;
+       unsigned char pci_slot;
+       unsigned char pci_func;
+       resource_size_t io_addr[5];
+       unsigned int irq;
+};
+
+struct pcilst_struct *amcc_devices;    // ptr to root list of all amcc devices
+
+static const int i_ADDIDATADeviceID[] = { 0x15B8, 0x10E8 };
+
+/****************************************************************************/
+
+void v_pci_card_list_init(unsigned short pci_vendor, char display);
+void v_pci_card_list_cleanup(unsigned short pci_vendor);
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+       unsigned short device_id);
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot, struct pcilst_struct **card);
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot, int i_Master);
+
+int pci_card_alloc(struct pcilst_struct *amcc, int master);
+int i_pci_card_free(struct pcilst_struct *amcc);
+void v_pci_card_list_display(void);
+int i_pci_card_data(struct pcilst_struct *amcc,
+       unsigned char *pci_bus, unsigned char *pci_slot,
+       unsigned char *pci_func, resource_size_t * io_addr, unsigned int *irq);
+
+/****************************************************************************/
+
+/* build list of amcc cards in this system */
+void v_pci_card_list_init(unsigned short pci_vendor, char display)
+{
+       struct pci_dev *pcidev;
+       struct pcilst_struct *amcc, *last;
+       int i;
+       int i_Count = 0;
+       amcc_devices = NULL;
+       last = NULL;
+
+       for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+               pcidev != NULL;
+               pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+               for (i_Count = 0; i_Count < 2; i_Count++) {
+                       pci_vendor = i_ADDIDATADeviceID[i_Count];
+                       if (pcidev->vendor == pci_vendor) {
+                               amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
+                               memset(amcc, 0, sizeof(*amcc));
+
+                               amcc->pcidev = pcidev;
+                               if (last) {
+                                       last->next = amcc;
+                               } else {
+                                       amcc_devices = amcc;
+                               }
+                               last = amcc;
+
+                               amcc->vendor = pcidev->vendor;
+                               amcc->device = pcidev->device;
+                               amcc->pci_bus = pcidev->bus->number;
+                               amcc->pci_slot = PCI_SLOT(pcidev->devfn);
+                               amcc->pci_func = PCI_FUNC(pcidev->devfn);
+                               /* Note: resources may be invalid if PCI device
+                                * not enabled, but they are corrected in
+                                * pci_card_alloc. */
+                               for (i = 0; i < 5; i++)
+                                       amcc->io_addr[i] =
+                                               pci_resource_start(pcidev, i);
+                               amcc->irq = pcidev->irq;
+
+                       }
+               }
+       }
+
+       if (display)
+               v_pci_card_list_display();
+}
+
+/****************************************************************************/
+/* free up list of amcc cards in this system */
+void v_pci_card_list_cleanup(unsigned short pci_vendor)
+{
+       struct pcilst_struct *amcc, *next;
+
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               kfree(amcc);
+       }
+
+       amcc_devices = NULL;
+}
+
+/****************************************************************************/
+/* find first unused card with this device_id */
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+       unsigned short device_id)
+{
+       struct pcilst_struct *amcc, *next;
+
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               if ((!amcc->used) && (amcc->device == device_id)
+                       && (amcc->vendor == vendor_id))
+                       return amcc;
+
+       }
+
+       return NULL;
+}
+
+/****************************************************************************/
+/* find card on requested position */
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot, struct pcilst_struct **card)
+{
+       struct pcilst_struct *amcc, *next;
+
+       *card = NULL;
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
+                       && (amcc->pci_bus == pci_bus)
+                       && (amcc->pci_slot == pci_slot)) {
+                       if (!(amcc->used)) {
+                               *card = amcc;
+                               return 0;       // ok, card is found
+                       } else {
+                               rt_printk
+                                       (" - \nCard on requested position is used b:s %d:%d!\n",
+                                       pci_bus, pci_slot);
+                               return 2;       // card exist but is used
+                       }
+               }
+       }
+
+       return 1;               // no card found
+}
+
+/****************************************************************************/
+/* mark card as used */
+int pci_card_alloc(struct pcilst_struct *amcc, int master)
+{
+       int i;
+
+       if (!amcc)
+               return -1;
+
+       if (amcc->used)
+               return 1;
+       if (comedi_pci_enable(amcc->pcidev, "addi_amcc_s5933"))
+               return -1;
+       /* Resources will be accurate now. */
+       for (i = 0; i < 5; i++)
+               amcc->io_addr[i] = pci_resource_start(amcc->pcidev, i);
+       if (master)
+               pci_set_master(amcc->pcidev);
+       amcc->used = 1;
+
+       return 0;
+}
+
+/****************************************************************************/
+/* mark card as free */
+int i_pci_card_free(struct pcilst_struct *amcc)
+{
+       if (!amcc)
+               return -1;
+
+       if (!amcc->used)
+               return 1;
+       amcc->used = 0;
+       comedi_pci_disable(amcc->pcidev);
+       return 0;
+}
+
+/****************************************************************************/
+/* display list of found cards */
+void v_pci_card_list_display(void)
+{
+       struct pcilst_struct *amcc, *next;
+
+       printk("List of pci cards\n");
+       printk("bus:slot:func vendor device io_amcc io_daq irq used\n");
+
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               printk("%2d   %2d   %2d  0x%4x 0x%4x   0x%8llx 0x%8llx  %2u  %2d\n", amcc->pci_bus, amcc->pci_slot, amcc->pci_func, amcc->vendor, amcc->device, (unsigned long long)amcc->io_addr[0], (unsigned long long)amcc->io_addr[2], amcc->irq, amcc->used);
+
+       }
+}
+
+/****************************************************************************/
+/* return all card information for driver */
+int i_pci_card_data(struct pcilst_struct *amcc,
+       unsigned char *pci_bus, unsigned char *pci_slot,
+       unsigned char *pci_func, resource_size_t * io_addr, unsigned int *irq)
+{
+       int i;
+
+       if (!amcc)
+               return -1;
+       *pci_bus = amcc->pci_bus;
+       *pci_slot = amcc->pci_slot;
+       *pci_func = amcc->pci_func;
+       for (i = 0; i < 5; i++)
+               io_addr[i] = amcc->io_addr[i];
+       *irq = amcc->irq;
+       return 0;
+}
+
+/****************************************************************************/
+/* select and alloc card */
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot, int i_Master)
+{
+       struct pcilst_struct *card;
+
+       if ((pci_bus < 1) & (pci_slot < 1)) {   // use autodetection
+               if ((card = ptr_find_free_pci_card_by_device(vendor_id,
+                                       device_id)) == NULL) {
+                       rt_printk(" - Unused card not found in system!\n");
+                       return NULL;
+               }
+       } else {
+               switch (i_find_free_pci_card_by_position(vendor_id, device_id,
+                               pci_bus, pci_slot, &card)) {
+               case 1:
+                       rt_printk
+                               (" - Card not found on requested position b:s %d:%d!\n",
+                               pci_bus, pci_slot);
+                       return NULL;
+               case 2:
+                       rt_printk
+                               (" - Card on requested position is used b:s %d:%d!\n",
+                               pci_bus, pci_slot);
+                       return NULL;
+               }
+       }
+
+       if (pci_card_alloc(card, i_Master) != 0) {
+               rt_printk(" - Can't allocate card!\n");
+               return NULL;
+
+       }
+
+       return card;
+}
+#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
new file mode 100644 (file)
index 0000000..63c93de
--- /dev/null
@@ -0,0 +1,3062 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project   : ADDI DATA         | Compiler : GCC                       |
+  | Modulname : addi_common.c     | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Author    :           | Date     :                                   |
+  +-----------------------------------------------------------------------+
+  | Description : ADDI COMMON Main Module                                 |
+  +-----------------------------------------------------------------------+
+  | CONFIG OPTIONS                                                        |
+  |    option[0] - PCI bus number - if bus number and slot number are 0, |
+  |                             then driver search for first unused card |
+  |    option[1] - PCI slot number                                       |
+  |                                                                      |
+  |    option[2] = 0  - DMA ENABLE                                       |
+  |               = 1  - DMA DISABLE                                      |
+  +----------+-----------+------------------------------------------------+
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include "../../comedidev.h"
+#include <asm/io.h>
+#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
+#include <asm/i387.h>
+#endif
+#include "../comedi_fc.h"
+
+#include "addi_common.h"
+#include "addi_amcc_s5933.h"
+
+//Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>");
+//Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module");
+//Update-0.7.57->0.7.68MODULE_LICENSE("GPL");
+
+#define devpriv ((addi_private *)dev->private)
+#define this_board ((boardtype *)dev->board_ptr)
+
+#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
+//BYTE b_SaveFPUReg [94];
+
+void fpu_begin(void)
+{
+       //asm ("fstenv b_SaveFPUReg");
+       kernel_fpu_begin();
+}
+
+void fpu_end(void)
+{
+       // asm ("frstor b_SaveFPUReg");
+       kernel_fpu_end();
+}
+#endif
+
+#include "addi_eeprom.c"
+#if (defined (CONFIG_APCI_3120) || defined (CONFIG_APCI_3001))
+#include "hwdrv_apci3120.c"
+#endif
+#ifdef CONFIG_APCI_1032
+#include "hwdrv_apci1032.c"
+#endif
+#ifdef CONFIG_APCI_1516
+#include "hwdrv_apci1516.c"
+#endif
+#ifdef CONFIG_APCI_2016
+#include "hwdrv_apci2016.c"
+#endif
+#ifdef CONFIG_APCI_2032
+#include "hwdrv_apci2032.c"
+#endif
+#ifdef CONFIG_APCI_2200
+#include "hwdrv_apci2200.c"
+#endif
+#ifdef CONFIG_APCI_1564
+#include "hwdrv_apci1564.c"
+#endif
+#ifdef CONFIG_APCI_1500
+#include "hwdrv_apci1500.c"
+#endif
+#ifdef CONFIG_APCI_3501
+#include "hwdrv_apci3501.c"
+#endif
+#ifdef CONFIG_APCI_035
+#include "hwdrv_apci035.c"
+#endif
+#if (defined (CONFIG_APCI_3200) || defined (CONFIG_APCI_3300))
+#include "hwdrv_apci3200.c"
+#endif
+#ifdef CONFIG_APCI_1710
+#include "hwdrv_APCI1710.c"
+#endif
+#ifdef CONFIG_APCI_16XX
+#include "hwdrv_apci16xx.c"
+#endif
+#ifdef CONFIG_APCI_3XXX
+#include "hwdrv_apci3xxx.c"
+#endif
+
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO   11 /* Digital Input Output But TTL */
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(addi_apci_tbl) = {
+#ifdef CONFIG_APCI_3120
+       {APCI3120_BOARD_VENDOR_ID, 0x818D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1032
+       {APCI1032_BOARD_VENDOR_ID, 0x1003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1516
+       {APCI1516_BOARD_VENDOR_ID, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_2016
+       {APCI2016_BOARD_VENDOR_ID, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_2032
+       {APCI2032_BOARD_VENDOR_ID, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_2200
+       {APCI2200_BOARD_VENDOR_ID, 0x1005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1564
+       {APCI1564_BOARD_VENDOR_ID, 0x1006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1500
+       {APCI1500_BOARD_VENDOR_ID, 0x80fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3001
+       {APCI3120_BOARD_VENDOR_ID, 0x828D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3501
+       {APCI3501_BOARD_VENDOR_ID, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_035
+       {APCI035_BOARD_VENDOR_ID, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3200
+       {APCI3200_BOARD_VENDOR_ID, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3300
+       {APCI3200_BOARD_VENDOR_ID, 0x3007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1710
+       {APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_16XX
+       {0x15B8, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x100A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3XXX
+       {0x15B8, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x300F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x300E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x301A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x301B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x301C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x301D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x301E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x301F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x300B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0x15B8, 0x3024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+       {0}
+};
+
+MODULE_DEVICE_TABLE(pci, addi_apci_tbl);
+
+static const boardtype boardtypes[] = {
+#ifdef CONFIG_APCI_3120
+       {"apci3120",
+                       APCI3120_BOARD_VENDOR_ID,
+                       0x818D,
+                       AMCC_OP_REG_SIZE,
+                       APCI3120_ADDRESS_RANGE,
+                       8,
+                       0,
+                       ADDIDATA_NO_EEPROM,
+                       NULL,
+                       16,
+                       8,
+                       16,
+                       8,
+                       0xffff,
+                       0x3fff,
+                       &range_apci3120_ai,
+                       &range_apci3120_ao,
+                       4,
+                       4,
+                       0x0f,
+                       0,
+                       NULL,
+                       1,
+                       1,
+                       1,
+                       10000,
+                       100000,
+                       v_APCI3120_Interrupt,
+                       i_APCI3120_Reset,
+                       i_APCI3120_InsnConfigAnalogInput,
+                       i_APCI3120_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       i_APCI3120_CommandTestAnalogInput,
+                       i_APCI3120_CommandAnalogInput,
+                       i_APCI3120_StopCyclicAcquisition,
+                       NULL,
+                       i_APCI3120_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       i_APCI3120_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3120_InsnBitsDigitalInput,
+                       i_APCI3120_InsnConfigDigitalOutput,
+                       i_APCI3120_InsnWriteDigitalOutput,
+                       i_APCI3120_InsnBitsDigitalOutput,
+                       NULL,
+                       i_APCI3120_InsnConfigTimer,
+                       i_APCI3120_InsnWriteTimer,
+                       i_APCI3120_InsnReadTimer,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_1032
+       {"apci1032",
+                       APCI1032_BOARD_VENDOR_ID,
+                       0x1003,
+                       4,
+                       APCI1032_ADDRESS_RANGE,
+                       0,
+                       0,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_93C76,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       32,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       v_APCI1032_Interrupt,
+                       i_APCI1032_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI1032_ConfigDigitalInput,
+                       i_APCI1032_Read1DigitalInput,
+                       NULL,
+                       i_APCI1032_ReadMoreDigitalInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_1516
+       {"apci1516",
+                       APCI1516_BOARD_VENDOR_ID,
+                       0x1001,
+                       128,
+                       APCI1516_ADDRESS_RANGE,
+                       32,
+                       0,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_S5920,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       8,
+                       8,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       i_APCI1516_Reset,
+                       NULL, NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI1516_Read1DigitalInput,
+                       NULL,
+                       i_APCI1516_ReadMoreDigitalInput,
+                       i_APCI1516_ConfigDigitalOutput,
+                       i_APCI1516_WriteDigitalOutput,
+                       i_APCI1516_ReadDigitalOutput,
+                       NULL,
+                       i_APCI1516_ConfigWatchdog,
+                       i_APCI1516_StartStopWriteWatchdog,
+                       i_APCI1516_ReadWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_2016
+       {"apci2016",
+                       APCI2016_BOARD_VENDOR_ID,
+                       0x1002,
+                       128,
+                       APCI2016_ADDRESS_RANGE,
+                       32,
+                       0,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_S5920,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       0,
+                       16,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       i_APCI2016_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI2016_ConfigDigitalOutput,
+                       i_APCI2016_WriteDigitalOutput,
+                       i_APCI2016_BitsDigitalOutput,
+                       NULL,
+                       i_APCI2016_ConfigWatchdog,
+                       i_APCI2016_StartStopWriteWatchdog,
+                       i_APCI2016_ReadWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_2032
+       {"apci2032",
+                       APCI2032_BOARD_VENDOR_ID,
+                       0x1004,
+                       4,
+                       APCI2032_ADDRESS_RANGE,
+                       0,
+                       0,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_93C76,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       0,
+                       32,
+                       0xffffffff,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       0,
+                       0,
+                       v_APCI2032_Interrupt,
+                       i_APCI2032_Reset,
+                       NULL, NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI2032_ConfigDigitalOutput,
+                       i_APCI2032_WriteDigitalOutput,
+                       i_APCI2032_ReadDigitalOutput,
+                       i_APCI2032_ReadInterruptStatus,
+                       i_APCI2032_ConfigWatchdog,
+                       i_APCI2032_StartStopWriteWatchdog,
+                       i_APCI2032_ReadWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_2200
+       {"apci2200",
+                       APCI2200_BOARD_VENDOR_ID,
+                       0x1005,
+                       4,
+                       APCI2200_ADDRESS_RANGE,
+                       0,
+                       0,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_93C76,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       8,
+                       16,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       i_APCI2200_Reset,
+                       NULL, NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI2200_Read1DigitalInput,
+                       NULL,
+                       i_APCI2200_ReadMoreDigitalInput,
+                       i_APCI2200_ConfigDigitalOutput,
+                       i_APCI2200_WriteDigitalOutput,
+                       i_APCI2200_ReadDigitalOutput,
+                       NULL,
+                       i_APCI2200_ConfigWatchdog,
+                       i_APCI2200_StartStopWriteWatchdog,
+                       i_APCI2200_ReadWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_1564
+       {"apci1564",
+                       APCI1564_BOARD_VENDOR_ID,
+                       0x1006,
+                       128,
+                       APCI1564_ADDRESS_RANGE,
+                       0,
+                       0,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_93C76,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       32,
+                       32,
+                       0xffffffff,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       0,
+                       0,
+                       v_APCI1564_Interrupt,
+                       i_APCI1564_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI1564_ConfigDigitalInput,
+                       i_APCI1564_Read1DigitalInput,
+                       NULL,
+                       i_APCI1564_ReadMoreDigitalInput,
+                       i_APCI1564_ConfigDigitalOutput,
+                       i_APCI1564_WriteDigitalOutput,
+                       i_APCI1564_ReadDigitalOutput,
+                       i_APCI1564_ReadInterruptStatus,
+                       i_APCI1564_ConfigTimerCounterWatchdog,
+                       i_APCI1564_StartStopWriteTimerCounterWatchdog,
+                       i_APCI1564_ReadTimerCounterWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_1500
+       {"apci1500",
+                       APCI1500_BOARD_VENDOR_ID,
+                       0x80fc,
+                       128,
+                       APCI1500_ADDRESS_RANGE,
+                       4,
+                       0,
+                       ADDIDATA_NO_EEPROM,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       16,
+                       16,
+                       0xffff,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       0,
+                       0,
+                       v_APCI1500_Interrupt,
+                       i_APCI1500_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI1500_ConfigDigitalInputEvent,
+                       i_APCI1500_Initialisation,
+                       i_APCI1500_StartStopInputEvent,
+                       i_APCI1500_ReadMoreDigitalInput,
+                       i_APCI1500_ConfigDigitalOutputErrorInterrupt,
+                       i_APCI1500_WriteDigitalOutput,
+                       i_APCI1500_ConfigureInterrupt,
+                       NULL,
+                       i_APCI1500_ConfigCounterTimerWatchdog,
+                       i_APCI1500_StartStopTriggerTimerCounterWatchdog,
+                       i_APCI1500_ReadInterruptMask,
+                       i_APCI1500_ReadCounterTimerWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_3001
+       {"apci3001",
+                       APCI3120_BOARD_VENDOR_ID,
+                       0x828D,
+                       AMCC_OP_REG_SIZE,
+                       APCI3120_ADDRESS_RANGE,
+                       8,
+                       0,
+                       ADDIDATA_NO_EEPROM,
+                       NULL,
+                       16,
+                       8,
+                       16,
+                       0,
+                       0xfff,
+                       0,
+                       &range_apci3120_ai,
+                       NULL,
+                       4,
+                       4,
+                       0x0f,
+                       0,
+                       NULL,
+                       1,
+                       1,
+                       1,
+                       10000,
+                       100000,
+                       v_APCI3120_Interrupt,
+                       i_APCI3120_Reset,
+                       i_APCI3120_InsnConfigAnalogInput,
+                       i_APCI3120_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       i_APCI3120_CommandTestAnalogInput,
+                       i_APCI3120_CommandAnalogInput,
+                       i_APCI3120_StopCyclicAcquisition,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3120_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3120_InsnBitsDigitalInput,
+                       i_APCI3120_InsnConfigDigitalOutput,
+                       i_APCI3120_InsnWriteDigitalOutput,
+                       i_APCI3120_InsnBitsDigitalOutput,
+                       NULL,
+                       i_APCI3120_InsnConfigTimer,
+                       i_APCI3120_InsnWriteTimer,
+                       i_APCI3120_InsnReadTimer,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_3501
+       {"apci3501",
+                       APCI3501_BOARD_VENDOR_ID,
+                       0x3001,
+                       64,
+                       APCI3501_ADDRESS_RANGE,
+                       0,
+                       0,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_S5933,
+                       0,
+                       0,
+                       0,
+                       8,
+                       0,
+                       16383,
+                       NULL,
+                       &range_apci3501_ao,
+                       2,
+                       2,
+                       0x3,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       0,
+                       0,
+                       v_APCI3501_Interrupt,
+                       i_APCI3501_Reset,
+                       NULL, NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3501_ConfigAnalogOutput,
+                       i_APCI3501_WriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3501_ReadDigitalInput,
+                       i_APCI3501_ConfigDigitalOutput,
+                       i_APCI3501_WriteDigitalOutput,
+                       i_APCI3501_ReadDigitalOutput,
+                       NULL,
+                       i_APCI3501_ConfigTimerCounterWatchdog,
+                       i_APCI3501_StartStopWriteTimerCounterWatchdog,
+                       i_APCI3501_ReadTimerCounterWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_035
+       {"apci035",
+                       APCI035_BOARD_VENDOR_ID,
+                       0x0300,
+                       127,
+                       APCI035_ADDRESS_RANGE,
+                       0,
+                       0,
+                       1,
+                       ADDIDATA_S5920,
+                       16,
+                       8,
+                       16,
+                       0,
+                       0xff,
+                       0,
+                       &range_apci035_ai,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       1,
+                       0,
+                       10000,
+                       100000,
+                       v_APCI035_Interrupt,
+                       i_APCI035_Reset,
+                       i_APCI035_ConfigAnalogInput,
+                       i_APCI035_ReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI035_ConfigTimerWatchdog,
+                       i_APCI035_StartStopWriteTimerWatchdog,
+                       i_APCI035_ReadTimerWatchdog,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_3200
+       {"apci3200",
+                       APCI3200_BOARD_VENDOR_ID,
+                       0x3000,
+                       128,
+                       256,
+                       4,
+                       4,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_S5920,
+                       16,
+                       8,
+                       16,
+                       0,
+                       0x3ffff,
+                       0,
+                       &range_apci3200_ai,
+                       NULL,
+                       4,
+                       4,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       10000,
+                       100000,
+                       v_APCI3200_Interrupt,
+                       i_APCI3200_Reset,
+                       i_APCI3200_ConfigAnalogInput,
+                       i_APCI3200_ReadAnalogInput,
+                       i_APCI3200_InsnWriteReleaseAnalogInput,
+                       i_APCI3200_InsnBits_AnalogInput_Test,
+                       i_APCI3200_CommandTestAnalogInput,
+                       i_APCI3200_CommandAnalogInput,
+                       i_APCI3200_StopCyclicAcquisition,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3200_ReadDigitalInput,
+                       i_APCI3200_ConfigDigitalOutput,
+                       i_APCI3200_WriteDigitalOutput,
+                       i_APCI3200_ReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_3300
+       //Begin JK 20.10.2004: APCI-3300 integration
+       {"apci3300",
+                       APCI3200_BOARD_VENDOR_ID,
+                       0x3007,
+                       128,
+                       256,
+                       4,
+                       4,
+                       ADDIDATA_EEPROM,
+                       ADDIDATA_S5920,
+                       0,
+                       8,
+                       8,
+                       0,
+                       0x3ffff,
+                       0,
+                       &range_apci3300_ai,
+                       NULL,
+                       4,
+                       4,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       10000,
+                       100000,
+                       v_APCI3200_Interrupt,
+                       i_APCI3200_Reset,
+                       i_APCI3200_ConfigAnalogInput,
+                       i_APCI3200_ReadAnalogInput,
+                       i_APCI3200_InsnWriteReleaseAnalogInput,
+                       i_APCI3200_InsnBits_AnalogInput_Test,
+                       i_APCI3200_CommandTestAnalogInput,
+                       i_APCI3200_CommandAnalogInput,
+                       i_APCI3200_StopCyclicAcquisition,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3200_ReadDigitalInput,
+                       i_APCI3200_ConfigDigitalOutput,
+                       i_APCI3200_WriteDigitalOutput,
+                       i_APCI3200_ReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_1710
+       {"apci1710", APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID,
+                       128,
+                       8,
+                       256,
+                       0,
+                       ADDIDATA_NO_EEPROM,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       v_APCI1710_Interrupt,
+                       i_APCI1710_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+#endif
+#ifdef CONFIG_APCI_16XX
+       {"apci1648",
+                       0x15B8,
+                       0x1009,
+                       128,
+                       0,
+                       0,
+                       0,
+                       ADDIDATA_NO_EEPROM,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       48,
+                       &range_apci16xx_ttl,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       i_APCI16XX_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI16XX_InsnConfigInitTTLIO,
+                       i_APCI16XX_InsnBitsReadTTLIO,
+                       i_APCI16XX_InsnReadTTLIOAllPortValue,
+               i_APCI16XX_InsnBitsWriteTTLIO},
+
+       {"apci1696",
+                       0x15B8,
+                       0x100A,
+                       128,
+                       0,
+                       0,
+                       0,
+                       ADDIDATA_NO_EEPROM,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       96,
+                       &range_apci16xx_ttl,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       NULL,
+                       i_APCI16XX_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI16XX_InsnConfigInitTTLIO,
+                       i_APCI16XX_InsnBitsReadTTLIO,
+                       i_APCI16XX_InsnReadTTLIOAllPortValue,
+               i_APCI16XX_InsnBitsWriteTTLIO},
+#endif
+#ifdef CONFIG_APCI_3XXX
+       {"apci3000-16",
+                       0x15B8,
+                       0x3010,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       0,
+                       4095,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3000-8",
+                       0x15B8,
+                       0x300F,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       0,
+                       4095,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3000-4",
+                       0x15B8,
+                       0x300E,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       4,
+                       2,
+                       4,
+                       0,
+                       4095,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3006-16",
+                       0x15B8,
+                       0x3013,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3006-8",
+                       0x15B8,
+                       0x3014,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3006-4",
+                       0x15B8,
+                       0x3015,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       4,
+                       2,
+                       4,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3010-16",
+                       0x15B8,
+                       0x3016,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       0,
+                       4095,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3010-8",
+                       0x15B8,
+                       0x3017,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       0,
+                       4095,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3010-4",
+                       0x15B8,
+                       0x3018,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       4,
+                       2,
+                       4,
+                       0,
+                       4095,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3016-16",
+                       0x15B8,
+                       0x3019,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3016-8",
+                       0x15B8,
+                       0x301A,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3016-4",
+                       0x15B8,
+                       0x301B,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       4,
+                       2,
+                       4,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3100-16-4",
+                       0x15B8,
+                       0x301C,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       4,
+                       4095,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3100-8-4",
+                       0x15B8,
+                       0x301D,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       4,
+                       4095,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3106-16-4",
+                       0x15B8,
+                       0x301E,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       4,
+                       65535,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3106-8-4",
+                       0x15B8,
+                       0x301F,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       4,
+                       65535,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       10000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3110-16-4",
+                       0x15B8,
+                       0x3020,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       4,
+                       4095,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3110-8-4",
+                       0x15B8,
+                       0x3021,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       4,
+                       4095,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3116-16-4",
+                       0x15B8,
+                       0x3022,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       16,
+                       8,
+                       16,
+                       4,
+                       65535,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3116-8-4",
+                       0x15B8,
+                       0x3023,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       8,
+                       4,
+                       8,
+                       4,
+                       65535,
+                       4095,
+                       &range_apci3XXX_ai,
+                       &range_apci3XXX_ao,
+                       4,
+                       4,
+                       1,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+
+       {"apci3003",
+                       0x15B8,
+                       0x300B,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       0,
+                       4,
+                       4,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       7,
+                       2500,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+
+       {"apci3002-16",
+                       0x15B8,
+                       0x3002,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       0,
+                       16,
+                       16,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+
+       {"apci3002-8",
+                       0x15B8,
+                       0x3003,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       0,
+                       8,
+                       8,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+
+       {"apci3002-4",
+                       0x15B8,
+                       0x3004,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       0,
+                       4,
+                       4,
+                       0,
+                       65535,
+                       0,
+                       &range_apci3XXX_ai,
+                       NULL,
+                       4,
+                       4,
+                       1,
+                       0,
+                       NULL,
+                       0,
+                       0,
+                       6,
+                       5000,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       i_APCI3XXX_InsnConfigAnalogInput,
+                       i_APCI3XXX_InsnReadAnalogInput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnReadDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnBitsDigitalInput,
+                       NULL,
+                       i_APCI3XXX_InsnWriteDigitalOutput,
+                       i_APCI3XXX_InsnBitsDigitalOutput,
+                       i_APCI3XXX_InsnReadDigitalOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+               NULL},
+
+       {"apci3500",
+                       0x15B8,
+                       0x3024,
+                       256,
+                       256,
+                       256,
+                       256,
+                       ADDIDATA_NO_EEPROM,
+                       ADDIDATA_9054,
+                       0,
+                       0,
+                       0,
+                       4,
+                       0,
+                       4095,
+                       NULL,
+                       &range_apci3XXX_ao,
+                       0,
+                       0,
+                       0,
+                       24,
+                       &range_apci3XXX_ttl,
+                       0,
+                       0,
+                       0,
+                       0,
+                       0,
+                       v_APCI3XXX_Interrupt,
+                       i_APCI3XXX_Reset,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnWriteAnalogOutput,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       i_APCI3XXX_InsnConfigInitTTLIO,
+                       i_APCI3XXX_InsnBitsTTLIO,
+                       i_APCI3XXX_InsnReadTTLIO,
+               i_APCI3XXX_InsnWriteTTLIO},
+#endif
+};
+
+#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+
+comedi_driver driver_addi = {
+      driver_name:"addi_common",
+      module:THIS_MODULE,
+      attach:i_ADDI_Attach,
+      detach:i_ADDI_Detach,
+      num_names:n_boardtypes,
+      board_name:&boardtypes[0].pc_DriverName,
+      offset:sizeof(boardtype),
+};
+
+COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :static int i_ADDI_Attach(comedi_device *dev,            |
+|                                                                              comedi_devconfig *it)        |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :Detects the card.                                       |
+|                       Configure the driver for a particular board.            |
+|                       This function does all the initializations and memory   |
+|                       allocation of data structures for the driver.           |
++----------------------------------------------------------------------------+
+| Input Parameters  :comedi_device *dev                                                                                 |
+|                    comedi_devconfig *it                                                                       |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :  0                                                                    |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDI_Attach(comedi_device * dev, comedi_devconfig * it)
+{
+       comedi_subdevice *s;
+       int ret, pages, i, n_subdevices;
+       DWORD dw_Dummy;
+       resource_size_t io_addr[5];
+       unsigned int irq;
+       resource_size_t iobase_a, iobase_main, iobase_addon, iobase_reserved;
+       struct pcilst_struct *card = NULL;
+       unsigned char pci_bus, pci_slot, pci_func;
+       int i_Dma = 0;
+       static char c_Identifier[150];
+
+       sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
+               this_board->pc_DriverName);
+
+       if ((ret = alloc_private(dev, sizeof(addi_private))) < 0) {
+               return -ENOMEM;
+       }
+
+       if (!pci_list_builded) {
+               v_pci_card_list_init(this_board->i_VendorId, 1);        //1 for displaying the list..
+               pci_list_builded = 1;
+       }
+       //rt_printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName);
+
+       if ((this_board->i_Dma) && (it->options[2] == 0)) {
+               i_Dma = 1;
+       }
+
+       if ((card = ptr_select_and_alloc_pci_card(this_board->i_VendorId,
+                               this_board->i_DeviceId,
+                               it->options[0],
+                               it->options[1], i_Dma)) == NULL) {
+               return -EIO;
+       }
+       devpriv->allocated = 1;
+
+       if ((i_pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0],
+                               &irq)) < 0) {
+               i_pci_card_free(card);
+               printk(" - Can't get AMCC data!\n");
+               return -EIO;
+       }
+
+       iobase_a = io_addr[0];
+       iobase_main = io_addr[1];
+       iobase_addon = io_addr[2];
+       iobase_reserved = io_addr[3];
+       printk("\nBus %d: Slot %d: Funct%d\nBase0: 0x%8llx\nBase1: 0x%8llx\nBase2: 0x%8llx\nBase3: 0x%8llx\n", pci_bus, pci_slot, pci_func, (unsigned long long)io_addr[0], (unsigned long long)io_addr[1], (unsigned long long)io_addr[2], (unsigned long long)io_addr[3]);
+
+       if ((this_board->pc_EepromChip == NULL)
+               || (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) {
+          /************************************/
+               /* Test if more that 1 address used */
+          /************************************/
+
+               if (this_board->i_IorangeBase1 != 0) {
+                       dev->iobase = (unsigned long)iobase_main;       // DAQ base address...
+               } else {
+                       dev->iobase = (unsigned long)iobase_a;  // DAQ base address...
+               }
+
+               dev->board_name = this_board->pc_DriverName;
+               devpriv->amcc = card;
+               devpriv->iobase = (INT) dev->iobase;
+               devpriv->i_IobaseAmcc = (INT) iobase_a; //AMCC base address...
+               devpriv->i_IobaseAddon = (INT) iobase_addon;    //ADD ON base address....
+               devpriv->i_IobaseReserved = (INT) iobase_reserved;
+               devpriv->ps_BoardInfo = this_board;
+       } else {
+               dev->board_name = this_board->pc_DriverName;
+               dev->iobase = (unsigned long)io_addr[2];
+               devpriv->amcc = card;
+               devpriv->iobase = (INT) io_addr[2];
+               devpriv->ps_BoardInfo = this_board;
+               devpriv->i_IobaseReserved = (INT) io_addr[3];
+               printk("\nioremap begin");
+               devpriv->dw_AiBase =
+                       (ULONG_PTR) ioremap(io_addr[3],
+                       this_board->i_IorangeBase3);
+               printk("\nioremap end");
+       }
+
+       //##
+
+       if (irq > 0) {
+               if (comedi_request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
+                               c_Identifier, dev) < 0) {
+                       printk(", unable to allocate IRQ %u, DISABLING IT",
+                               irq);
+                       irq = 0;        /* Can't use IRQ */
+               } else {
+                       rt_printk("\nirq=%u", irq);
+               }
+       } else {
+               rt_printk(", IRQ disabled");
+       }
+
+       printk("\nOption %d %d %d\n", it->options[0], it->options[1],
+               it->options[2]);
+       dev->irq = irq;
+
+       // Read eepeom and fill boardtype Structure
+
+       if (this_board->i_PCIEeprom) {
+               printk("\nPCI Eeprom used");
+               if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
+                       // Set 3 wait stait
+                       if (!(strcmp(this_board->pc_DriverName, "apci035"))) {
+                               outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
+                       } else {
+                               outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
+                       }
+                       // Enable the interrupt for the controler
+                       dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
+                       outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
+                       printk("\nEnable the interrupt for the controler");
+               }
+               printk("\nRead Eeprom");
+               i_EepromReadMainHeader(io_addr[0], this_board->pc_EepromChip,
+                       dev);
+       } else {
+               printk("\nPCI Eeprom unused");
+       }
+
+       if (it->options[2] > 0) {
+               devpriv->us_UseDma = ADDI_DISABLE;
+       } else {
+               devpriv->us_UseDma = ADDI_ENABLE;
+       }
+
+       if (this_board->i_Dma) {
+               printk("\nDMA used");
+               if (devpriv->us_UseDma == ADDI_ENABLE) {
+                       // alloc DMA buffers
+                       devpriv->b_DmaDoubleBuffer = 0;
+                       for (i = 0; i < 2; i++) {
+                               for (pages = 4; pages >= 0; pages--) {
+                                       if ((devpriv->ul_DmaBufferVirtual[i] =
+                                                       (void *)
+                                                       __get_free_pages
+                                                       (GFP_KERNEL, pages))) {
+                                               break;
+                                       }
+                               }
+                               if (devpriv->ul_DmaBufferVirtual[i]) {
+                                       devpriv->ui_DmaBufferPages[i] = pages;
+                                       devpriv->ui_DmaBufferSize[i] =
+                                               PAGE_SIZE * pages;
+                                       devpriv->ui_DmaBufferSamples[i] =
+                                               devpriv->
+                                               ui_DmaBufferSize[i] >> 1;
+                                       devpriv->ul_DmaBufferHw[i] =
+                                               virt_to_bus((void *)devpriv->
+                                               ul_DmaBufferVirtual[i]);
+                               }
+                       }
+                       if (!devpriv->ul_DmaBufferVirtual[0]) {
+                               rt_printk
+                                       (", Can't allocate DMA buffer, DMA disabled!");
+                               devpriv->us_UseDma = ADDI_DISABLE;
+                       }
+
+                       if (devpriv->ul_DmaBufferVirtual[1]) {
+                               devpriv->b_DmaDoubleBuffer = 1;
+                       }
+               }
+
+               if ((devpriv->us_UseDma == ADDI_ENABLE)) {
+                       rt_printk("\nDMA ENABLED\n");
+               } else {
+                       printk("\nDMA DISABLED\n");
+               }
+       }
+
+       if (!strcmp(this_board->pc_DriverName, "apci1710")) {
+#ifdef CONFIG_APCI_1710
+               i_ADDI_AttachPCI1710(dev);
+
+               // save base address
+               devpriv->s_BoardInfos.ui_Address = io_addr[2];
+#endif
+       } else {
+               //Update-0.7.57->0.7.68dev->n_subdevices = 7;
+               n_subdevices = 7;
+               if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+                       return ret;
+
+               // Allocate and Initialise AI Subdevice Structures
+               s = dev->subdevices + 0;
+               if ((this_board->i_NbrAiChannel)
+                       || (this_board->i_NbrAiChannelDiff)) {
+                       dev->read_subdev = s;
+                       s->type = COMEDI_SUBD_AI;
+                       s->subdev_flags =
+                               SDF_READABLE | SDF_RT | SDF_COMMON | SDF_GROUND
+                               | SDF_DIFF;
+                       if (this_board->i_NbrAiChannel) {
+                               s->n_chan = this_board->i_NbrAiChannel;
+                               devpriv->b_SingelDiff = 0;
+                       } else {
+                               s->n_chan = this_board->i_NbrAiChannelDiff;
+                               devpriv->b_SingelDiff = 1;
+                       }
+                       s->maxdata = this_board->i_AiMaxdata;
+                       s->len_chanlist = this_board->i_AiChannelList;
+                       s->range_table = this_board->pr_AiRangelist;
+
+                       /* Set the initialisation flag */
+                       devpriv->b_AiInitialisation = 1;
+
+                       s->insn_config =
+                               this_board->i_hwdrv_InsnConfigAnalogInput;
+                       s->insn_read = this_board->i_hwdrv_InsnReadAnalogInput;
+                       s->insn_write =
+                               this_board->i_hwdrv_InsnWriteAnalogInput;
+                       s->insn_bits = this_board->i_hwdrv_InsnBitsAnalogInput;
+                       s->do_cmdtest =
+                               this_board->i_hwdrv_CommandTestAnalogInput;
+                       s->do_cmd = this_board->i_hwdrv_CommandAnalogInput;
+                       s->cancel = this_board->i_hwdrv_CancelAnalogInput;
+
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+
+               // Allocate and Initialise AO Subdevice Structures
+               s = dev->subdevices + 1;
+               if (this_board->i_NbrAoChannel) {
+                       s->type = COMEDI_SUBD_AO;
+                       s->subdev_flags =
+                               SDF_WRITEABLE | SDF_GROUND | SDF_COMMON |
+                               SDF_RT;
+                       s->n_chan = this_board->i_NbrAoChannel;
+                       s->maxdata = this_board->i_AoMaxdata;
+                       s->len_chanlist = this_board->i_NbrAoChannel;
+                       s->range_table = this_board->pr_AoRangelist;
+                       s->insn_config =
+                               this_board->i_hwdrv_InsnConfigAnalogOutput;
+                       s->insn_write =
+                               this_board->i_hwdrv_InsnWriteAnalogOutput;
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+               // Allocate and Initialise DI Subdevice Structures
+               s = dev->subdevices + 2;
+               if (this_board->i_NbrDiChannel) {
+                       s->type = COMEDI_SUBD_DI;
+                       s->subdev_flags =
+                               SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+                       s->n_chan = this_board->i_NbrDiChannel;
+                       s->maxdata = 1;
+                       s->len_chanlist = this_board->i_NbrDiChannel;
+                       s->range_table = &range_digital;
+                       s->io_bits = 0; /* all bits input */
+                       s->insn_config =
+                               this_board->i_hwdrv_InsnConfigDigitalInput;
+                       s->insn_read = this_board->i_hwdrv_InsnReadDigitalInput;
+                       s->insn_write =
+                               this_board->i_hwdrv_InsnWriteDigitalInput;
+                       s->insn_bits = this_board->i_hwdrv_InsnBitsDigitalInput;
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+               // Allocate and Initialise DO Subdevice Structures
+               s = dev->subdevices + 3;
+               if (this_board->i_NbrDoChannel) {
+                       s->type = COMEDI_SUBD_DO;
+                       s->subdev_flags =
+                               SDF_READABLE | SDF_WRITEABLE | SDF_RT |
+                               SDF_GROUND | SDF_COMMON;
+                       s->n_chan = this_board->i_NbrDoChannel;
+                       s->maxdata = this_board->i_DoMaxdata;
+                       s->len_chanlist = this_board->i_NbrDoChannel;
+                       s->range_table = &range_digital;
+                       s->io_bits = 0xf;       /* all bits output */
+
+                       s->insn_config = this_board->i_hwdrv_InsnConfigDigitalOutput;   //for digital output memory..
+                       s->insn_write =
+                               this_board->i_hwdrv_InsnWriteDigitalOutput;
+                       s->insn_bits =
+                               this_board->i_hwdrv_InsnBitsDigitalOutput;
+                       s->insn_read =
+                               this_board->i_hwdrv_InsnReadDigitalOutput;
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+
+               // Allocate and Initialise Timer Subdevice Structures
+               s = dev->subdevices + 4;
+               if (this_board->i_Timer) {
+                       s->type = COMEDI_SUBD_TIMER;
+                       s->subdev_flags =
+                               SDF_WRITEABLE | SDF_RT | SDF_GROUND |
+                               SDF_COMMON;
+                       s->n_chan = 1;
+                       s->maxdata = 0;
+                       s->len_chanlist = 1;
+                       s->range_table = &range_digital;
+
+                       s->insn_write = this_board->i_hwdrv_InsnWriteTimer;
+                       s->insn_read = this_board->i_hwdrv_InsnReadTimer;
+                       s->insn_config = this_board->i_hwdrv_InsnConfigTimer;
+                       s->insn_bits = this_board->i_hwdrv_InsnBitsTimer;
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+
+               // Allocate and Initialise TTL
+               s = dev->subdevices + 5;
+               if (this_board->i_NbrTTLChannel) {
+                       s->type = COMEDI_SUBD_TTLIO;
+                       s->subdev_flags =
+                               SDF_WRITEABLE | SDF_READABLE | SDF_RT |
+                               SDF_GROUND | SDF_COMMON;
+                       s->n_chan = this_board->i_NbrTTLChannel;
+                       s->maxdata = 1;
+                       s->io_bits = 0; /* all bits input */
+                       s->len_chanlist = this_board->i_NbrTTLChannel;
+                       s->range_table = &range_digital;
+                       s->insn_config = this_board->i_hwdr_ConfigInitTTLIO;
+                       s->insn_bits = this_board->i_hwdr_ReadTTLIOBits;
+                       s->insn_read = this_board->i_hwdr_ReadTTLIOAllPortValue;
+                       s->insn_write = this_board->i_hwdr_WriteTTLIOChlOnOff;
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+
+               /* EEPROM */
+               s = dev->subdevices + 6;
+               if (this_board->i_PCIEeprom) {
+                       s->type = COMEDI_SUBD_MEMORY;
+                       s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
+                       s->n_chan = 256;
+                       s->maxdata = 0xffff;
+                       s->insn_read = i_ADDIDATA_InsnReadEeprom;
+               } else {
+                       s->type = COMEDI_SUBD_UNUSED;
+               }
+       }
+
+       printk("\ni_ADDI_Attach end\n");
+       i_ADDI_Reset(dev);
+       devpriv->b_ValidDriver = 1;
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : static int i_ADDI_Detach(comedi_device *dev)           |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Deallocates resources of the addi_common driver        |
+|                        Free the DMA buffers, unregister irq.                              |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                     |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDI_Detach(comedi_device * dev)
+{
+
+       if (dev->private) {
+               if (devpriv->b_ValidDriver) {
+                       i_ADDI_Reset(dev);
+               }
+
+               if (dev->irq) {
+                       comedi_free_irq(dev->irq, dev);
+               }
+
+               if ((devpriv->ps_BoardInfo->pc_EepromChip == NULL)
+                       || (strcmp(devpriv->ps_BoardInfo->pc_EepromChip,
+                                       ADDIDATA_9054) != 0)) {
+                       if (devpriv->allocated) {
+                               i_pci_card_free(devpriv->amcc);
+                       }
+
+                       if (devpriv->ul_DmaBufferVirtual[0]) {
+                               free_pages((unsigned long)devpriv->
+                                       ul_DmaBufferVirtual[0],
+                                       devpriv->ui_DmaBufferPages[0]);
+                       }
+
+                       if (devpriv->ul_DmaBufferVirtual[1]) {
+                               free_pages((unsigned long)devpriv->
+                                       ul_DmaBufferVirtual[1],
+                                       devpriv->ui_DmaBufferPages[1]);
+                       }
+               } else {
+                       iounmap((void *)devpriv->dw_AiBase);
+
+                       if (devpriv->allocated) {
+                               i_pci_card_free(devpriv->amcc);
+                       }
+               }
+
+               if (pci_list_builded) {
+                       //v_pci_card_list_cleanup(PCI_VENDOR_ID_AMCC);
+                       v_pci_card_list_cleanup(this_board->i_VendorId);
+                       pci_list_builded = 0;
+               }
+       }
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : static int i_ADDI_Reset(comedi_device *dev)                       |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Disables all interrupts, Resets digital output to low, |
+|                              Set all analog output to low                                             |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                         |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDI_Reset(comedi_device * dev)
+{
+
+       this_board->i_hwdrv_Reset(dev);
+       return 0;
+}
+
+// Interrupt function
+/*
++----------------------------------------------------------------------------+
+| Function name     :                                                        |
+|static void v_ADDI_Interrupt(int irq, void *d  PT_REGS_ARG)                 |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Registerd interrupt routine                                                   |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :  int irq                                                                                          |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+{
+       comedi_device *dev = d;
+       this_board->v_hwdrv_Interrupt(irq, d);
+       return IRQ_RETVAL(1);
+}
+
+// EEPROM Read Function
+/*
++----------------------------------------------------------------------------+
+| Function name     :                                                        |
+|INT i_ADDIDATA_InsnReadEeprom(comedi_device *dev,comedi_subdevice *s,
+                                                       comedi_insn *insn,lsampl_t *data)
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Read 256 words from EEPROM                                            |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :(comedi_device *dev,comedi_subdevice *s,
+                       comedi_insn *insn,lsampl_t *data)                                                |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDIDATA_InsnReadEeprom(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       WORD w_Data;
+       WORD w_Address;
+       w_Address = CR_CHAN(insn->chanspec);    // address to be read as 0,1,2,3...255
+
+       w_Data = w_EepromReadWord(devpriv->i_IobaseAmcc,
+               this_board->pc_EepromChip, 0x100 + (2 * w_Address));
+       data[0] = w_Data;
+       //multiplied by 2 bcozinput will be like 0,1,2...255
+       return insn->n;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
new file mode 100644 (file)
index 0000000..b86010c
--- /dev/null
@@ -0,0 +1,482 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project   : ADDI-DATA        | Compiler : GCC                        |
+  | Modulname : addi_common.h     | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description : ADDI COMMON Header File                                 |
+  +-----------------------------------------------------------------------+
+*/
+
+//including header files
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+//#include <linux/malloc.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include "../../comedidev.h"
+#include "addi_amcc_s5933.h"
+#include <linux/kmod.h>
+#include <asm/uaccess.h>
+
+#define ERROR  -1
+#define SUCCESS 1
+
+// variable type definition
+
+typedef void VOID, *PVOID;
+typedef char CHAR, *PCHAR;
+typedef const CHAR *PCSTR;
+typedef unsigned char BYTE, *PBYTE;
+typedef short SHORT, *PSHORT;
+typedef unsigned short USHORT, *PUSHORT;
+typedef unsigned short WORD, *PWORD;
+typedef int INT, *PINT;;
+typedef unsigned int UINT, *PUINT;
+typedef int LONG, *PLONG;      /* 32-bit */
+typedef unsigned int ULONG, *PULONG;   /* 32-bit */
+typedef unsigned int DWORD, *PDWORD;   /* 32-bit */
+typedef unsigned long ULONG_PTR;
+
+typedef const comedi_lrange *PCRANGE;
+#define LOBYTE(W)                                                               (BYTE         )((W)&0xFF)
+#define HIBYTE(W)                                (BYTE         )(((W)>>8)&0xFF)
+#define MAKEWORD(H,L)                            (USHORT       )((L)|( (H)<<8) )
+#define LOWORD(W)                                                               (USHORT       )((W)&0xFFFF)
+#define HIWORD(W)                                (USHORT       )(((W)>>16)&0xFFFF)
+#define MAKEDWORD(H,L)                                                 (UINT         )((L)|( (H)<<16) )
+
+#define ADDI_ENABLE   1
+#define ADDI_DISABLE  0
+#define APCI1710_SAVE_INTERRUPT 1
+
+#define ADDIDATA_EEPROM          1
+#define ADDIDATA_NO_EEPROM    0
+#define ADDIDATA_93C76        "93C76"
+#define ADDIDATA_S5920        "S5920"
+#define ADDIDATA_S5933        "S5933"
+#define ADDIDATA_9054         "9054"
+
+//ADDIDATA Enable Disable
+#define ADDIDATA_ENABLE                            1
+#define ADDIDATA_DISABLE                           0
+
+// Structures
+// structure for the boardtype
+typedef struct {
+
+       PCSTR pc_DriverName;    // driver name
+       INT i_VendorId;         //PCI vendor a device ID of card
+       INT i_DeviceId;
+       INT i_IorangeBase0;
+       INT i_IorangeBase1;
+       INT i_IorangeBase2;     //  base 2 range
+       INT i_IorangeBase3;     //  base 3 range
+       INT i_PCIEeprom;        // eeprom present or not
+       PCHAR pc_EepromChip;    // type of chip
+       INT i_NbrAiChannel;     // num of A/D chans
+       INT i_NbrAiChannelDiff; // num of A/D chans in diff mode
+       INT i_AiChannelList;    // len of chanlist
+       INT i_NbrAoChannel;     // num of D/A chans
+       INT i_AiMaxdata;        // resolution of A/D
+       INT i_AoMaxdata;        // resolution of D/A
+       PCRANGE pr_AiRangelist; // rangelist for A/D
+       PCRANGE pr_AoRangelist; // rangelist for D/A
+
+       INT i_NbrDiChannel;     // Number of DI channels
+       INT i_NbrDoChannel;     // Number of DO channels
+       INT i_DoMaxdata;        // data to set all chanels high
+
+       INT i_NbrTTLChannel;    // Number of TTL channels
+       PCRANGE pr_TTLRangelist;        // rangelist for TTL
+
+       INT i_Dma;              // dma present or not
+       INT i_Timer;            //   timer subdevice present or not
+       BYTE b_AvailableConvertUnit;
+       UINT ui_MinAcquisitiontimeNs;   // Minimum Acquisition in Nano secs
+       UINT ui_MinDelaytimeNs; // Minimum Delay in Nano secs
+
+// interrupt and reset
+       void (*v_hwdrv_Interrupt) (int irq, void *d);
+       int (*i_hwdrv_Reset) (comedi_device * dev);
+
+//Subdevice functions
+//ANALOG INPUT
+
+       int (*i_hwdrv_InsnConfigAnalogInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnReadAnalogInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnWriteAnalogInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnBitsAnalogInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_CommandTestAnalogInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_cmd * cmd);
+       int (*i_hwdrv_CommandAnalogInput) (comedi_device * dev,
+               comedi_subdevice * s);
+       int (*i_hwdrv_CancelAnalogInput) (comedi_device * dev,
+               comedi_subdevice * s);
+
+//Analog Output
+       int (*i_hwdrv_InsnConfigAnalogOutput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnWriteAnalogOutput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnBitsAnalogOutput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+//Digital Input
+       int (*i_hwdrv_InsnConfigDigitalInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnReadDigitalInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnWriteDigitalInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnBitsDigitalInput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+//Digital Output
+       int (*i_hwdrv_InsnConfigDigitalOutput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnWriteDigitalOutput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnBitsDigitalOutput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnReadDigitalOutput) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+//TIMER
+       int (*i_hwdrv_InsnConfigTimer) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnWriteTimer) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnReadTimer) (comedi_device * dev, comedi_subdevice * s,
+               comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdrv_InsnBitsTimer) (comedi_device * dev, comedi_subdevice * s,
+               comedi_insn * insn, lsampl_t * data);
+
+//TTL IO
+       int (*i_hwdr_ConfigInitTTLIO) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdr_ReadTTLIOBits) (comedi_device * dev, comedi_subdevice * s,
+               comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdr_ReadTTLIOAllPortValue) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+       int (*i_hwdr_WriteTTLIOChlOnOff) (comedi_device * dev,
+               comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+} boardtype;
+
+//MODULE INFO STRUCTURE
+
+typedef union {
+      /*****************************/
+       /* Incremental counter infos */
+      /*****************************/
+
+       struct {
+               union {
+                       struct {
+                               BYTE b_ModeRegister1;
+                               BYTE b_ModeRegister2;
+                               BYTE b_ModeRegister3;
+                               BYTE b_ModeRegister4;
+                       } s_ByteModeRegister;
+                       DWORD dw_ModeRegister1_2_3_4;
+               } s_ModeRegister;
+
+               struct {
+                       unsigned int b_IndexInit:1;
+                       unsigned int b_CounterInit:1;
+                       unsigned int b_ReferenceInit:1;
+                       unsigned int b_IndexInterruptOccur:1;
+                       unsigned int b_CompareLogicInit:1;
+                       unsigned int b_FrequencyMeasurementInit:1;
+                       unsigned int b_FrequencyMeasurementEnable:1;
+               } s_InitFlag;
+
+       } s_SiemensCounterInfo;
+
+      /*************/
+       /* SSI infos */
+      /*************/
+
+       struct {
+               BYTE b_SSIProfile;
+               BYTE b_PositionTurnLength;
+               BYTE b_TurnCptLength;
+               BYTE b_SSIInit;
+       } s_SSICounterInfo;
+
+      /*****************/
+       /* TTL I/O infos */
+      /*****************/
+
+       struct {
+               BYTE b_TTLInit;
+               BYTE b_PortConfiguration[4];
+       } s_TTLIOInfo;
+
+      /*********************/
+       /* Digital I/O infos */
+      /*********************/
+
+       struct {
+               BYTE b_DigitalInit;
+               BYTE b_ChannelAMode;
+               BYTE b_ChannelBMode;
+               BYTE b_OutputMemoryEnabled;
+               DWORD dw_OutputMemory;
+       } s_DigitalIOInfo;
+
+      /*********************/
+       /* 82X54 timer infos */
+      /*********************/
+
+       struct {
+               struct {
+                       BYTE b_82X54Init;
+                       BYTE b_InputClockSelection;
+                       BYTE b_InputClockLevel;
+                       BYTE b_OutputLevel;
+                       BYTE b_HardwareGateLevel;
+                       DWORD dw_ConfigurationWord;
+               } s_82X54TimerInfo[3];
+               BYTE b_InterruptMask;
+       } s_82X54ModuleInfo;
+
+      /*********************/
+       /* Chronometer infos */
+      /*********************/
+
+       struct {
+               BYTE b_ChronoInit;
+               BYTE b_InterruptMask;
+               BYTE b_PCIInputClock;
+               BYTE b_TimingUnit;
+               BYTE b_CycleMode;
+               double d_TimingInterval;
+               DWORD dw_ConfigReg;
+       } s_ChronoModuleInfo;
+
+      /***********************/
+       /* Pulse encoder infos */
+      /***********************/
+
+       struct {
+               struct {
+                       BYTE b_PulseEncoderInit;
+               } s_PulseEncoderInfo[4];
+               DWORD dw_SetRegister;
+               DWORD dw_ControlRegister;
+               DWORD dw_StatusRegister;
+       } s_PulseEncoderModuleInfo;
+
+      /********************/
+       /* Tor conter infos */
+      /********************/
+
+       struct {
+               struct {
+                       BYTE b_TorCounterInit;
+                       BYTE b_TimingUnit;
+                       BYTE b_InterruptEnable;
+                       double d_TimingInterval;
+                       ULONG ul_RealTimingInterval;
+               } s_TorCounterInfo[2];
+               BYTE b_PCIInputClock;
+       } s_TorCounterModuleInfo;
+
+      /*************/
+       /* PWM infos */
+      /*************/
+
+       struct {
+               struct {
+                       BYTE b_PWMInit;
+                       BYTE b_TimingUnit;
+                       BYTE b_InterruptEnable;
+                       double d_LowTiming;
+                       double d_HighTiming;
+                       ULONG ul_RealLowTiming;
+                       ULONG ul_RealHighTiming;
+               } s_PWMInfo[2];
+               BYTE b_ClockSelection;
+       } s_PWMModuleInfo;
+
+      /*************/
+       /* ETM infos */
+      /*************/
+
+       struct {
+               struct {
+                       BYTE b_ETMEnable;
+                       BYTE b_ETMInterrupt;
+               } s_ETMInfo[2];
+               BYTE b_ETMInit;
+               BYTE b_TimingUnit;
+               BYTE b_ClockSelection;
+               double d_TimingInterval;
+               ULONG ul_Timing;
+       } s_ETMModuleInfo;
+
+      /*************/
+       /* CDA infos */
+      /*************/
+
+       struct {
+               BYTE b_CDAEnable;
+               BYTE b_CDAInterrupt;
+               BYTE b_CDAInit;
+               BYTE b_FctSelection;
+               BYTE b_CDAReadFIFOOverflow;
+       } s_CDAModuleInfo;
+
+} str_ModuleInfo;
+// Private structure for the addi_apci3120 driver
+
+typedef struct {
+
+       INT iobase;
+       INT i_IobaseAmcc;       // base+size for AMCC chip
+       INT i_IobaseAddon;      //addon base address
+       INT i_IobaseReserved;
+       ULONG_PTR dw_AiBase;
+       struct pcilst_struct *amcc;     // ptr too AMCC data
+       BYTE allocated;         // we have blocked card
+       BYTE b_ValidDriver;     // driver is ok
+       BYTE b_AiContinuous;    // we do unlimited AI
+       BYTE b_AiInitialisation;
+       UINT ui_AiActualScan;   //how many scans we finished
+       UINT ui_AiBufferPtr;    // data buffer ptr in samples
+       UINT ui_AiNbrofChannels;        // how many channels is measured
+       UINT ui_AiScanLength;   // Length of actual scanlist
+       UINT ui_AiActualScanPosition;   // position in actual scan
+       PUINT pui_AiChannelList;        // actual chanlist
+       UINT ui_AiChannelList[32];      // actual chanlist
+       BYTE b_AiChannelConfiguration[32];      // actual chanlist
+       UINT ui_AiReadData[32];
+       DWORD dw_AiInitialised;
+       UINT ui_AiTimer0;       //Timer Constant for Timer0
+       UINT ui_AiTimer1;       //Timer constant for Timer1
+       UINT ui_AiFlags;
+       UINT ui_AiDataLength;
+       sampl_t *AiData;        // Pointer to sample data
+       UINT ui_AiNbrofScans;   // number of scans to do
+       USHORT us_UseDma;       // To use Dma or not
+       BYTE b_DmaDoubleBuffer; // we can use double buffering
+       UINT ui_DmaActualBuffer;        // which buffer is used now
+       //*UPDATE-0.7.57->0.7.68
+       //ULONG               ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer
+       sampl_t *ul_DmaBufferVirtual[2];        // pointers to begin of DMA buffer
+       ULONG ul_DmaBufferHw[2];        // hw address of DMA buff
+       UINT ui_DmaBufferSize[2];       // size of dma buffer in bytes
+       UINT ui_DmaBufferUsesize[2];    // which size we may now used for transfer
+       UINT ui_DmaBufferSamples[2];    // size in samples
+       UINT ui_DmaBufferPages[2];      // number of pages in buffer
+       BYTE b_DigitalOutputRegister;   // Digital Output Register
+       BYTE b_OutputMemoryStatus;
+       BYTE b_AnalogInputChannelNbr;   // Analog input channel Nbr
+       BYTE b_AnalogOutputChannelNbr;  // Analog input Output  Nbr
+       BYTE b_TimerSelectMode; // Contain data written at iobase + 0C
+       BYTE b_ModeSelectRegister;      // Contain data written at iobase + 0E
+       USHORT us_OutputRegister;       // Contain data written at iobase + 0
+       BYTE b_InterruptState;
+       BYTE b_TimerInit;       // Specify if InitTimerWatchdog was load
+       BYTE b_TimerStarted;    // Specify if timer 2 is running or not
+       BYTE b_Timer2Mode;      // Specify the timer 2 mode
+       BYTE b_Timer2Interrupt; //Timer2  interrupt enable or disable
+       BYTE b_AiCyclicAcquisition;     // indicate cyclic acquisition
+       BYTE b_InterruptMode;   // eoc eos or dma
+       BYTE b_EocEosInterrupt; // Enable disable eoc eos interrupt
+       UINT ui_EocEosConversionTime;
+       BYTE b_EocEosConversionTimeBase;
+       BYTE b_SingelDiff;
+       BYTE b_ExttrigEnable;   //  To enable or disable external trigger
+
+       struct task_struct *tsk_Current;        // Pointer to the current process
+       boardtype *ps_BoardInfo;
+
+       // Hardware board infos for 1710
+
+       struct {
+               UINT ui_Address;        // Board address
+               UINT ui_FlashAddress;
+               BYTE b_InterruptNbr;    // Board interrupt number
+               BYTE b_SlotNumber;      // PCI slot number
+               BYTE b_BoardVersion;
+               DWORD dw_MolduleConfiguration[4];       // Module configuration
+       } s_BoardInfos;
+
+           /*******************/
+       /* Interrupt infos */
+          /*******************/
+
+       struct {
+               ULONG ul_InterruptOccur;        /* 0   : No interrupt occur  */
+               /* > 0 : Interrupt occur     */
+               UINT ui_Read;   /* Read FIFO                 */
+               UINT ui_Write;  /* Write FIFO                */
+               struct {
+                       BYTE b_OldModuleMask;
+                       ULONG ul_OldInterruptMask;      /* Interrupt mask          */
+                       ULONG ul_OldCounterLatchValue;  /* Interrupt counter value */
+               } s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
+       } s_InterruptParameters;
+
+       str_ModuleInfo s_ModuleInfo[4];
+       ULONG ul_TTLPortConfiguration[10];
+
+} addi_private;
+
+static unsigned short pci_list_builded = 0;    /* set to 1 when list of card is known */
+
+//Function declarations
+
+static int i_ADDI_Attach(comedi_device * dev, comedi_devconfig * it);
+static int i_ADDI_Detach(comedi_device * dev);
+static int i_ADDI_Reset(comedi_device * dev);
+
+static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG);
+static int i_ADDIDATA_InsnReadEeprom(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
new file mode 100644 (file)
index 0000000..b8fa5c9
--- /dev/null
@@ -0,0 +1,1158 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project   : ADDI DATA         | Compiler : GCC                                   |
+  | Modulname : addi_eeprom.c     | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
+  +-----------------------------------------------------------------------+
+  | Description : ADDI EEPROM  Module                                     |
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |                  |                                                |
+  |          |           |                                               |
+  +----------+-----------+------------------------------------------------+
+*/
+
+#define NVCMD_BEGIN_READ       (0x7 << 5 )     // nvRam begin read command
+#define NVCMD_LOAD_LOW         (0x4 << 5 )     // nvRam load low command
+#define NVCMD_LOAD_HIGH        (0x5 << 5 )     // nvRam load high command
+#define EE76_CMD_LEN           13      // bits in instructions
+#define EE_READ                0x0180  // 01 1000 0000 read instruction
+
+#define        WORD                            unsigned short
+#define PWORD                          unsigned short *
+#define PDWORD                         unsigned int  *
+
+#ifndef DWORD
+#define        DWORD                           unsigned int
+#endif
+
+#define EEPROM_DIGITALINPUT                    0
+#define EEPROM_DIGITALOUTPUT                   1
+#define EEPROM_ANALOGINPUT                             2
+#define EEPROM_ANALOGOUTPUT                            3
+#define EEPROM_TIMER                                   4
+#define EEPROM_WATCHDOG                                        5
+#define EEPROM_TIMER_WATCHDOG_COUNTER  10
+
+struct str_Functionality {
+       BYTE b_Type;
+       WORD w_Address;
+};
+
+typedef struct {
+       WORD w_HeaderSize;
+       BYTE b_Nfunctions;
+       struct str_Functionality s_Functions[7];
+} str_MainHeader;
+
+typedef struct {
+       WORD w_Nchannel;
+       BYTE b_Interruptible;
+       WORD w_NinterruptLogic;
+} str_DigitalInputHeader;
+
+typedef struct {
+       WORD w_Nchannel;
+} str_DigitalOutputHeader;
+
+// used for timer as well as watchdog
+
+typedef struct {
+       WORD w_HeaderSize;
+       BYTE b_Resolution;
+       BYTE b_Mode;            // in case of Watchdog it is functionality
+       WORD w_MinTiming;
+       BYTE b_TimeBase;
+} str_TimerDetails;
+typedef struct {
+
+       WORD w_Ntimer;
+       str_TimerDetails s_TimerDetails[4];     //  supports 4 timers
+} str_TimerMainHeader;
+
+typedef struct {
+       WORD w_Nchannel;
+       BYTE b_Resolution;
+} str_AnalogOutputHeader;
+
+typedef struct {
+       WORD w_Nchannel;
+       WORD w_MinConvertTiming;
+       WORD w_MinDelayTiming;
+       BYTE b_HasDma;
+       BYTE b_Resolution;
+} str_AnalogInputHeader;
+
+               /*****************************************/
+               /*            Read Header Functions              */
+               /*****************************************/
+
+INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, comedi_device * dev);
+
+INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_DigitalInputHeader * s_Header);
+
+INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_DigitalOutputHeader * s_Header);
+
+INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_TimerMainHeader * s_Header);
+
+INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_AnalogOutputHeader * s_Header);
+
+INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_AnalogInputHeader * s_Header);
+
+               /******************************************/
+               /*      Eeprom Specific Functions                         */
+               /******************************************/
+WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, PCHAR pc_PCIChipInformation,
+       WORD w_EepromStartAddress);
+VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+VOID v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
+VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+VOID v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+       BYTE b_DataLengthInBits);
+VOID v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : WORD w_EepromReadWord                                  |
+|                              (WORD   w_PCIBoardEepromAddress,                         |
+|                               PCHAR  pc_PCIChipInformation,                           |
+|                               WORD   w_EepromStartAddress)                            |
++----------------------------------------------------------------------------+
+| Task              : Read from eepromn a word                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+|                                                                                                                                       |
+|                    PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+|                                                                                                                                       |
+|                    WORD w_EepromStartAddress    : Selected eeprom address |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : Read word value from eeprom                            |
++----------------------------------------------------------------------------+
+*/
+
+WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, PCHAR pc_PCIChipInformation,
+       WORD w_EepromStartAddress)
+{
+
+       BYTE b_Counter = 0;
+
+       BYTE b_ReadByte = 0;
+
+       BYTE b_ReadLowByte = 0;
+
+       BYTE b_ReadHighByte = 0;
+
+       BYTE b_SelectedAddressLow = 0;
+
+       BYTE b_SelectedAddressHigh = 0;
+
+       WORD w_ReadWord = 0;
+
+       /**************************/
+
+       /* Test the PCI chip type */
+
+       /**************************/
+
+       if ((!strcmp(pc_PCIChipInformation, "S5920")) ||
+               (!strcmp(pc_PCIChipInformation, "S5933")))
+       {
+
+               for (b_Counter = 0; b_Counter < 2; b_Counter++)
+               {
+
+                       b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256;        //Read the low 8 bit part
+
+                       b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256;       //Read the high 8 bit part
+
+             /************************************/
+
+                       /* Select the load low address mode */
+
+             /************************************/
+
+                       outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F);
+
+             /****************/
+
+                       /* Wait on busy */
+
+             /****************/
+
+                       v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+             /************************/
+
+                       /* Load the low address */
+
+             /************************/
+
+                       outb(b_SelectedAddressLow,
+                               w_PCIBoardEepromAddress + 0x3E);
+
+             /****************/
+
+                       /* Wait on busy */
+
+             /****************/
+
+                       v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+             /*************************************/
+
+                       /* Select the load high address mode */
+
+             /*************************************/
+
+                       outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F);
+
+             /****************/
+
+                       /* Wait on busy */
+
+             /****************/
+
+                       v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+             /*************************/
+
+                       /* Load the high address */
+
+             /*************************/
+
+                       outb(b_SelectedAddressHigh,
+                               w_PCIBoardEepromAddress + 0x3E);
+
+             /****************/
+
+                       /* Wait on busy */
+
+             /****************/
+
+                       v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+             /************************/
+
+                       /* Select the READ mode */
+
+             /************************/
+
+                       outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F);
+
+             /****************/
+
+                       /* Wait on busy */
+
+             /****************/
+
+                       v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+             /*****************************/
+
+                       /* Read data into the EEPROM */
+
+             /*****************************/
+
+                       b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E);
+
+             /****************/
+
+                       /* Wait on busy */
+
+             /****************/
+
+                       v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+             /*********************************/
+
+                       /* Select the upper address part */
+
+             /*********************************/
+
+                       if (b_Counter == 0)
+                       {
+
+                               b_ReadLowByte = b_ReadByte;
+
+                       }       // if(b_Counter==0)
+
+                       else
+                       {
+
+                               b_ReadHighByte = b_ReadByte;
+
+                       }       // if(b_Counter==0)
+
+               }               // for (b_Counter=0; b_Counter<2; b_Counter++)
+
+               w_ReadWord = (b_ReadLowByte | (((WORD) b_ReadHighByte) * 256));
+
+       }                       // end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933")))
+
+       if (!strcmp(pc_PCIChipInformation, "93C76"))
+       {
+
+          /*************************************/
+
+               /* Read 16 bit from the EEPROM 93C76 */
+
+          /*************************************/
+
+               v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress,
+                       &w_ReadWord);
+
+       }
+
+       return (w_ReadWord);
+
+}
+
+/*
+
++----------------------------------------------------------------------------+
+
+| Function   Name   : VOID v_EepromWaitBusy                                  |
+
+|                      (WORD   w_PCIBoardEepromAddress)                         |
+
++----------------------------------------------------------------------------+
+
+| Task              : Wait the busy flag from PCI controller                 |
+
++----------------------------------------------------------------------------+
+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom base address |
+
++----------------------------------------------------------------------------+
+
+| Output Parameters : -                                                      |
+
++----------------------------------------------------------------------------+
+
+| Return Value      : -                                                      |
+
++----------------------------------------------------------------------------+
+
+*/
+
+VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
+{
+
+       BYTE b_EepromBusy = 0;
+
+       do
+       {
+
+          /*************/
+
+               /* IMPORTANT */
+
+          /*************/
+
+          /************************************************************************/
+
+               /* An error has been written in the AMCC 5933 book at the page B-13 */
+
+               /* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and   */
+
+               /*      the operator register is AMCC_OP_REG_MCSR+3 */
+
+               /*      WORD read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */
+
+               /*      DWORD read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
+
+          /************************************************************************/
+
+               b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F);
+               b_EepromBusy = b_EepromBusy & 0x80;
+
+       }
+       while (b_EepromBusy == 0x80);
+
+}
+
+/*
+
++---------------------------------------------------------------------------------+
+
+| Function   Name   : VOID v_EepromClock76(DWORD dw_Address,                      |
+
+|                                         DWORD dw_RegisterValue)                                        |
+
++---------------------------------------------------------------------------------+
+
+| Task              : This function sends the clocking sequence to the EEPROM.    |
+
++---------------------------------------------------------------------------------+
+
+| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
+
+|                    DWORD dw_RegisterValue : PCI eeprom register value to write.|
+
++---------------------------------------------------------------------------------+
+
+| Output Parameters : -                                                           |
+
++---------------------------------------------------------------------------------+
+
+| Return Value      : -                                                           |
+
++---------------------------------------------------------------------------------+
+
+*/
+
+VOID v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+{
+
+   /************************/
+
+       /* Set EEPROM clock Low */
+
+   /************************/
+
+       outl(dw_RegisterValue & 0x6, dw_Address);
+
+   /***************/
+
+       /* Wait 0.1 ms */
+
+   /***************/
+
+       udelay(100);
+
+   /*************************/
+
+       /* Set EEPROM clock High */
+
+   /*************************/
+
+       outl(dw_RegisterValue | 0x1, dw_Address);
+
+   /***************/
+
+       /* Wait 0.1 ms */
+
+   /***************/
+
+       udelay(100);
+
+}
+
+/*
+
++---------------------------------------------------------------------------------+
+
+| Function   Name   : VOID v_EepromSendCommand76(DWORD dw_Address,                |
+
+|                                         DWORD   dw_EepromCommand,                              |
+
+|                                         BYTE    b_DataLengthInBits)                        |
+
++---------------------------------------------------------------------------------+
+
+| Task              : This function sends a Command to the EEPROM 93C76.          |
+
++---------------------------------------------------------------------------------+
+
+| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
+
+|                    DWORD dw_EepromCommand : PCI eeprom command to write.       |
+
+|                    BYTE  b_DataLengthInBits : PCI eeprom command data length.  |
+
++---------------------------------------------------------------------------------+
+
+| Output Parameters : -                                                           |
+
++---------------------------------------------------------------------------------+
+
+| Return Value      : -                                                           |
+
++---------------------------------------------------------------------------------+
+
+*/
+
+VOID v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+       BYTE b_DataLengthInBits)
+{
+
+       CHAR c_BitPos = 0;
+
+       DWORD dw_RegisterValue = 0;
+
+   /*****************************/
+
+       /* Enable EEPROM Chip Select */
+
+   /*****************************/
+
+       dw_RegisterValue = 0x2;
+
+   /********************************************************************/
+
+       /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
+
+   /********************************************************************/
+
+       outl(dw_RegisterValue, dw_Address);
+
+   /***************/
+
+       /* Wait 0.1 ms */
+
+   /***************/
+
+       udelay(100);
+
+   /*******************************************/
+
+       /* Send EEPROM command - one bit at a time */
+
+   /*******************************************/
+
+       for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--)
+       {
+
+      /**********************************/
+
+               /* Check if current bit is 0 or 1 */
+
+      /**********************************/
+
+               if (dw_EepromCommand & (1 << c_BitPos))
+               {
+
+        /***********/
+
+                       /* Write 1 */
+
+        /***********/
+
+                       dw_RegisterValue = dw_RegisterValue | 0x4;
+
+               }
+
+               else
+               {
+
+        /***********/
+
+                       /* Write 0 */
+
+        /***********/
+
+                       dw_RegisterValue = dw_RegisterValue & 0x3;
+
+               }
+
+      /*********************/
+
+               /* Write the command */
+
+      /*********************/
+
+               outl(dw_RegisterValue, dw_Address);
+
+      /***************/
+
+               /* Wait 0.1 ms */
+
+      /***************/
+
+               udelay(100);
+
+      /****************************/
+
+               /* Trigger the EEPROM clock */
+
+      /****************************/
+
+               v_EepromClock76(dw_Address, dw_RegisterValue);
+
+       }
+
+}
+
+/*
+
++---------------------------------------------------------------------------------+
+
+| Function   Name   : VOID v_EepromCs76Read(DWORD dw_Address,                     |
+
+|                                         WORD    w_offset,                                              |
+
+|                                         PWORD   pw_Value)                                              |
+
++---------------------------------------------------------------------------------+
+
+| Task              : This function read a value from the EEPROM 93C76.           |
+
++---------------------------------------------------------------------------------+
+
+| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
+
+|                    WORD    w_offset : Offset of the adress to read             |
+
+|                    PWORD   pw_Value : PCI eeprom 16 bit read value.            |
+
++---------------------------------------------------------------------------------+
+
+| Output Parameters : -                                                           |
+
++---------------------------------------------------------------------------------+
+
+| Return Value      : -                                                           |
+
++---------------------------------------------------------------------------------+
+
+*/
+
+VOID v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+{
+
+       CHAR c_BitPos = 0;
+
+       DWORD dw_RegisterValue = 0;
+
+       DWORD dw_RegisterValueRead = 0;
+
+   /*************************************************/
+
+       /* Send EEPROM read command and offset to EEPROM */
+
+   /*************************************************/
+
+       v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2),
+               EE76_CMD_LEN);
+
+   /*******************************/
+
+       /* Get the last register value */
+
+   /*******************************/
+
+       dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2;
+
+   /*****************************/
+
+       /* Set the 16-bit value of 0 */
+
+   /*****************************/
+
+       *pw_Value = 0;
+
+   /************************/
+
+       /* Get the 16-bit value */
+
+   /************************/
+
+       for (c_BitPos = 0; c_BitPos < 16; c_BitPos++)
+       {
+
+      /****************************/
+
+               /* Trigger the EEPROM clock */
+
+      /****************************/
+
+               v_EepromClock76(dw_Address, dw_RegisterValue);
+
+      /**********************/
+
+               /* Get the result bit */
+
+      /**********************/
+
+               dw_RegisterValueRead = inl(dw_Address);
+
+      /***************/
+
+               /* Wait 0.1 ms */
+
+      /***************/
+
+               udelay(100);
+
+      /***************************************/
+
+               /* Get bit value and shift into result */
+
+      /***************************************/
+
+               if (dw_RegisterValueRead & 0x8)
+               {
+
+        /**********/
+
+                       /* Read 1 */
+
+        /**********/
+
+                       *pw_Value = (*pw_Value << 1) | 0x1;
+
+               }
+
+               else
+               {
+
+        /**********/
+
+                       /* Read 0 */
+
+        /**********/
+
+                       *pw_Value = (*pw_Value << 1);
+
+               }
+
+       }
+
+   /*************************/
+
+       /* Clear all EEPROM bits */
+
+   /*************************/
+
+       dw_RegisterValue = 0x0;
+
+   /********************************************************************/
+
+       /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
+
+   /********************************************************************/
+
+       outl(dw_RegisterValue, dw_Address);
+
+   /***************/
+
+       /* Wait 0.1 ms */
+
+   /***************/
+
+       udelay(100);
+
+}
+
+       /******************************************/
+       /*      EEPROM HEADER READ FUNCTIONS      */
+       /******************************************/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name  : INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,  |
+|                              PCHAR   pc_PCIChipInformation,comedi_device *dev)    |
++----------------------------------------------------------------------------+
+| Task              : Read from eeprom Main Header                           |
++----------------------------------------------------------------------------+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+|                                                                                                                                       |
+|                    PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+|                                                                                                                                       |
+|                        comedi_device *dev               : comedi device structure |
+|                                                                                       pointer                                 |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                                     |
++----------------------------------------------------------------------------+
+*/
+
+INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, comedi_device * dev)
+{
+       WORD w_Temp, i, w_Count = 0;
+       UINT ui_Temp;
+       str_MainHeader s_MainHeader;
+       str_DigitalInputHeader s_DigitalInputHeader;
+       str_DigitalOutputHeader s_DigitalOutputHeader;
+       //str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
+       str_AnalogOutputHeader s_AnalogOutputHeader;
+       str_AnalogInputHeader s_AnalogInputHeader;
+
+       // Read size
+       s_MainHeader.w_HeaderSize =
+               w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+               0x100 + 8);
+
+       // Read nbr of functionality
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+               pc_PCIChipInformation, 0x100 + 10);
+       s_MainHeader.b_Nfunctions = (BYTE) w_Temp & 0x00FF;
+
+       // Read functionality details
+       for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+               // Read Type
+               w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+                       pc_PCIChipInformation, 0x100 + 12 + w_Count);
+               s_MainHeader.s_Functions[i].b_Type = (BYTE) w_Temp & 0x3F;
+               w_Count = w_Count + 2;
+               //Read Address
+               s_MainHeader.s_Functions[i].w_Address =
+                       w_EepromReadWord(w_PCIBoardEepromAddress,
+                       pc_PCIChipInformation, 0x100 + 12 + w_Count);
+               w_Count = w_Count + 2;
+       }
+
+       // Display main header info
+       for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+
+               switch (s_MainHeader.s_Functions[i].b_Type) {
+               case EEPROM_DIGITALINPUT:
+                       i_EepromReadDigitalInputHeader(w_PCIBoardEepromAddress,
+                               pc_PCIChipInformation,
+                               s_MainHeader.s_Functions[i].w_Address,
+                               &s_DigitalInputHeader);
+                       this_board->i_NbrDiChannel =
+                               s_DigitalInputHeader.w_Nchannel;
+                       break;
+
+               case EEPROM_DIGITALOUTPUT:
+                       i_EepromReadDigitalOutputHeader(w_PCIBoardEepromAddress,
+                               pc_PCIChipInformation,
+                               s_MainHeader.s_Functions[i].w_Address,
+                               &s_DigitalOutputHeader);
+                       this_board->i_NbrDoChannel =
+                               s_DigitalOutputHeader.w_Nchannel;
+                       ui_Temp = 0xffffffff;
+                       this_board->i_DoMaxdata =
+                               ui_Temp >> (32 - this_board->i_NbrDoChannel);
+                       break;
+
+               case EEPROM_ANALOGINPUT:
+                       i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress,
+                               pc_PCIChipInformation,
+                               s_MainHeader.s_Functions[i].w_Address,
+                               &s_AnalogInputHeader);
+                       if (!(strcmp(this_board->pc_DriverName, "apci3200")))
+                               this_board->i_NbrAiChannel =
+                                       s_AnalogInputHeader.w_Nchannel * 4;
+                       else
+                               this_board->i_NbrAiChannel =
+                                       s_AnalogInputHeader.w_Nchannel;
+                       this_board->i_Dma = s_AnalogInputHeader.b_HasDma;
+                       this_board->ui_MinAcquisitiontimeNs =
+                               (UINT) s_AnalogInputHeader.w_MinConvertTiming *
+                               1000;
+                       this_board->ui_MinDelaytimeNs =
+                               (UINT) s_AnalogInputHeader.w_MinDelayTiming *
+                               1000;
+                       ui_Temp = 0xffff;
+                       this_board->i_AiMaxdata =
+                               ui_Temp >> (16 -
+                               s_AnalogInputHeader.b_Resolution);
+                       break;
+
+               case EEPROM_ANALOGOUTPUT:
+                       i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress,
+                               pc_PCIChipInformation,
+                               s_MainHeader.s_Functions[i].w_Address,
+                               &s_AnalogOutputHeader);
+                       this_board->i_NbrAoChannel =
+                               s_AnalogOutputHeader.w_Nchannel;
+                       ui_Temp = 0xffff;
+                       this_board->i_AoMaxdata =
+                               ui_Temp >> (16 -
+                               s_AnalogOutputHeader.b_Resolution);
+                       break;
+
+               case EEPROM_TIMER:
+                       this_board->i_Timer = 1;        //Timer subdevice present
+                       break;
+
+               case EEPROM_WATCHDOG:
+                       this_board->i_Timer = 1;        //Timer subdevice present
+                       break;
+
+               case EEPROM_TIMER_WATCHDOG_COUNTER:
+                       this_board->i_Timer = 1;        //Timer subdevice present
+               }
+       }
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name  : INT i_EepromReadDigitalInputHeader(WORD                                      |
+|                      w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,     |
+|                      WORD w_Address,str_DigitalInputHeader *s_Header)                 |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Task              : Read Digital Input Header                              |
++----------------------------------------------------------------------------+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+|                                                                                                                                       |
+|                    PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+|                                                                                                                                       |
+|                       str_DigitalInputHeader *s_Header: Digita Input Header   |
+|                                                                                                 Pointer                       |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                                     |
++----------------------------------------------------------------------------+
+*/
+INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_DigitalInputHeader * s_Header)
+{
+       WORD w_Temp;
+
+       // read nbr of channels
+       s_Header->w_Nchannel =
+               w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+               0x100 + w_Address + 6);
+
+       // interruptible or not
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+               pc_PCIChipInformation, 0x100 + w_Address + 8);
+       s_Header->b_Interruptible = (BYTE) (w_Temp >> 7) & 0x01;
+
+// How many interruptible logic
+       s_Header->w_NinterruptLogic =
+               w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+               0x100 + w_Address + 10);
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name  : INT i_EepromReadDigitalOutputHeader(WORD                             |
+|                      w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,     |
+|                      WORD w_Address,str_DigitalOutputHeader *s_Header)            |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Task              : Read Digital Output Header                             |
++----------------------------------------------------------------------------+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+|                                                                                                                                       |
+|                    PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+|                                                                                                                                       |
+|                       str_DigitalOutputHeader *s_Header: Digital Output Header|
+|                                                                                         Pointer                               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                                     |
++----------------------------------------------------------------------------+
+*/
+INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_DigitalOutputHeader * s_Header)
+{
+// Read Nbr channels
+       s_Header->w_Nchannel =
+               w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+               0x100 + w_Address + 6);
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name  : INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, |
+|                      PCHAR pc_PCIChipInformation,WORD w_Address,                              |
+|                      str_TimerMainHeader *s_Header)                                                   |
++----------------------------------------------------------------------------+
+| Task              : Read Timer or Watchdog Header                          |
++----------------------------------------------------------------------------+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+|                                                                                                                                       |
+|                    PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+|                                                                                                                                       |
+|                       str_TimerMainHeader *s_Header: Timer Header                     |
+|                                                                                         Pointer                               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                                     |
++----------------------------------------------------------------------------+
+*/
+INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_TimerMainHeader * s_Header)
+{
+
+       WORD i, w_Size = 0, w_Temp;
+
+//Read No of Timer
+       s_Header->w_Ntimer =
+               w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+               0x100 + w_Address + 6);
+//Read header size
+
+       for (i = 0; i < s_Header->w_Ntimer; i++) {
+               s_Header->s_TimerDetails[i].w_HeaderSize =
+                       w_EepromReadWord(w_PCIBoardEepromAddress,
+                       pc_PCIChipInformation,
+                       0x100 + w_Address + 8 + w_Size + 0);
+               w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+                       pc_PCIChipInformation,
+                       0x100 + w_Address + 8 + w_Size + 2);
+
+               //Read Resolution
+               s_Header->s_TimerDetails[i].b_Resolution =
+                       (BYTE) (w_Temp >> 10) & 0x3F;
+
+               //Read Mode
+               s_Header->s_TimerDetails[i].b_Mode =
+                       (BYTE) (w_Temp >> 4) & 0x3F;
+
+               w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+                       pc_PCIChipInformation,
+                       0x100 + w_Address + 8 + w_Size + 4);
+
+               //Read MinTiming
+               s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF;
+
+               //Read Timebase
+               s_Header->s_TimerDetails[i].b_TimeBase = (BYTE) (w_Temp) & 0x3F;
+               w_Size += s_Header->s_TimerDetails[i].w_HeaderSize;
+       }
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name  : INT i_EepromReadAnlogOutputHeader(WORD                                       |
+|                      w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,     |
+|                      WORD w_Address,str_AnalogOutputHeader *s_Header)         |
++----------------------------------------------------------------------------+
+| Task              : Read Nalog Output  Header                              |
++----------------------------------------------------------------------------+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+|                                                                                                                                       |
+|                    PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+|                                                                                                                                       |
+|                       str_AnalogOutputHeader *s_Header:Anlog Output Header    |
+|                                                                                         Pointer                               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                                     |
++----------------------------------------------------------------------------+
+*/
+
+INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_AnalogOutputHeader * s_Header)
+{
+       WORD w_Temp;
+       // No of channels for 1st hard component
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+               pc_PCIChipInformation, 0x100 + w_Address + 10);
+       s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
+       // Resolution for 1st hard component
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+               pc_PCIChipInformation, 0x100 + w_Address + 16);
+       s_Header->b_Resolution = (BYTE) (w_Temp >> 8) & 0xFF;
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name  : INT i_EepromReadAnlogInputHeader(WORD                                        |
+|                      w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,     |
+|                      WORD w_Address,str_AnalogInputHeader *s_Header)          |
++----------------------------------------------------------------------------+
+| Task              : Read Nalog Output  Header                              |
++----------------------------------------------------------------------------+
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom address      |
+|                                                                                                                                       |
+|                    PCHAR pc_PCIChipInformation  : PCI Chip Type.          |
+|                                                                                                                                       |
+|                       str_AnalogInputHeader *s_Header:Anlog Input Header      |
+|                                                                                         Pointer                               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                                     |
++----------------------------------------------------------------------------+
+*/
+
+// Reads only for ONE  hardware component
+INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+       PCHAR pc_PCIChipInformation, WORD w_Address,
+       str_AnalogInputHeader * s_Header)
+{
+       WORD w_Temp, w_Offset;
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+               pc_PCIChipInformation, 0x100 + w_Address + 10);
+       s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
+       s_Header->w_MinConvertTiming =
+               w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+               0x100 + w_Address + 16);
+       s_Header->w_MinDelayTiming =
+               w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+               0x100 + w_Address + 30);
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+               pc_PCIChipInformation, 0x100 + w_Address + 20);
+       s_Header->b_HasDma = (w_Temp >> 13) & 0x01;     // whether dma present or not
+
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72);      // reading Y
+       w_Temp = w_Temp & 0x00FF;
+       if (w_Temp)             //Y>0
+       {
+               w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16)));      // offset of first analog input single header
+               w_Offset = w_Offset + 2;        // resolution
+       } else                  //Y=0
+       {
+               w_Offset = 74;
+               w_Offset = w_Offset + 2;        // resolution
+       }
+
+// read Resolution
+       w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+               pc_PCIChipInformation, 0x100 + w_Address + w_Offset);
+       s_Header->b_Resolution = w_Temp & 0x001F;       // last 5 bits
+
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
new file mode 100644 (file)
index 0000000..74b6197
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+       Modified by umesh on 16th may 2001
+       Modified by sarath on 22nd may 2001
+*/
+
+/*
+    comedi/drivers/amcc_s5933_v_58.h
+
+    Stuff for AMCC S5933 PCI Controller
+
+    Author: Michal Dobes <majkl@tesnet.cz>
+
+    Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver
+    made by Andrea Cisternino  <acister@pcape1.pi.infn.it>
+    and as result of espionage from MITE code made by David A. Schleef.
+    Thanks to AMCC for their on-line documentation and bus master DMA
+    example.
+*/
+
+#ifndef _AMCC_S5933_H_
+#define _AMCC_S5933_H_
+
+#include <linux/pci.h>
+#include "../../comedidev.h"
+
+#ifdef PCI_SUPPORT_VER1
+#error    Sorry, no support for 2.1.55 and older! :-((((
+#endif
+
+/***********Added by sarath for compatibility with APCI3120
+
+*************************/
+
+#define FIFO_ADVANCE_ON_BYTE_2     0x20000000  // written on base0
+
+#define AMWEN_ENABLE                     0x02  // added for step 6 dma written on base2
+#define A2P_FIFO_WRITE_ENABLE            0x01
+
+#define AGCSTS_TC_ENABLE                  0x10000000   // Added for transfer count enable bit
+
+//  ADDON RELATED ADDITIONS
+// Constant
+#define     APCI3120_ENABLE_TRANSFER_ADD_ON_LOW       0x00
+#define     APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH      0x1200
+#define     APCI3120_A2P_FIFO_MANAGEMENT              0x04000400L
+#define     APCI3120_AMWEN_ENABLE                     0x02
+#define     APCI3120_A2P_FIFO_WRITE_ENABLE            0x01
+#define     APCI3120_FIFO_ADVANCE_ON_BYTE_2           0x20000000L
+#define     APCI3120_ENABLE_WRITE_TC_INT              0x00004000L
+#define     APCI3120_CLEAR_WRITE_TC_INT               0x00040000L
+#define     APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
+#define     APCI3120_DISABLE_BUS_MASTER_ADD_ON        0x0
+#define     APCI3120_DISABLE_BUS_MASTER_PCI           0x0
+
+ // ADD_ON ::: this needed since apci supports 16 bit interface to add on
+#define     APCI3120_ADD_ON_AGCSTS_LOW       0x3C
+#define     APCI3120_ADD_ON_AGCSTS_HIGH      APCI3120_ADD_ON_AGCSTS_LOW + 2
+#define     APCI3120_ADD_ON_MWAR_LOW         0x24
+#define     APCI3120_ADD_ON_MWAR_HIGH        APCI3120_ADD_ON_MWAR_LOW + 2
+#define     APCI3120_ADD_ON_MWTC_LOW         0x058
+#define     APCI3120_ADD_ON_MWTC_HIGH        APCI3120_ADD_ON_MWTC_LOW + 2
+
+// AMCC
+#define     APCI3120_AMCC_OP_MCSR            0x3C
+#define     APCI3120_AMCC_OP_REG_INTCSR      0x38
+
+/*******from here all upward definitions are added by sarath */
+
+/****************************************************************************/
+/* AMCC Operation Register Offsets - PCI                                    */
+/****************************************************************************/
+
+#define AMCC_OP_REG_OMB1         0x00
+#define AMCC_OP_REG_OMB2         0x04
+#define AMCC_OP_REG_OMB3         0x08
+#define AMCC_OP_REG_OMB4         0x0c
+#define AMCC_OP_REG_IMB1         0x10
+#define AMCC_OP_REG_IMB2         0x14
+#define AMCC_OP_REG_IMB3         0x18
+#define AMCC_OP_REG_IMB4         0x1c
+#define AMCC_OP_REG_FIFO         0x20
+#define AMCC_OP_REG_MWAR         0x24
+#define AMCC_OP_REG_MWTC         0x28
+#define AMCC_OP_REG_MRAR         0x2c
+#define AMCC_OP_REG_MRTC         0x30
+#define AMCC_OP_REG_MBEF         0x34
+#define AMCC_OP_REG_INTCSR       0x38
+#define  AMCC_OP_REG_INTCSR_SRC  (AMCC_OP_REG_INTCSR + 2)      /* INT source */
+#define  AMCC_OP_REG_INTCSR_FEC  (AMCC_OP_REG_INTCSR + 3)      /* FIFO ctrl */
+#define AMCC_OP_REG_MCSR         0x3c
+#define  AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2)        /* Data in byte 2 */
+#define  AMCC_OP_REG_MCSR_NVCMD  (AMCC_OP_REG_MCSR + 3)        /* Command in byte 3 */
+
+#define AMCC_FIFO_DEPTH_DWORD  8
+#define AMCC_FIFO_DEPTH_BYTES  (8 * sizeof (u32))
+
+/****************************************************************************/
+/* AMCC Operation Registers Size - PCI                                      */
+/****************************************************************************/
+
+#define AMCC_OP_REG_SIZE        64     /* in bytes */
+
+/****************************************************************************/
+/* AMCC Operation Register Offsets - Add-on                                 */
+/****************************************************************************/
+
+#define AMCC_OP_REG_AIMB1         0x00
+#define AMCC_OP_REG_AIMB2         0x04
+#define AMCC_OP_REG_AIMB3         0x08
+#define AMCC_OP_REG_AIMB4         0x0c
+#define AMCC_OP_REG_AOMB1         0x10
+#define AMCC_OP_REG_AOMB2         0x14
+#define AMCC_OP_REG_AOMB3         0x18
+#define AMCC_OP_REG_AOMB4         0x1c
+#define AMCC_OP_REG_AFIFO         0x20
+#define AMCC_OP_REG_AMWAR         0x24
+#define AMCC_OP_REG_APTA          0x28
+#define AMCC_OP_REG_APTD          0x2c
+#define AMCC_OP_REG_AMRAR         0x30
+#define AMCC_OP_REG_AMBEF         0x34
+#define AMCC_OP_REG_AINT          0x38
+#define AMCC_OP_REG_AGCSTS        0x3c
+#define AMCC_OP_REG_AMWTC         0x58
+#define AMCC_OP_REG_AMRTC         0x5c
+
+/****************************************************************************/
+/* AMCC - Add-on General Control/Status Register                            */
+/****************************************************************************/
+
+#define AGCSTS_CONTROL_MASK    0xfffff000
+#define  AGCSTS_NV_ACC_MASK    0xe0000000
+#define  AGCSTS_RESET_MASK     0x0e000000
+#define  AGCSTS_NV_DA_MASK     0x00ff0000
+#define  AGCSTS_BIST_MASK      0x0000f000
+#define AGCSTS_STATUS_MASK     0x000000ff
+#define  AGCSTS_TCZERO_MASK    0x000000c0
+#define  AGCSTS_FIFO_ST_MASK   0x0000003f
+
+#define AGCSTS_RESET_MBFLAGS   0x08000000
+#define AGCSTS_RESET_P2A_FIFO  0x04000000
+#define AGCSTS_RESET_A2P_FIFO  0x02000000
+#define AGCSTS_RESET_FIFOS     (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
+
+#define AGCSTS_A2P_TCOUNT      0x00000080
+#define AGCSTS_P2A_TCOUNT      0x00000040
+
+#define AGCSTS_FS_P2A_EMPTY    0x00000020
+#define AGCSTS_FS_P2A_HALF     0x00000010
+#define AGCSTS_FS_P2A_FULL     0x00000008
+
+#define AGCSTS_FS_A2P_EMPTY    0x00000004
+#define AGCSTS_FS_A2P_HALF     0x00000002
+#define AGCSTS_FS_A2P_FULL     0x00000001
+
+/****************************************************************************/
+/* AMCC - Add-on Interrupt Control/Status Register                            */
+/****************************************************************************/
+
+#define AINT_INT_MASK          0x00ff0000
+#define AINT_SEL_MASK          0x0000ffff
+#define  AINT_IS_ENSEL_MASK    0x00001f1f
+
+#define AINT_INT_ASSERTED      0x00800000
+#define AINT_BM_ERROR          0x00200000
+#define AINT_BIST_INT          0x00100000
+
+#define AINT_RT_COMPLETE       0x00080000
+#define AINT_WT_COMPLETE       0x00040000
+
+#define AINT_OUT_MB_INT                0x00020000
+#define AINT_IN_MB_INT         0x00010000
+
+#define AINT_READ_COMPL                0x00008000
+#define AINT_WRITE_COMPL       0x00004000
+
+#define AINT_OMB_ENABLE        0x00001000
+#define AINT_OMB_SELECT        0x00000c00
+#define AINT_OMB_BYTE          0x00000300
+
+#define AINT_IMB_ENABLE        0x00000010
+#define AINT_IMB_SELECT        0x0000000c
+#define AINT_IMB_BYTE          0x00000003
+
+/* Enable Bus Mastering */
+#define EN_A2P_TRANSFERS       0x00000400
+/* FIFO Flag Reset */
+#define RESET_A2P_FLAGS                0x04000000L
+/* FIFO Relative Priority */
+#define A2P_HI_PRIORITY                0x00000100L
+/* Identify Interrupt Sources */
+#define ANY_S593X_INT          0x00800000L
+#define READ_TC_INT            0x00080000L
+#define WRITE_TC_INT           0x00040000L
+#define IN_MB_INT              0x00020000L
+#define MASTER_ABORT_INT       0x00100000L
+#define TARGET_ABORT_INT       0x00200000L
+#define BUS_MASTER_INT         0x00200000L
+
+/****************************************************************************/
+
+struct pcilst_struct {
+       struct pcilst_struct *next;
+       int used;
+       struct pci_dev *pcidev;
+       unsigned short vendor;
+       unsigned short device;
+       unsigned int master;
+       unsigned char pci_bus;
+       unsigned char pci_slot;
+       unsigned char pci_func;
+       unsigned int io_addr[5];
+       unsigned int irq;
+};
+
+struct pcilst_struct *amcc_devices;    // ptr to root list of all amcc devices
+
+/****************************************************************************/
+
+void v_pci_card_list_init(unsigned short pci_vendor, char display);
+void v_pci_card_list_cleanup(unsigned short pci_vendor);
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+       unsigned short device_id);
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot, struct pcilst_struct **card);
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot);
+
+int i_pci_card_alloc(struct pcilst_struct *amcc);
+int i_pci_card_free(struct pcilst_struct *amcc);
+void v_pci_card_list_display(void);
+int i_pci_card_data(struct pcilst_struct *amcc,
+       unsigned char *pci_bus, unsigned char *pci_slot,
+       unsigned char *pci_func, unsigned short *io_addr, unsigned short *irq,
+       unsigned short *master);
+
+/****************************************************************************/
+
+/* build list of amcc cards in this system */
+void v_pci_card_list_init(unsigned short pci_vendor, char display)
+{
+       struct pci_dev *pcidev;
+       struct pcilst_struct *amcc, *last;
+       int i;
+
+       amcc_devices = NULL;
+       last = NULL;
+
+#if LINUX_VERSION_CODE < 0x020300
+       for (pcidev = pci_devices; pcidev; pcidev = pcidev->next) {
+#else
+       pci_for_each_dev(pcidev) {
+#endif
+               if (pcidev->vendor == pci_vendor) {
+                       amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
+                       memset(amcc, 0, sizeof(*amcc));
+
+                       amcc->pcidev = pcidev;
+                       if (last) {
+                               last->next = amcc;
+                       } else {
+                               amcc_devices = amcc;
+                       }
+                       last = amcc;
+
+#if LINUX_VERSION_CODE < 0x020300
+                       amcc->vendor = pcidev->vendor;
+                       amcc->device = pcidev->device;
+                       amcc->master = pcidev->master;
+                       amcc->pci_bus = pcidev->bus->number;
+                       amcc->pci_slot = PCI_SLOT(pcidev->devfn);
+                       amcc->pci_func = PCI_FUNC(pcidev->devfn);
+                       for (i = 0; i < 5; i++)
+                               amcc->io_addr[i] =
+                                       pcidev->base_address[i] & ~3UL;
+                       amcc->irq = pcidev->irq;
+#else
+                       amcc->vendor = pcidev->vendor;
+                       amcc->device = pcidev->device;
+#if 0
+                       amcc->master = pcidev->master;  // how get this information under 2.4 kernels?
+#endif
+                       amcc->pci_bus = pcidev->bus->number;
+                       amcc->pci_slot = PCI_SLOT(pcidev->devfn);
+                       amcc->pci_func = PCI_FUNC(pcidev->devfn);
+                       for (i = 0; i < 5; i++)
+                               amcc->io_addr[i] =
+                                       pcidev->resource[i].start & ~3UL;
+                       amcc->irq = pcidev->irq;
+#endif
+
+               }
+       }
+
+       if (display)
+               v_pci_card_list_display();
+}
+
+/****************************************************************************/
+/* free up list of amcc cards in this system */
+void v_pci_card_list_cleanup(unsigned short pci_vendor)
+{
+       struct pcilst_struct *amcc, *next;
+
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               kfree(amcc);
+       }
+
+       amcc_devices = NULL;
+}
+
+/****************************************************************************/
+/* find first unused card with this device_id */
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+       unsigned short device_id)
+{
+       struct pcilst_struct *amcc, *next;
+
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               if ((!amcc->used) && (amcc->device == device_id)
+                       && (amcc->vendor == vendor_id))
+                       return amcc;
+
+       }
+
+       return NULL;
+}
+
+/****************************************************************************/
+/* find card on requested position */
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot, struct pcilst_struct **card)
+{
+       struct pcilst_struct *amcc, *next;
+
+       *card = NULL;
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
+                       && (amcc->pci_bus == pci_bus)
+                       && (amcc->pci_slot == pci_slot)) {
+                       if (!(amcc->used)) {
+                               *card = amcc;
+                               return 0;       // ok, card is found
+                       } else {
+                               rt_printk
+                                       (" - \nCard on requested position is used b:s %d:%d!\n",
+                                       pci_bus, pci_slot);
+                               return 2;       // card exist but is used
+                       }
+               }
+       }
+
+       return 1;               // no card found
+}
+
+/****************************************************************************/
+/* mark card as used */
+int i_pci_card_alloc(struct pcilst_struct *amcc)
+{
+       if (!amcc)
+               return -1;
+
+       if (amcc->used)
+               return 1;
+       amcc->used = 1;
+       return 0;
+}
+
+/****************************************************************************/
+/* mark card as free */
+int i_pci_card_free(struct pcilst_struct *amcc)
+{
+       if (!amcc)
+               return -1;
+
+       if (!amcc->used)
+               return 1;
+       amcc->used = 0;
+       return 0;
+}
+
+/****************************************************************************/
+/* display list of found cards */
+void v_pci_card_list_display(void)
+{
+       struct pcilst_struct *amcc, *next;
+
+       printk("List of pci cards\n");
+       printk("bus:slot:func vendor device master io_amcc io_daq irq used\n");
+
+       for (amcc = amcc_devices; amcc; amcc = next) {
+               next = amcc->next;
+               printk("%2d   %2d   %2d  0x%4x 0x%4x   %3s   0x%4x 0x%4x  %2d  %2d\n", amcc->pci_bus, amcc->pci_slot, amcc->pci_func, amcc->vendor, amcc->device, amcc->master ? "yes" : "no", amcc->io_addr[0], amcc->io_addr[2], amcc->irq, amcc->used);
+
+       }
+}
+
+/****************************************************************************/
+/* return all card information for driver */
+int i_pci_card_data(struct pcilst_struct *amcc,
+       unsigned char *pci_bus, unsigned char *pci_slot,
+       unsigned char *pci_func, unsigned short *io_addr, unsigned short *irq,
+       unsigned short *master)
+{
+       int i;
+
+       if (!amcc)
+               return -1;
+       *pci_bus = amcc->pci_bus;
+       *pci_slot = amcc->pci_slot;
+       *pci_func = amcc->pci_func;
+       for (i = 0; i < 5; i++)
+               io_addr[i] = amcc->io_addr[i];
+       *irq = amcc->irq;
+       *master = amcc->master;
+       return 0;
+}
+
+/****************************************************************************/
+/* select and alloc card */
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+       unsigned short device_id, unsigned short pci_bus,
+       unsigned short pci_slot)
+{
+       struct pcilst_struct *card;
+
+       if ((pci_bus < 1) & (pci_slot < 1)) {   // use autodetection
+               if ((card = ptr_find_free_pci_card_by_device(vendor_id,
+                                       device_id)) == NULL) {
+                       rt_printk(" - Unused card not found in system!\n");
+                       return NULL;
+               }
+       } else {
+               switch (i_find_free_pci_card_by_position(vendor_id, device_id,
+                               pci_bus, pci_slot, &card)) {
+               case 1:
+                       rt_printk
+                               (" - Card not found on requested position b:s %d:%d!\n",
+                               pci_bus, pci_slot);
+                       return NULL;
+               case 2:
+                       rt_printk
+                               (" - Card on requested position is used b:s %d:%d!\n",
+                               pci_bus, pci_slot);
+                       return NULL;
+               }
+       }
+
+       if (i_pci_card_alloc(card) != 0) {
+               rt_printk(" - Can't allocate card!\n");
+               return NULL;
+       }
+
+       return card;
+}
+
+#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
new file mode 100644 (file)
index 0000000..e18d085
--- /dev/null
@@ -0,0 +1,1265 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-1710       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci1710.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-1710                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+#include "hwdrv_APCI1710.h"
+#include "APCI1710_Inp_cpt.c"
+
+#include "APCI1710_Ssi.c"
+#include "APCI1710_Tor.c"
+#include "APCI1710_Ttl.c"
+#include "APCI1710_Dig_io.c"
+#include "APCI1710_82x54.c"
+#include "APCI1710_Chrono.c"
+#include "APCI1710_Pwm.c"
+#include "APCI1710_INCCPT.c"
+
+void i_ADDI_AttachPCI1710(comedi_device * dev)
+{
+       comedi_subdevice *s;
+       int ret = 0;
+       int n_subdevices = 9;
+
+       //Update-0.7.57->0.7.68dev->n_subdevices = 9;
+       if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+               return;
+
+       // Allocate and Initialise Timer Subdevice Structures
+       s = dev->subdevices + 0;
+
+       s->type = COMEDI_SUBD_TIMER;
+       s->subdev_flags = SDF_WRITEABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 3;
+       s->maxdata = 0;
+       s->len_chanlist = 3;
+       s->range_table = &range_digital;
+       s->insn_write = i_APCI1710_InsnWriteEnableDisableTimer;
+       s->insn_read = i_APCI1710_InsnReadAllTimerValue;
+       s->insn_config = i_APCI1710_InsnConfigInitTimer;
+       s->insn_bits = i_APCI1710_InsnBitsTimer;
+
+       // Allocate and Initialise DIO Subdevice Structures
+       s = dev->subdevices + 1;
+
+       s->type = COMEDI_SUBD_DIO;
+       s->subdev_flags =
+               SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 7;
+       s->maxdata = 1;
+       s->len_chanlist = 7;
+       s->range_table = &range_digital;
+       s->insn_config = i_APCI1710_InsnConfigDigitalIO;
+       s->insn_read = i_APCI1710_InsnReadDigitalIOChlValue;
+       s->insn_bits = i_APCI1710_InsnBitsDigitalIOPortOnOff;
+       s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff;
+
+       // Allocate and Initialise Chrono Subdevice Structures
+       s = dev->subdevices + 2;
+
+       s->type = COMEDI_SUBD_CHRONO;
+       s->subdev_flags = SDF_WRITEABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 4;
+       s->maxdata = 0;
+       s->len_chanlist = 4;
+       s->range_table = &range_digital;
+       s->insn_write = i_APCI1710_InsnWriteEnableDisableChrono;
+       s->insn_read = i_APCI1710_InsnReadChrono;
+       s->insn_config = i_APCI1710_InsnConfigInitChrono;
+       s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO;
+
+       // Allocate and Initialise PWM Subdevice Structures
+       s = dev->subdevices + 3;
+       s->type = COMEDI_SUBD_PWM;
+       s->subdev_flags =
+               SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 3;
+       s->maxdata = 1;
+       s->len_chanlist = 3;
+       s->range_table = &range_digital;
+       s->io_bits = 0;         //all bits input
+       s->insn_config = i_APCI1710_InsnConfigPWM;
+       s->insn_read = i_APCI1710_InsnReadGetPWMStatus;
+       s->insn_write = i_APCI1710_InsnWritePWM;
+       s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt;
+
+       // Allocate and Initialise TTLIO Subdevice Structures
+       s = dev->subdevices + 4;
+       s->type = COMEDI_SUBD_TTLIO;
+       s->subdev_flags =
+               SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 8;
+       s->maxdata = 1;
+       s->len_chanlist = 8;
+       s->range_table = &range_apci1710_ttl;   // to pass arguments in range
+       s->insn_config = i_APCI1710_InsnConfigInitTTLIO;
+       s->insn_bits = i_APCI1710_InsnBitsReadTTLIO;
+       s->insn_write = i_APCI1710_InsnWriteSetTTLIOChlOnOff;
+       s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue;
+
+       // Allocate and Initialise TOR Subdevice Structures
+       s = dev->subdevices + 5;
+       s->type = COMEDI_SUBD_TOR;
+       s->subdev_flags =
+               SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 8;
+       s->maxdata = 1;
+       s->len_chanlist = 8;
+       s->range_table = &range_digital;
+       s->io_bits = 0;         //all bits input
+       s->insn_config = i_APCI1710_InsnConfigInitTorCounter;
+       s->insn_read = i_APCI1710_InsnReadGetTorCounterInitialisation;
+       s->insn_write = i_APCI1710_InsnWriteEnableDisableTorCounter;
+       s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue;
+
+       // Allocate and Initialise SSI Subdevice Structures
+       s = dev->subdevices + 6;
+       s->type = COMEDI_SUBD_SSI;
+       s->subdev_flags =
+               SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 4;
+       s->maxdata = 1;
+       s->len_chanlist = 4;
+       s->range_table = &range_apci1710_ssi;
+       s->insn_config = i_APCI1710_InsnConfigInitSSI;
+       s->insn_read = i_APCI1710_InsnReadSSIValue;
+       s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO;
+
+       // Allocate and Initialise PULSEENCODER Subdevice Structures
+       s = dev->subdevices + 7;
+       s->type = COMEDI_SUBD_PULSEENCODER;
+       s->subdev_flags =
+               SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 4;
+       s->maxdata = 1;
+       s->len_chanlist = 4;
+       s->range_table = &range_digital;
+       s->insn_config = i_APCI1710_InsnConfigInitPulseEncoder;
+       s->insn_write = i_APCI1710_InsnWriteEnableDisablePulseEncoder;
+       s->insn_bits = i_APCI1710_InsnBitsReadWritePulseEncoder;
+       s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder;
+
+       // Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures
+       s = dev->subdevices + 8;
+       s->type = COMEDI_SUBD_INCREMENTALCOUNTER;
+       s->subdev_flags =
+               SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+       s->n_chan = 500;
+       s->maxdata = 1;
+       s->len_chanlist = 500;
+       s->range_table = &range_apci1710_inccpt;
+       s->insn_config = i_APCI1710_InsnConfigINCCPT;
+       s->insn_write = i_APCI1710_InsnWriteINCCPT;
+       s->insn_read = i_APCI1710_InsnReadINCCPT;
+       s->insn_bits = i_APCI1710_InsnBitsINCCPT;
+}
+
+int i_APCI1710_Reset(comedi_device * dev);
+VOID v_APCI1710_Interrupt(int irq, void *d);
+//for 1710
+
+int i_APCI1710_Reset(comedi_device * dev)
+{
+       int ret;
+       DWORD dw_Dummy;
+
+       /*********************************/
+       /* Read all module configuration */
+       /*********************************/
+       ret = inl(devpriv->s_BoardInfos.ui_Address + 60);
+       devpriv->s_BoardInfos.dw_MolduleConfiguration[0] = ret;
+
+       ret = inl(devpriv->s_BoardInfos.ui_Address + 124);
+       devpriv->s_BoardInfos.dw_MolduleConfiguration[1] = ret;
+
+       ret = inl(devpriv->s_BoardInfos.ui_Address + 188);
+       devpriv->s_BoardInfos.dw_MolduleConfiguration[2] = ret;
+
+       ret = inl(devpriv->s_BoardInfos.ui_Address + 252);
+       devpriv->s_BoardInfos.dw_MolduleConfiguration[3] = ret;
+
+       // outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60);
+       outl(0x83838383, devpriv->s_BoardInfos.ui_Address + 0x60);
+
+       devpriv->s_BoardInfos.b_BoardVersion = 1;
+
+       // Enable the interrupt for the controler
+       dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address + 0x38);
+       outl(dw_Dummy | 0x2000, devpriv->s_BoardInfos.ui_Address + 0x38);
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function's Name   : __VOID__ v_APCI1710_InterruptFunction                  |
+|                              (BYTE b_Interrupt, __CPPARGS)                |
++----------------------------------------------------------------------------+
+| Task              : APCI-1710 interrupt function                           |
++----------------------------------------------------------------------------+
+| Input Parameters  : BYTE b_Interrupt : Interrupt number                    |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0 : OK                                                 |
+|                    -1 : Error                                              |
++----------------------------------------------------------------------------+
+*/
+
+VOID v_APCI1710_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+       BYTE b_ModuleCpt = 0;
+       BYTE b_InterruptFlag = 0;
+       BYTE b_PWMCpt = 0;
+       BYTE b_TorCounterCpt = 0;
+       BYTE b_PulseIncoderCpt = 0;
+       UINT ui_16BitValue;
+       ULONG ul_InterruptLatchReg = 0;
+       ULONG ul_LatchRegisterValue = 0;
+       ULONG ul_82X54InterruptStatus;
+       ULONG ul_StatusRegister;
+
+       str_ModuleInfo *ps_ModuleInfo;
+
+       printk("APCI1710 Interrupt\n");
+       for (b_ModuleCpt = 0; b_ModuleCpt < 4; b_ModuleCpt++, ps_ModuleInfo++) {
+
+                /**************************/
+               /* 1199/0225 to 0100/0226 */
+                /**************************/
+               ps_ModuleInfo = &devpriv->s_ModuleInfo[b_ModuleCpt];
+
+                /***********************/
+               /* Test if 82X54 timer */
+                /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModuleCpt] &
+                               0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+
+                       //printk("TIMER Interrupt Occurred\n");
+                       ul_82X54InterruptStatus = inl(devpriv->s_BoardInfos.
+                               ui_Address + 12 + (64 * b_ModuleCpt));
+
+                   /***************************/
+                       /* Test if interrupt occur */
+                   /***************************/
+
+                       if ((ul_82X54InterruptStatus & ps_ModuleInfo->
+                                       s_82X54ModuleInfo.
+                                       b_InterruptMask) != 0) {
+                               devpriv->
+                                       s_InterruptParameters.
+                                       s_FIFOInterruptParameters[devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write].
+                                       ul_OldInterruptMask =
+                                       (ul_82X54InterruptStatus &
+                                       ps_ModuleInfo->s_82X54ModuleInfo.
+                                       b_InterruptMask) << 4;
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       s_FIFOInterruptParameters[devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write].
+                                       b_OldModuleMask = 1 << b_ModuleCpt;
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       s_FIFOInterruptParameters[devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write].ul_OldCounterLatchValue = 0;
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       ul_InterruptOccur++;
+
+                      /****************************/
+                               /* Increment the write FIFO */
+                      /****************************/
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write = (devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write + 1) % APCI1710_SAVE_INTERRUPT;
+
+                               b_InterruptFlag = 1;
+
+                            /**********************/
+                               /* Call user function */
+                            /**********************/
+                               //Send a signal to from kernel to user space
+                               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+                       }       // if ((ul_82X54InterruptStatus & 0x7) != 0)
+               }               // 82X54 timer
+
+                /***************************/
+               /* Test if increm. counter */
+                /***************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModuleCpt] &
+                               0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
+
+                       ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
+                               ui_Address + (64 * b_ModuleCpt));
+
+                   /*********************/
+                       /* Test if interrupt */
+                   /*********************/
+
+                       if ((ul_InterruptLatchReg & 0x22) && (ps_ModuleInfo->
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister2 & 0x80)) {
+                      /************************************/
+                               /* Test if strobe latch I interrupt */
+                      /************************************/
+
+                               if (ul_InterruptLatchReg & 2) {
+                                       ul_LatchRegisterValue =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 4 +
+                                               (64 * b_ModuleCpt));
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].ul_OldInterruptMask =
+                                               1UL;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].b_OldModuleMask =
+                                               1 << b_ModuleCpt;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].
+                                               ul_OldCounterLatchValue =
+                                               ul_LatchRegisterValue;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ul_InterruptOccur++;
+
+                         /****************************/
+                                       /* 0899/0224 to 1199/0225   */
+                         /****************************/
+                                       /* Increment the write FIFO */
+                     /****************************/
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write = (devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write +
+                                               1) % APCI1710_SAVE_INTERRUPT;
+
+                                       b_InterruptFlag = 1;
+
+                               /**********************/
+                                       /* Call user function */
+                               /**********************/
+                                       //Send a signal to from kernel to user space
+                                       send_sig(SIGIO, devpriv->tsk_Current,
+                                               0);
+
+                               }
+
+                      /*************************************/
+                               /* Test if strobe latch II interrupt */
+                      /*************************************/
+
+                               if (ul_InterruptLatchReg & 0x20) {
+
+                                       ul_LatchRegisterValue =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 8 +
+                                               (64 * b_ModuleCpt));
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].ul_OldInterruptMask =
+                                               2UL;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].b_OldModuleMask =
+                                               1 << b_ModuleCpt;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].
+                                               ul_OldCounterLatchValue =
+                                               ul_LatchRegisterValue;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ul_InterruptOccur++;
+
+                         /****************************/
+                                       /* 0899/0224 to 1199/0225   */
+                         /****************************/
+                                       /* Increment the write FIFO */
+                         /****************************/
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write = (devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write +
+                                               1) % APCI1710_SAVE_INTERRUPT;
+
+                                       b_InterruptFlag = 1;
+
+                           /**********************/
+                                       /* Call user function */
+                               /**********************/
+                                       //Send a signal to from kernel to user space
+                                       send_sig(SIGIO, devpriv->tsk_Current,
+                                               0);
+
+                               }
+                       }
+
+                       ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
+                               ui_Address + 24 + (64 * b_ModuleCpt));
+
+                   /***************************/
+                       /* Test if index interrupt */
+                   /***************************/
+
+                       if (ul_InterruptLatchReg & 0x8) {
+                               ps_ModuleInfo->
+                                       s_SiemensCounterInfo.
+                                       s_InitFlag.b_IndexInterruptOccur = 1;
+
+                               if (ps_ModuleInfo->
+                                       s_SiemensCounterInfo.
+                                       s_ModeRegister.
+                                       s_ByteModeRegister.
+                                       b_ModeRegister2 &
+                                       APCI1710_INDEX_AUTO_MODE) {
+
+                                       outl(ps_ModuleInfo->
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               dw_ModeRegister1_2_3_4,
+                                               devpriv->s_BoardInfos.
+                                               ui_Address + 20 +
+                                               (64 * b_ModuleCpt));
+                               }
+
+                      /*****************************/
+                               /* Test if interrupt enabled */
+                      /*****************************/
+
+                               if ((ps_ModuleInfo->
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister3 &
+                                               APCI1710_ENABLE_INDEX_INT) ==
+                                       APCI1710_ENABLE_INDEX_INT) {
+                                       devpriv->s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].ul_OldInterruptMask =
+                                               4UL;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].b_OldModuleMask =
+                                               1 << b_ModuleCpt;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].
+                                               ul_OldCounterLatchValue =
+                                               ul_LatchRegisterValue;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ul_InterruptOccur++;
+
+                         /****************************/
+                                       /* 0899/0224 to 1199/0225   */
+                         /****************************/
+                                       /* Increment the write FIFO */
+                         /****************************/
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write = (devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write +
+                                               1) % APCI1710_SAVE_INTERRUPT;
+
+                                       b_InterruptFlag = 1;
+
+                               /**********************/
+                                       /* Call user function */
+                               /**********************/
+                                       //Send a signal to from kernel to user space
+                                       send_sig(SIGIO, devpriv->tsk_Current,
+                                               0);
+
+                               }
+                       }
+
+                   /*****************************/
+                       /* Test if compare interrupt */
+                   /*****************************/
+
+                       if (ul_InterruptLatchReg & 0x10) {
+                      /*****************************/
+                               /* Test if interrupt enabled */
+                      /*****************************/
+
+                               if ((ps_ModuleInfo->
+                                               s_SiemensCounterInfo.
+                                               s_ModeRegister.
+                                               s_ByteModeRegister.
+                                               b_ModeRegister3 &
+                                               APCI1710_ENABLE_COMPARE_INT) ==
+                                       APCI1710_ENABLE_COMPARE_INT) {
+                                       devpriv->s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].ul_OldInterruptMask =
+                                               8UL;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].b_OldModuleMask =
+                                               1 << b_ModuleCpt;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].
+                                               ul_OldCounterLatchValue =
+                                               ul_LatchRegisterValue;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ul_InterruptOccur++;
+
+                         /****************************/
+                                       /* 0899/0224 to 1199/0225   */
+                         /****************************/
+                                       /* Increment the write FIFO */
+                     /****************************/
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write = (devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write +
+                                               1) % APCI1710_SAVE_INTERRUPT;
+
+                                       b_InterruptFlag = 1;
+
+                               /**********************/
+                                       /* Call user function */
+                               /**********************/
+                                       //Send a signal to from kernel to user space
+                                       send_sig(SIGIO, devpriv->tsk_Current,
+                                               0);
+
+                               }
+                       }
+
+                   /*******************************************/
+                       /* Test if frequency measurement interrupt */
+                   /*******************************************/
+
+                       if (ul_InterruptLatchReg & 0x20) {
+                      /*******************/
+                               /* Read the status */
+                      /*******************/
+
+                               ul_StatusRegister = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 32 + (64 * b_ModuleCpt));
+
+                      /******************/
+                               /* Read the value */
+                      /******************/
+
+                               ul_LatchRegisterValue =
+                                       inl(devpriv->s_BoardInfos.ui_Address +
+                                       28 + (64 * b_ModuleCpt));
+
+                               switch ((ul_StatusRegister >> 1) & 3) {
+                               case 0:
+                              /*************************/
+                                       /* Test the counter mode */
+                              /*************************/
+
+                                       if ((devpriv->s_ModuleInfo[b_ModuleCpt].
+                                                       s_SiemensCounterInfo.
+                                                       s_ModeRegister.
+                                                       s_ByteModeRegister.
+                                                       b_ModeRegister1 &
+                                                       APCI1710_16BIT_COUNTER)
+                                               == APCI1710_16BIT_COUNTER) {
+                                 /****************************************/
+                                               /* Test if 16-bit counter 1 pulse occur */
+                                 /****************************************/
+
+                                               if ((ul_LatchRegisterValue &
+                                                               0xFFFFU) != 0) {
+                                                       ui_16BitValue =
+                                                               (UINT)
+                                                               ul_LatchRegisterValue
+                                                               & 0xFFFFU;
+                                                       ul_LatchRegisterValue =
+                                                               (ul_LatchRegisterValue
+                                                               & 0xFFFF0000UL)
+                                                               | (0xFFFFU -
+                                                               ui_16BitValue);
+                                               }
+
+                                 /****************************************/
+                                               /* Test if 16-bit counter 2 pulse occur */
+                                 /****************************************/
+
+                                               if ((ul_LatchRegisterValue &
+                                                               0xFFFF0000UL) !=
+                                                       0) {
+                                                       ui_16BitValue =
+                                                               (UINT) (
+                                                               (ul_LatchRegisterValue
+                                                                       >> 16) &
+                                                               0xFFFFU);
+                                                       ul_LatchRegisterValue =
+                                                               (ul_LatchRegisterValue
+                                                               & 0xFFFFUL) |
+                                                               ((0xFFFFU -
+                                                                       ui_16BitValue)
+                                                               << 16);
+                                               }
+                                       } else {
+                                               if (ul_LatchRegisterValue != 0) {
+                                                       ul_LatchRegisterValue =
+                                                               0xFFFFFFFFUL -
+                                                               ul_LatchRegisterValue;
+                                               }
+                                       }
+                                       break;
+
+                               case 1:
+                              /****************************************/
+                                       /* Test if 16-bit counter 2 pulse occur */
+                              /****************************************/
+
+                                       if ((ul_LatchRegisterValue &
+                                                       0xFFFF0000UL) != 0) {
+                                               ui_16BitValue =
+                                                       (UINT) (
+                                                       (ul_LatchRegisterValue
+                                                               >> 16) &
+                                                       0xFFFFU);
+                                               ul_LatchRegisterValue =
+                                                       (ul_LatchRegisterValue &
+                                                       0xFFFFUL) | ((0xFFFFU -
+                                                               ui_16BitValue)
+                                                       << 16);
+                                       }
+                                       break;
+
+                               case 2:
+                              /****************************************/
+                                       /* Test if 16-bit counter 1 pulse occur */
+                              /****************************************/
+
+                                       if ((ul_LatchRegisterValue & 0xFFFFU) !=
+                                               0) {
+                                               ui_16BitValue =
+                                                       (UINT)
+                                                       ul_LatchRegisterValue &
+                                                       0xFFFFU;
+                                               ul_LatchRegisterValue =
+                                                       (ul_LatchRegisterValue &
+                                                       0xFFFF0000UL) | (0xFFFFU
+                                                       - ui_16BitValue);
+                                       }
+                                       break;
+                               }
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       s_FIFOInterruptParameters[devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write].
+                                       ul_OldInterruptMask = 0x10000UL;
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       s_FIFOInterruptParameters[devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write].
+                                       b_OldModuleMask = 1 << b_ModuleCpt;
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       s_FIFOInterruptParameters[devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write].
+                                       ul_OldCounterLatchValue =
+                                       ul_LatchRegisterValue;
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       ul_InterruptOccur++;
+
+                      /****************************/
+                               /* 0899/0224 to 1199/0225   */
+                      /****************************/
+                               /* Increment the write FIFO */
+                      /****************************/
+
+                               devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write = (devpriv->
+                                       s_InterruptParameters.
+                                       ui_Write + 1) % APCI1710_SAVE_INTERRUPT;
+
+                               b_InterruptFlag = 1;
+
+                            /**********************/
+                               /* Call user function */
+                            /**********************/
+                               //Send a signal to from kernel to user space
+                               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+                       }
+               }               // Incremental counter
+
+                /***************/
+               /* Test if CDA */
+                /***************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModuleCpt] &
+                               0xFFFF0000UL) == APCI1710_CDA) {
+                   /******************************************/
+                       /* Test if CDA enable and functionality 0 */
+                   /******************************************/
+
+                       if ((devpriv->s_ModuleInfo[b_ModuleCpt].
+                                       s_CDAModuleInfo.
+                                       b_CDAEnable == APCI1710_ENABLE)
+                               && (devpriv->s_ModuleInfo[b_ModuleCpt].
+                                       s_CDAModuleInfo.b_FctSelection == 0)) {
+                      /****************************/
+                               /* Get the interrupt status */
+                      /****************************/
+
+                               ul_StatusRegister = inl(devpriv->s_BoardInfos.
+                                       ui_Address + 16 + (64 * b_ModuleCpt));
+                      /***************************/
+                               /* Test if interrupt occur */
+                      /***************************/
+
+                               if (ul_StatusRegister & 1) {
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].ul_OldInterruptMask =
+                                               0x80000UL;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].b_OldModuleMask =
+                                               1 << b_ModuleCpt;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].
+                                               ul_OldCounterLatchValue = 0;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ul_InterruptOccur++;
+
+                         /****************************/
+                                       /* Increment the write FIFO */
+                         /****************************/
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write = (devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write +
+                                               1) % APCI1710_SAVE_INTERRUPT;
+
+                                       b_InterruptFlag = 1;
+
+                               /**********************/
+                                       /* Call user function */
+                               /**********************/
+
+                                       //Send a signal to from kernel to user space
+                                       send_sig(SIGIO, devpriv->tsk_Current,
+                                               0);
+
+                               }       // if (ul_StatusRegister & 1)
+
+                       }
+               }               // CDA
+
+                /***********************/
+               /* Test if PWM counter */
+                /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModuleCpt] &
+                               0xFFFF0000UL) == APCI1710_PWM) {
+                       for (b_PWMCpt = 0; b_PWMCpt < 2; b_PWMCpt++) {
+                      /*************************************/
+                               /* Test if PWM interrupt initialised */
+                      /*************************************/
+
+                               if (devpriv->
+                                       s_ModuleInfo[b_ModuleCpt].
+                                       s_PWMModuleInfo.
+                                       s_PWMInfo[b_PWMCpt].
+                                       b_InterruptEnable == APCI1710_ENABLE) {
+                         /*****************************/
+                                       /* Read the interrupt status */
+                         /*****************************/
+
+                                       ul_StatusRegister =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 16 +
+                                               (20 * b_PWMCpt) +
+                                               (64 * b_ModuleCpt));
+
+                         /***************************/
+                                       /* Test if interrupt occur */
+                         /***************************/
+
+                                       if (ul_StatusRegister & 0x1) {
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       ul_OldInterruptMask =
+                                                       0x4000UL << b_PWMCpt;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       b_OldModuleMask =
+                                                       1 << b_ModuleCpt;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       ul_InterruptOccur++;
+
+                            /****************************/
+                                               /* Increment the write FIFO */
+                            /****************************/
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write = (devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write +
+                                                       1) %
+                                                       APCI1710_SAVE_INTERRUPT;
+
+                                               b_InterruptFlag = 1;
+
+                                  /**********************/
+                                               /* Call user function */
+                                  /**********************/
+                                               //Send a signal to from kernel to user space
+                                               send_sig(SIGIO,
+                                                       devpriv->tsk_Current,
+                                                       0);
+
+                                       }       // if (ul_StatusRegister & 0x1)
+                               }       // if (APCI1710_ENABLE)
+                       }       // for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++)
+               }               // PWM counter
+
+                /***********************/
+               /* Test if tor counter */
+                /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModuleCpt] &
+                               0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+                       for (b_TorCounterCpt = 0; b_TorCounterCpt < 2;
+                               b_TorCounterCpt++) {
+                      /*************************************/
+                               /* Test if tor interrupt initialised */
+                      /*************************************/
+
+                               if (devpriv->
+                                       s_ModuleInfo[b_ModuleCpt].
+                                       s_TorCounterModuleInfo.
+                                       s_TorCounterInfo[b_TorCounterCpt].
+                                       b_InterruptEnable == APCI1710_ENABLE) {
+                         /*****************************/
+                                       /* Read the interrupt status */
+                         /*****************************/
+
+                                       ul_StatusRegister =
+                                               inl(devpriv->s_BoardInfos.
+                                               ui_Address + 12 +
+                                               (16 * b_TorCounterCpt) +
+                                               (64 * b_ModuleCpt));
+
+                         /***************************/
+                                       /* Test if interrupt occur */
+                         /***************************/
+
+                                       if (ul_StatusRegister & 0x1) {
+                            /******************************/
+                                               /* Read the tor counter value */
+                            /******************************/
+
+                                               ul_LatchRegisterValue =
+                                                       inl(devpriv->
+                                                       s_BoardInfos.
+                                                       ui_Address + 0 +
+                                                       (16 * b_TorCounterCpt) +
+                                                       (64 * b_ModuleCpt));
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       ul_OldInterruptMask =
+                                                       0x1000UL <<
+                                                       b_TorCounterCpt;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       b_OldModuleMask =
+                                                       1 << b_ModuleCpt;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       ul_OldCounterLatchValue
+                                                       = ul_LatchRegisterValue;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       ul_InterruptOccur++;
+
+                            /****************************/
+                                               /* Increment the write FIFO */
+                            /****************************/
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write = (devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write +
+                                                       1) %
+                                                       APCI1710_SAVE_INTERRUPT;
+
+                                               b_InterruptFlag = 1;
+
+                                  /**********************/
+                                               /* Call user function */
+                                  /**********************/
+
+                                               //Send a signal to from kernel to user space
+                                               send_sig(SIGIO,
+                                                       devpriv->tsk_Current,
+                                                       0);
+                                       }       // if (ul_StatusRegister & 0x1)
+                               }       // if (APCI1710_ENABLE)
+                       }       // for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++)
+               }               // Tor counter
+
+                /***********************/
+               /* Test if chronometer */
+                /***********************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModuleCpt] &
+                               0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+
+                       //printk("APCI1710 Chrono Interrupt\n");
+                   /*****************************/
+                       /* Read the interrupt status */
+                   /*****************************/
+
+                       ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
+                               ui_Address + 12 + (64 * b_ModuleCpt));
+
+                   /***************************/
+                       /* Test if interrupt occur */
+                   /***************************/
+
+                       if ((ul_InterruptLatchReg & 0x8) == 0x8) {
+                      /****************************/
+                               /* Clear the interrupt flag */
+                      /****************************/
+
+                               outl(0, devpriv->s_BoardInfos.
+                                       ui_Address + 32 + (64 * b_ModuleCpt));
+
+                      /***************************/
+                               /* Test if continuous mode */
+                      /***************************/
+
+                               if (ps_ModuleInfo->
+                                       s_ChronoModuleInfo.
+                                       b_CycleMode == APCI1710_ENABLE) {
+                         /********************/
+                                       /* Clear the status */
+                         /********************/
+
+                                       outl(0, devpriv->s_BoardInfos.
+                                               ui_Address + 36 +
+                                               (64 * b_ModuleCpt));
+                               }
+
+                      /*************************/
+                               /* Read the timing value */
+                      /*************************/
+
+                               ul_LatchRegisterValue =
+                                       inl(devpriv->s_BoardInfos.ui_Address +
+                                       4 + (64 * b_ModuleCpt));
+
+                      /*****************************/
+                               /* Test if interrupt enabled */
+                      /*****************************/
+
+                               if (ps_ModuleInfo->
+                                       s_ChronoModuleInfo.b_InterruptMask) {
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].ul_OldInterruptMask =
+                                               0x80;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].b_OldModuleMask =
+                                               1 << b_ModuleCpt;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               s_FIFOInterruptParameters
+                                               [devpriv->s_InterruptParameters.
+                                               ui_Write].
+                                               ul_OldCounterLatchValue =
+                                               ul_LatchRegisterValue;
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ul_InterruptOccur++;
+
+                         /****************************/
+                                       /* Increment the write FIFO */
+                     /****************************/
+
+                                       devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write = (devpriv->
+                                               s_InterruptParameters.
+                                               ui_Write +
+                                               1) % APCI1710_SAVE_INTERRUPT;
+
+                                       b_InterruptFlag = 1;
+
+                               /**********************/
+                                       /* Call user function */
+                               /**********************/
+                                       //Send a signal to from kernel to user space
+                                       send_sig(SIGIO, devpriv->tsk_Current,
+                                               0);
+
+                               }
+                       }
+               }               // Chronometer
+
+                /*************************/
+               /* Test if pulse encoder */
+                /*************************/
+
+               if ((devpriv->s_BoardInfos.
+                               dw_MolduleConfiguration[b_ModuleCpt] &
+                               0xFFFF0000UL) == APCI1710_PULSE_ENCODER) {
+                   /****************************/
+                       /* Read the status register */
+                   /****************************/
+
+                       ul_StatusRegister = inl(devpriv->s_BoardInfos.
+                               ui_Address + 20 + (64 * b_ModuleCpt));
+
+                       if (ul_StatusRegister & 0xF) {
+                               for (b_PulseIncoderCpt = 0;
+                                       b_PulseIncoderCpt < 4;
+                                       b_PulseIncoderCpt++) {
+                         /*************************************/
+                                       /* Test if pulse encoder initialised */
+                         /*************************************/
+
+                                       if ((ps_ModuleInfo->
+                                                       s_PulseEncoderModuleInfo.
+                                                       s_PulseEncoderInfo
+                                                       [b_PulseIncoderCpt].
+                                                       b_PulseEncoderInit == 1)
+                                               && (((ps_ModuleInfo->s_PulseEncoderModuleInfo.dw_SetRegister >> b_PulseIncoderCpt) & 1) == 1) && (((ul_StatusRegister >> (b_PulseIncoderCpt)) & 1) == 1)) {
+                                               devpriv->s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       ul_OldInterruptMask =
+                                                       0x100UL <<
+                                                       b_PulseIncoderCpt;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       b_OldModuleMask =
+                                                       1 << b_ModuleCpt;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       s_FIFOInterruptParameters
+                                                       [devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write].
+                                                       ul_OldCounterLatchValue
+                                                       = ul_LatchRegisterValue;
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       ul_InterruptOccur++;
+
+                            /****************************/
+                                               /* 0899/0224 to 1199/0225   */
+                            /****************************/
+                                               /* Increment the write FIFO */
+                            /****************************/
+
+                                               devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write = (devpriv->
+                                                       s_InterruptParameters.
+                                                       ui_Write +
+                                                       1) %
+                                                       APCI1710_SAVE_INTERRUPT;
+
+                                               b_InterruptFlag = 1;
+
+                                  /**********************/
+                                               /* Call user function */
+                                  /**********************/
+                                               //Send a signal to from kernel to user space
+                                               send_sig(SIGIO,
+                                                       devpriv->tsk_Current,
+                                                       0);
+
+                                       }
+                               }
+                       }
+               }               //pulse encoder
+
+       }
+       return;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
new file mode 100644 (file)
index 0000000..8b9d77e
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#define COMEDI_SUBD_TTLIO                              11      /* Digital Input Output But TTL */
+#define COMEDI_SUBD_PWM                                        12      /* Pulse width Measurement */
+#define COMEDI_SUBD_SSI                                        13      /* Synchronous serial interface */
+#define COMEDI_SUBD_TOR                                        14      /* Tor counter */
+#define COMEDI_SUBD_CHRONO              15     /* Chrono meter */
+#define COMEDI_SUBD_PULSEENCODER        16     /* Pulse Encoder INP CPT */
+#define COMEDI_SUBD_INCREMENTALCOUNTER  17     /* Incremental Counter */
+
+#define      APCI1710_BOARD_NAME                         "apci1710"
+#define      APCI1710_BOARD_VENDOR_ID    0x10E8
+#define      APCI1710_BOARD_DEVICE_ID    0x818F
+#define      APCI1710_ADDRESS_RANGE        256
+#define      APCI1710_CONFIG_ADDRESS_RANGE 8
+#define      APCI1710_INCREMENTAL_COUNTER  0x53430000UL
+#define      APCI1710_SSI_COUNTER          0x53490000UL
+#define      APCI1710_TTL_IO               0x544C0000UL
+#define      APCI1710_DIGITAL_IO           0x44490000UL
+#define      APCI1710_82X54_TIMER          0x49430000UL
+#define      APCI1710_CHRONOMETER          0x43480000UL
+#define      APCI1710_PULSE_ENCODER          0x495A0000UL
+#define      APCI1710_TOR_COUNTER            0x544F0000UL
+#define      APCI1710_PWM                    0x50570000UL
+#define      APCI1710_ETM                    0x45540000UL
+#define      APCI1710_CDA                    0x43440000UL
+#define      APCI1710_DISABLE              0
+#define      APCI1710_ENABLE               1
+#define      APCI1710_SYNCHRONOUS_MODE     1
+#define      APCI1710_ASYNCHRONOUS_MODE    0
+
+//MODULE INFO STRUCTURE
+
+static const comedi_lrange range_apci1710_ttl = { 4, {
+                       BIP_RANGE(10),
+                       BIP_RANGE(5),
+                       BIP_RANGE(2),
+                       BIP_RANGE(1)
+       }
+};
+
+static const comedi_lrange range_apci1710_ssi = { 4, {
+                       BIP_RANGE(10),
+                       BIP_RANGE(5),
+                       BIP_RANGE(2),
+                       BIP_RANGE(1)
+       }
+};
+
+static const comedi_lrange range_apci1710_inccpt = { 4, {
+                       BIP_RANGE(10),
+                       BIP_RANGE(5),
+                       BIP_RANGE(2),
+                       BIP_RANGE(1)
+       }
+};
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
new file mode 100644 (file)
index 0000000..f10ea4b
--- /dev/null
@@ -0,0 +1,600 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-035        | Compiler   : GCC                      |
+  | Module name : hwdrv_apci035.c | Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-035                     |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci035.h"
+INT i_WatchdogNbr = 0;
+INT i_Temp = 0;
+INT i_Flag = 1;
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI035_ConfigTimerWatchdog                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Timer , Counter or Watchdog             |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[0]            : 0 Configure As Timer      |
+|                                                                                 1 Configure As Watchdog   |
+                              data[1]            : Watchdog number
+|                                        data[2]            : Time base Unit            |
+|                                        data[3]                        : Reload Value                      |
+                              data[4]            : External Trigger          |
+                                                   1:Enable
+                                                   0:Disable
+                              data[5]            :External Trigger Level
+                                                  00 Trigger Disabled
+                                                  01 Trigger Enabled (Low level)
+                                                  10 Trigger Enabled (High Level)
+                                                  11 Trigger Enabled (High/Low level)
+                              data[6]            : External Gate            |
+                                                   1:Enable
+                                                   0:Disable
+                              data[7]            : External Gate level
+                                                  00 Gate Disabled
+                                                  01 Gate Enabled (Low level)
+                                                  10 Gate Enabled (High Level)
+                              data[8]            :Warning Relay
+                                                  1: ENABLE
+                                                  0: DISABLE
+                              data[9]            :Warning Delay available
+                              data[10]           :Warning Relay Time unit
+                              data[11]           :Warning Relay Time Reload value
+                              data[12]           :Reset Relay
+                                                  1 : ENABLE
+                                                  0 : DISABLE
+                              data[13]           :Interrupt
+                                                  1 : ENABLE
+                                                  0 : DISABLE
+
+|
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Status = 0;
+       UINT ui_Command = 0;
+       UINT ui_Mode = 0;
+       i_Temp = 0;
+       devpriv->tsk_Current = current;
+       devpriv->b_TimerSelectMode = data[0];
+       i_WatchdogNbr = data[1];
+       if (data[0] == 0) {
+               ui_Mode = 2;
+       } else {
+               ui_Mode = 0;
+       }
+//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
+       ui_Command = 0;
+//ui_Command = ui_Command & 0xFFFFF9FEUL;
+       outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       ui_Command = 0;
+       ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/************************/
+/* Set the reload value */
+/************************/
+       outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
+/*********************/
+/* Set the time unit */
+/*********************/
+       outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
+       if (data[0] == ADDIDATA_TIMER) {
+
+                /******************************/
+               /* Set the mode :             */
+               /* - Disable the hardware     */
+               /* - Disable the counter mode */
+               /* - Disable the warning      */
+               /* - Disable the reset        */
+               /* - Enable the timer mode    */
+               /* - Set the timer mode       */
+                /******************************/
+
+               ui_Command =
+                       (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
+
+       }                       //if (data[0] == ADDIDATA_TIMER)
+       else {
+               if (data[0] == ADDIDATA_WATCHDOG) {
+
+                /******************************/
+                       /* Set the mode :             */
+                       /* - Disable the hardware     */
+                       /* - Disable the counter mode */
+                       /* - Disable the warning      */
+                       /* - Disable the reset        */
+                       /* - Disable the timer mode   */
+                /******************************/
+
+                       ui_Command = ui_Command & 0xFFF819E2UL;
+
+               } else {
+                       printk("\n The parameter for Timer/watchdog selection is in error\n");
+                       return -EINVAL;
+               }
+       }
+       outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       ui_Command = 0;
+       ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/********************************/
+/* Disable the hardware trigger */
+/********************************/
+       ui_Command = ui_Command & 0xFFFFF89FUL;
+       if (data[4] == ADDIDATA_ENABLE) {
+    /**********************************/
+               /* Set the hardware trigger level */
+    /**********************************/
+               ui_Command = ui_Command | (data[5] << 5);
+       }
+       outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       ui_Command = 0;
+       ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/*****************************/
+/* Disable the hardware gate */
+/*****************************/
+       ui_Command = ui_Command & 0xFFFFF87FUL;
+       if (data[6] == ADDIDATA_ENABLE) {
+/*******************************/
+/* Set the hardware gate level */
+/*******************************/
+               ui_Command = ui_Command | (data[7] << 7);
+       }
+       outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       ui_Command = 0;
+       ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/*******************************/
+/* Disable the hardware output */
+/*******************************/
+       ui_Command = ui_Command & 0xFFFFF9FBUL;
+/*********************************/
+/* Set the hardware output level */
+/*********************************/
+       ui_Command = ui_Command | (data[8] << 2);
+       outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       if (data[9] == ADDIDATA_ENABLE) {
+   /************************/
+               /* Set the reload value */
+   /************************/
+               outl(data[11],
+                       devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
+   /**********************/
+               /* Set the time unite */
+   /**********************/
+               outl(data[10],
+                       devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
+       }
+
+       ui_Command = 0;
+       ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ /*******************************/
+       /* Disable the hardware output */
+ /*******************************/
+       ui_Command = ui_Command & 0xFFFFF9F7UL;
+   /*********************************/
+       /* Set the hardware output level */
+   /*********************************/
+       ui_Command = ui_Command | (data[12] << 3);
+       outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ /*************************************/
+ /**  Enable the watchdog interrupt  **/
+ /*************************************/
+       ui_Command = 0;
+       ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/*******************************/
+/* Set the interrupt selection */
+/*******************************/
+       ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
+
+       ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
+       outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI035_StartStopWriteTimerWatchdog              |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Start / Stop The Selected Timer , or Watchdog  |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                                       |
+|                                        data[0] : 0 - Stop Selected Timer/Watchdog     |
+|                                                  1 - Start Selected Timer/Watchdog    |
+|                                                  2 - Trigger Selected Timer/Watchdog  |
+|                                                  3 - Stop All Timer/Watchdog          |
+|                                                  4 - Start All Timer/Watchdog         |
+|                                                  5 - Trigger All Timer/Watchdog       |
+|                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error                      |
+|                                                                                       |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Command = 0;
+       INT i_Count = 0;
+       if (data[0] == 1) {
+               ui_Command =
+                       inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+        /**********************/
+               /* Start the hardware */
+        /**********************/
+               ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
+               outl(ui_Command,
+                       devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       }                       // if  (data[0]==1)
+       if (data[0] == 2) {
+               ui_Command =
+                       inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+        /***************************/
+               /* Set the trigger command */
+        /***************************/
+               ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
+               outl(ui_Command,
+                       devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       }
+
+       if (data[0] == 0)       //Stop The Watchdog
+       {
+               //Stop The Watchdog
+               ui_Command = 0;
+               //ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
+               //ui_Command = ui_Command & 0xFFFFF9FEUL;
+               outl(ui_Command,
+                       devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+       }                       //  if (data[1]==0)
+       if (data[0] == 3)       //stop all Watchdogs
+       {
+               ui_Command = 0;
+               for (i_Count = 1; i_Count <= 4; i_Count++) {
+                       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+                               ui_Command = 0x2UL;
+                       } else {
+                               ui_Command = 0x10UL;
+                       }
+                       i_WatchdogNbr = i_Count;
+                       outl(ui_Command,
+                               devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
+                               0);
+               }
+
+       }
+       if (data[0] == 4)       //start all Watchdogs
+       {
+               ui_Command = 0;
+               for (i_Count = 1; i_Count <= 4; i_Count++) {
+                       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+                               ui_Command = 0x1UL;
+                       } else {
+                               ui_Command = 0x8UL;
+                       }
+                       i_WatchdogNbr = i_Count;
+                       outl(ui_Command,
+                               devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
+                               0);
+               }
+       }
+       if (data[0] == 5)       //trigger all Watchdogs
+       {
+               ui_Command = 0;
+               for (i_Count = 1; i_Count <= 4; i_Count++) {
+                       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+                               ui_Command = 0x4UL;
+                       } else {
+                               ui_Command = 0x20UL;
+                       }
+
+                       i_WatchdogNbr = i_Count;
+                       outl(ui_Command,
+                               devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
+                               0);
+               }
+               i_Temp = 1;
+       }
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI035_ReadTimerWatchdog                        |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read The Selected Timer , Counter or Watchdog          |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  data[0]            : software trigger status
+              data[1]            : hardware trigger status
+|                              data[2]            : Software clear status
+                        data[3]            : Overflow status
+                     data[4]            : Timer actual value
+
+
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Status = 0;     // Status register
+       i_WatchdogNbr = insn->unused[0];
+             /******************/
+       /* Get the status */
+             /******************/
+       ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
+      /***********************************/
+       /* Get the software trigger status */
+      /***********************************/
+       data[0] = ((ui_Status >> 1) & 1);
+      /***********************************/
+       /* Get the hardware trigger status */
+      /***********************************/
+       data[1] = ((ui_Status >> 2) & 1);
+      /*********************************/
+       /* Get the software clear status */
+      /*********************************/
+       data[2] = ((ui_Status >> 3) & 1);
+      /***************************/
+       /* Get the overflow status */
+      /***************************/
+       data[3] = ((ui_Status >> 0) & 1);
+       if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+               data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
+
+       }                       //  if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : INT i_APCI035_ConfigAnalogInput                        |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Analog Input Subdevice                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s     : Subdevice Pointer            |
+|                     comedi_insn *insn       : Insn Structure Pointer       |
+|                     lsampl_t *data          : Data Pointer contains        |
+|                                          configuration parameters as below |
+|                     data[0]                  : Warning delay value
+|                                                                            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       devpriv->tsk_Current = current;
+       outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
+       outl(0, devpriv->iobase + 128 + 0);
+/********************************/
+/* Initialise the warning value */
+/********************************/
+       outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
+       outl((data[0] << 8), devpriv->iobase + 128 + 0);
+       outl(0x200000UL, devpriv->iobase + 128 + 12);
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI035_ReadAnalogInput                          |
+|                                (comedi_device *dev,comedi_subdevice *s,       |
+|                     comedi_insn *insn,lsampl_t *data)                      |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel                              |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
+|                                data[0]  : Digital Value Of Input              |
+|                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_CommandRegister = 0;
+/******************/
+/*  Set the start */
+/******************/
+       ui_CommandRegister = 0x80000;
+ /******************************/
+       /* Write the command register */
+ /******************************/
+       outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
+
+/***************************************/
+/* Read the digital value of the input */
+/***************************************/
+       data[0] = inl(devpriv->iobase + 128 + 28);
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   :  int i_APCI035_Reset(comedi_device *dev)                      |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :Resets the registers of the card                        |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                        |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                                       |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_Reset(comedi_device * dev)
+{
+       INT i_Count = 0;
+       for (i_Count = 1; i_Count <= 4; i_Count++) {
+               i_WatchdogNbr = i_Count;
+               outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);    //stop all timers
+       }
+       outl(0x0, devpriv->iobase + 128 + 12);  //Disable the warning delay
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : static void v_APCI035_Interrupt                                       |
+|                                        (int irq , void *d)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt processing Routine                           |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+static void v_APCI035_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+       UINT ui_StatusRegister1 = 0;
+       UINT ui_StatusRegister2 = 0;
+       UINT ui_ReadCommand = 0;
+       UINT ui_ChannelNumber = 0;
+       UINT ui_DigitalTemperature = 0;
+       if (i_Temp == 1) {
+               i_WatchdogNbr = i_Flag;
+               i_Flag = i_Flag + 1;
+       }
+  /**************************************/
+       /* Read the interrupt status register of temperature Warning */
+  /**************************************/
+       ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
+  /**************************************/
+       /* Read the interrupt status register for Watchdog/timer */
+   /**************************************/
+
+       ui_StatusRegister2 =
+               inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
+
+       if ((((ui_StatusRegister1) & 0x8) == 0x8))      //Test if warning relay interrupt
+       {
+       /**********************************/
+               /* Disable the temperature warning */
+       /**********************************/
+               ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
+               ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
+               outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
+      /***************************/
+               /* Read the channel number */
+      /***************************/
+               ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
+       /**************************************/
+               /* Read the digital temperature value */
+       /**************************************/
+               ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
+               send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+       }                       //if (((ui_StatusRegister1 & 0x8) == 0x8))
+
+       else {
+               if ((ui_StatusRegister2 & 0x1) == 0x1) {
+                       send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+               }
+       }                       //else if (((ui_StatusRegister1 & 0x8) == 0x8))
+
+       return;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
new file mode 100644 (file)
index 0000000..be57557
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+// Card Specific information
+#define APCI035_BOARD_VENDOR_ID                 0x15B8
+#define APCI035_ADDRESS_RANGE                   255
+
+INT i_TW_Number;
+struct {
+       INT i_Gain;
+       INT i_Polarity;
+       INT i_OffsetRange;
+       INT i_Coupling;
+       INT i_SingleDiff;
+       INT i_AutoCalibration;
+       UINT ui_ReloadValue;
+       UINT ui_TimeUnitReloadVal;
+       INT i_Interrupt;
+       INT i_ModuleSelection;
+} Config_Parameters_Main;
+
+//ANALOG INPUT RANGE
+comedi_lrange range_apci035_ai = { 8, {
+                       BIP_RANGE(10),
+                       BIP_RANGE(5),
+                       BIP_RANGE(2),
+                       BIP_RANGE(1),
+                       UNI_RANGE(10),
+                       UNI_RANGE(5),
+                       UNI_RANGE(2),
+                       UNI_RANGE(1)
+       }
+};
+
+// Timer / Watchdog Related Defines
+
+#define APCI035_TCW_SYNC_ENABLEDISABLE           0
+#define APCI035_TCW_RELOAD_VALUE                 4
+#define APCI035_TCW_TIMEBASE                     8
+#define APCI035_TCW_PROG                         12
+#define APCI035_TCW_TRIG_STATUS                  16
+#define APCI035_TCW_IRQ                          20
+#define APCI035_TCW_WARN_TIMEVAL                 24
+#define APCI035_TCW_WARN_TIMEBASE                28
+
+#define ADDIDATA_TIMER                            0
+//#define ADDIDATA_WATCHDOG                         1
+
+#define APCI035_TW1                               0
+#define APCI035_TW2                               32
+#define APCI035_TW3                               64
+#define APCI035_TW4                               96
+
+#define APCI035_AI_OFFSET                        0
+#define APCI035_TEMP                             128
+#define APCI035_ALR_SEQ                          4
+#define APCI035_START_STOP_INDEX                 8
+#define APCI035_ALR_START_STOP                   12
+#define APCI035_ALR_IRQ                          16
+#define APCI035_EOS                              20
+#define APCI035_CHAN_NO                          24
+#define APCI035_CHAN_VAL                         28
+#define APCI035_CONV_TIME_TIME_BASE              36
+#define APCI035_RELOAD_CONV_TIME_VAL             32
+#define APCI035_DELAY_TIME_TIME_BASE             44
+#define APCI035_RELOAD_DELAY_TIME_VAL            40
+#define ENABLE_EXT_TRIG                          1
+#define ENABLE_EXT_GATE                          2
+#define ENABLE_EXT_TRIG_GATE                     3
+
+#define ANALOG_INPUT                             0
+#define TEMPERATURE                              1
+#define RESISTANCE                               2
+
+#define ADDIDATA_GREATER_THAN_TEST               0
+#define ADDIDATA_LESS_THAN_TEST                  1
+
+#define APCI035_MAXVOLT                         2.5
+
+#define ADDIDATA_UNIPOLAR                        1
+#define ADDIDATA_BIPOLAR                         2
+
+//ADDIDATA Enable Disable
+#define ADDIDATA_ENABLE                            1
+#define ADDIDATA_DISABLE                           0
+
+// Hardware Layer  functions for Apci035
+
+// TIMER
+// timer value is passed as u seconds
+INT i_APCI035_ConfigTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+INT i_APCI035_ReadTimerWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//Temperature Related Defines (Analog Input Subdevice)
+
+INT i_APCI035_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI035_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//Interrupt
+static void v_APCI035_Interrupt(int irq, void *d);
+
+//Reset functions
+INT i_APCI035_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
new file mode 100644 (file)
index 0000000..b9fa997
--- /dev/null
@@ -0,0 +1,285 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-1032       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci1032.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-1032                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci1032.h"
+#include <linux/delay.h>
+//Global variables
+UINT ui_InterruptStatus = 0;
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1032_ConfigDigitalInput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures the digital input Subdevice                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     lsampl_t *data         : Data Pointer contains         |
+|                                          configuration parameters as below |
+|                                                                            |
+|                        data[0]            : 1 Enable  Digital Input Interrupt |
+|                                                                 0 Disable Digital Input Interrupt |
+|                        data[1]            : 0 ADDIDATA Interrupt OR LOGIC     |
+|                                                               : 1 ADDIDATA Interrupt AND LOGIC    |
+|                        data[2]                        : Interrupt mask for the mode 1         |
+|                        data[3]                        : Interrupt mask for the mode 2         |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_TmpValue;
+
+       ULONG ul_Command1 = 0;
+       ULONG ul_Command2 = 0;
+       devpriv->tsk_Current = current;
+
+  /*******************************/
+       /* Set the digital input logic */
+  /*******************************/
+       if (data[0] == ADDIDATA_ENABLE) {
+               ul_Command1 = ul_Command1 | data[2];
+               ul_Command2 = ul_Command2 | data[3];
+               outl(ul_Command1,
+                       devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
+               outl(ul_Command2,
+                       devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+               if (data[1] == ADDIDATA_OR) {
+                       outl(0x4, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+                       ui_TmpValue =
+                               inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+               }               //if (data[1] == ADDIDATA_OR)
+               else {
+                       outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+               }               //else if(data[1] == ADDIDATA_OR)
+       }                       // if( data[0] == ADDIDATA_ENABLE)
+       else {
+               ul_Command1 = ul_Command1 & 0xFFFF0000;
+               ul_Command2 = ul_Command2 & 0xFFFF0000;
+               outl(ul_Command1,
+                       devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
+               outl(ul_Command2,
+                       devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+               outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+       }                       //else if  ( data[0] == ADDIDATA_ENABLE)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1032_Read1DigitalInput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the digital input                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                            UINT ui_Channel : Channel number to read       |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_TmpValue = 0;
+       UINT ui_Channel;
+       ui_Channel = CR_CHAN(insn->chanspec);
+       if (ui_Channel >= 0 && ui_Channel <= 31) {
+               ui_TmpValue = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+               //  since only 1 channel reqd  to bring it to last bit it is rotated
+               //  8 +(chan - 1) times then ANDed with 1 for last bit.
+               *data = (ui_TmpValue >> ui_Channel) & 0x1;
+       }                       //if(ui_Channel >= 0 && ui_Channel <=31)
+       else {
+               //comedi_error(dev," \n chan spec wrong\n");
+               return -EINVAL; // "sorry channel spec wrong "
+       }                       //else if(ui_Channel >= 0 && ui_Channel <=31)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1032_ReadMoreDigitalInput                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                     comedi_insn *insn,lsampl_t *data)                      |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the Requested digital inputs      |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+|                      UINT *data             : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1032_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_PortValue = data[0];
+       UINT ui_Mask = 0;
+       UINT ui_NoOfChannels;
+
+       ui_NoOfChannels = CR_CHAN(insn->chanspec);
+       if (data[1] == 0) {
+               *data = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+               switch (ui_NoOfChannels) {
+               case 2:
+                       ui_Mask = 3;
+                       *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 4:
+                       ui_Mask = 15;
+                       *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 8:
+                       ui_Mask = 255;
+                       *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 16:
+                       ui_Mask = 65535;
+                       *data = (*data >> (16 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 31:
+                       break;
+               default:
+                       //comedi_error(dev," \nchan spec wrong\n");
+                       return -EINVAL; // "sorry channel spec wrong "
+                       break;
+               }               //switch(ui_NoOfChannels)
+       }                       //if(data[1]==0)
+       else {
+               if (data[1] == 1) {
+                       *data = ui_InterruptStatus;
+               }               //if(data[1]==1)
+       }                       //else if(data[1]==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : static void v_APCI1032_Interrupt                                      |
+|                                        (int irq , void *d)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt handler for the interruptible digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                   |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                           |
++----------------------------------------------------------------------------+
+*/
+static VOID v_APCI1032_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+
+       UINT ui_Temp;
+       //disable the interrupt
+       ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+       outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE,
+               devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+       ui_InterruptStatus =
+               inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);
+       ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF;
+       send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+       outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);       //enable the interrupt
+       return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1032_Reset(comedi_device *dev)               |                                                       |
++----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1032_Reset(comedi_device * dev)
+{
+       outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);   //disable the interrupts
+       inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);    //Reset the interrupt status register
+       outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);       //Disable the and/or interrupt
+       outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
new file mode 100644 (file)
index 0000000..d5683dc
--- /dev/null
@@ -0,0 +1,70 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+/*********      Definitions for APCI-1032 card  *****/
+
+#define APCI1032_BOARD_VENDOR_ID 0x15B8
+#define APCI1032_ADDRESS_RANGE  20
+//DIGITAL INPUT DEFINE
+
+#define APCI1032_DIGITAL_IP                     0
+#define APCI1032_DIGITAL_IP_INTERRUPT_MODE1     4
+#define APCI1032_DIGITAL_IP_INTERRUPT_MODE2     8
+#define APCI1032_DIGITAL_IP_IRQ                 16
+
+//Digital Input IRQ Function Selection
+#define ADDIDATA_OR                  0
+#define ADDIDATA_AND                 1
+
+//Digital Input Interrupt Status
+#define APCI1032_DIGITAL_IP_INTERRUPT_STATUS    12
+
+//Digital Input Interrupt Enable Disable.
+#define APCI1032_DIGITAL_IP_INTERRUPT_ENABLE    0x4
+#define APCI1032_DIGITAL_IP_INTERRUPT_DISABLE   0xFFFFFFFB
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE                            1
+#define ADDIDATA_DISABLE                           0
+
+// Hardware Layer  functions for Apci1032
+
+//DI
+// for di read
+
+INT i_APCI1032_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1032_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+INT i_APCI1032_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// Interrupt functions.....
+
+static VOID v_APCI1032_Interrupt(int irq, void *d);
+//Reset
+INT i_APCI1032_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
new file mode 100644 (file)
index 0000000..ff7284d
--- /dev/null
@@ -0,0 +1,3045 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-1500       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci1500.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-1500                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+#include "hwdrv_apci1500.h"
+
+int i_TimerCounter1Init = 0;
+int i_TimerCounter2Init = 0;
+int i_WatchdogCounter3Init = 0;
+int i_Event1Status = 0, i_Event2Status = 0;
+int i_TimerCounterWatchdogInterrupt = 0;
+int i_Logic = 0, i_CounterLogic = 0;
+int i_InterruptMask = 0;
+int i_InputChannel = 0;
+int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+       0, i_WatchdogCounter3Enabled = 0;
+
+/*
+  +----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_ConfigDigitalInputEvent                 |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : An event can be generated for each port.               |
+|                     The first event is related to the first 8 channels     |
+|                     (port 1) and the second to the following 6 channels    |
+|                     (port 2). An interrupt is generated when one or both   |
+|                     events have occurred                                   |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     lsampl_t *data     : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                        data[0]            :Number of the input port on        |
+|                                         which the event will take place    |
+|                                         (1 or 2)
+                      data[1]            : The event logic for port 1 has    |
+|                                            three possibilities             |
+|                                        :0  APCI1500_AND       :This logic  |
+|                                                                links       |
+|                                                                the inputs  |
+|                                                                with an AND |
+|                                                                logic.      |
+|                                          1 APCI1500_OR        :This logic  |
+|                                                                links       |
+|                                                                the inputs  |
+|                                                                with a      |
+|                                                                OR logic.   |
+|                                          2    APCI1500_OR_PRIORITY        |
+|                                                              :This logic                          |
+|                                                                links       |
+|                                                                the inputs  |
+|                                                                with a      |
+|                                                                priority    |
+|                                                                OR logic.   |
+|                                                                Input 1     |
+|                                                                has the     |
+|                                                                highest     |
+|                                                                priority    |
+|                                                                level and   |
+|                                                                input   8   |
+|                                                                the smallest|
+|                                            For the second port the user has|
+|                                            1 possibility:                  |
+|                                            APCI1500_OR        :This logic  |
+|                                                                links       |
+|                                                                the inputs  |
+|                                                                with a      |
+|                                                                polarity    |
+|                                                                OR logic    |
+|                     data[2]              : These 8-character word for port1|
+|                                            and 6-character word for port 2 |
+|                                            give the mask of the event.     |
+|                                            Each place gives the state      |
+|                                            of the input channels and can   |
+|                                            have one of these six characters|
+|                                                     |
+|                                       0  : This input must be on 0         |
+|                                       1  : This input must be on 1         |
+|                                       2  : This input reacts to            |
+|                                            a falling edge                  |
+|                                       3  : This input reacts to a          |
+|                                            rising edge                     |
+|                                       4  : This input reacts to both edges |
+|
+|                                                              5  : This input is not               |
+|                                            used for event                             |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+       int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
+       int i_PatternTransitionCount = 0, i_RegValue;
+       int i;
+
+      /*************************************************/
+       /* Selects the master interrupt control register */
+      /*************************************************/
+       outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+      /**********************************************/
+       /* Disables  the main interrupt on the board */
+      /**********************************************/
+       outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       if (data[0] == 1) {
+               i_MaxChannel = 8;
+       }                       // if (data[0] == 1)
+       else {
+               if (data[0] == 2) {
+                       i_MaxChannel = 6;
+               }               // if(data[0]==2)
+               else {
+                       printk("\nThe specified port event  does not exist\n");
+                       return -EINVAL;
+               }               //else if(data[0]==2)
+       }                       //else  if (data[0] == 1)
+       switch (data[1]) {
+       case 0:
+               data[1] = APCI1500_AND;
+               break;
+       case 1:
+               data[1] = APCI1500_OR;
+               break;
+       case 2:
+               data[1] = APCI1500_OR_PRIORITY;
+               break;
+       default:
+               printk("\nThe specified interrupt logic does not exist\n");
+               return -EINVAL;
+       }                       //switch(data[1]);
+
+       i_Logic = data[1];
+       for (i_Count = i_MaxChannel, i = 0; i_Count > 0; i_Count--, i++) {
+               i_EventMask = data[2 + i];
+               switch (i_EventMask) {
+               case 0:
+                       i_PatternMask =
+                               i_PatternMask | (1 << (i_MaxChannel - i_Count));
+                       break;
+               case 1:
+                       i_PatternMask =
+                               i_PatternMask | (1 << (i_MaxChannel - i_Count));
+                       i_PatternPolarity =
+                               i_PatternPolarity | (1 << (i_MaxChannel -
+                                       i_Count));
+                       break;
+               case 2:
+                       i_PatternMask =
+                               i_PatternMask | (1 << (i_MaxChannel - i_Count));
+                       i_PatternTransition =
+                               i_PatternTransition | (1 << (i_MaxChannel -
+                                       i_Count));
+                       break;
+               case 3:
+                       i_PatternMask =
+                               i_PatternMask | (1 << (i_MaxChannel - i_Count));
+                       i_PatternPolarity =
+                               i_PatternPolarity | (1 << (i_MaxChannel -
+                                       i_Count));
+                       i_PatternTransition =
+                               i_PatternTransition | (1 << (i_MaxChannel -
+                                       i_Count));
+                       break;
+               case 4:
+                       i_PatternTransition =
+                               i_PatternTransition | (1 << (i_MaxChannel -
+                                       i_Count));
+                       break;
+               case 5:
+                       break;
+               default:
+                       printk("\nThe option indicated in the event mask does not exist\n");
+                       return -EINVAL;
+               }               // switch(i_EventMask)
+       }                       //for (i_Count = i_MaxChannel; i_Count >0;i_Count --)
+
+       if (data[0] == 1) {
+                   /****************************/
+               /* Test the interrupt logic */
+                   /****************************/
+
+               if (data[1] == APCI1500_AND ||
+                       data[1] == APCI1500_OR ||
+                       data[1] == APCI1500_OR_PRIORITY) {
+                      /**************************************/
+                       /* Tests if a transition was declared */
+                       /* for a OR PRIORITY logic            */
+                      /**************************************/
+
+                       if (data[1] == APCI1500_OR_PRIORITY
+                               && i_PatternTransition != 0) {
+                             /********************************************/
+                               /* Transition error on an OR PRIORITY logic */
+                             /********************************************/
+                               printk("\nTransition error on an OR PRIORITY logic\n");
+                               return -EINVAL;
+                       }       // if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0)
+
+                      /*************************************/
+                       /* Tests if more than one transition */
+                       /* was declared for an AND logic     */
+                      /*************************************/
+
+                       if (data[1] == APCI1500_AND) {
+                               for (i_Count = 0; i_Count < 8; i_Count++) {
+                                       i_PatternTransitionCount =
+                                               i_PatternTransitionCount +
+                                               ((i_PatternTransition >>
+                                                       i_Count) & 0x1);
+
+                               }       //for (i_Count = 0; i_Count < 8; i_Count++)
+
+                               if (i_PatternTransitionCount > 1) {
+                                 /****************************************/
+                                       /* Transition error on an AND logic     */
+                                 /****************************************/
+                                       printk("\n Transition error on an AND logic\n");
+                                       return -EINVAL;
+                               }       // if (i_PatternTransitionCount > 1)
+                       }       // if (data[1]== APCI1500_AND)
+
+                           /*****************************************************************/
+                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                           /*****************************************************************/
+                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       /******************/
+                       /* Disable Port A */
+                           /******************/
+                       outb(0xF0,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       /**********************************************/
+                       /* Selects the polarity register of port 1    */
+                           /**********************************************/
+                       outb(APCI1500_RW_PORT_A_PATTERN_POLARITY,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_PatternPolarity,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                       /*********************************************/
+                       /* Selects the pattern mask register of      */
+                       /* port 1                                    */
+                           /*********************************************/
+                       outb(APCI1500_RW_PORT_A_PATTERN_MASK,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_PatternMask,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       /********************************************/
+                       /* Selects the pattern transition register  */
+                       /* of port 1                                */
+                           /********************************************/
+                       outb(APCI1500_RW_PORT_A_PATTERN_TRANSITION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_PatternTransition,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                     /******************************************/
+                       /* Selects the mode specification mask    */
+                       /* register of port 1                     */
+                         /******************************************/
+                       outb(APCI1500_RW_PORT_A_SPECIFICATION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_RegValue =
+                               inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                     /******************************************/
+                       /* Selects the mode specification mask    */
+                       /* register of port 1                     */
+                         /******************************************/
+                       outb(APCI1500_RW_PORT_A_SPECIFICATION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                     /**********************/
+                       /* Port A new mode    */
+                         /**********************/
+
+                       i_RegValue = (i_RegValue & 0xF9) | data[1] | 0x9;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                       i_Event1Status = 1;
+
+                     /*****************************************************************/
+                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                         /*****************************************************************/
+
+                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                     /*****************/
+                       /* Enable Port A */
+                         /*****************/
+                       outb(0xF4,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+               }               // if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY)
+               else {
+                       printk("\nThe choice for interrupt logic does not exist\n");
+                       return -EINVAL;
+               }               // else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY)
+       }                       //   if (data[0]== 1)
+
+                /************************************/
+       /* Test if event setting for port 2 */
+                /************************************/
+
+       if (data[0] == 2) {
+                   /************************/
+               /* Test the event logic */
+                   /************************/
+
+               if (data[1] == APCI1500_OR) {
+                      /*****************************************************************/
+                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /******************/
+                       /* Disable Port B */
+                      /******************/
+                       outb(0x74,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /****************************************/
+                       /* Selects the mode specification mask  */
+                       /* register of port B                   */
+                      /****************************************/
+                       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_RegValue =
+                               inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                      /******************************************/
+                       /* Selects the mode specification mask    */
+                       /* register of port B                     */
+                      /******************************************/
+                       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_RegValue = i_RegValue & 0xF9;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                      /**********************************/
+                       /* Selects error channels 1 and 2 */
+                      /**********************************/
+
+                       i_PatternMask = (i_PatternMask | 0xC0);
+                       i_PatternPolarity = (i_PatternPolarity | 0xC0);
+                       i_PatternTransition = (i_PatternTransition | 0xC0);
+
+                      /**********************************************/
+                       /* Selects the polarity register of port 2    */
+                      /**********************************************/
+                       outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_PatternPolarity,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /**********************************************/
+                       /* Selects the pattern transition register    */
+                       /* of port 2                                  */
+                      /**********************************************/
+                       outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_PatternTransition,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /**********************************************/
+                       /* Selects the pattern Mask register    */
+                       /* of port 2                                  */
+                      /**********************************************/
+
+                       outb(APCI1500_RW_PORT_B_PATTERN_MASK,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_PatternMask,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                      /******************************************/
+                       /* Selects the mode specification mask    */
+                       /* register of port 2                     */
+                      /******************************************/
+                       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_RegValue =
+                               inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /******************************************/
+                       /* Selects the mode specification mask    */
+                       /* register of port 2                     */
+                      /******************************************/
+                       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_RegValue = (i_RegValue & 0xF9) | 4;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                       i_Event2Status = 1;
+                      /*****************************************************************/
+                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+
+                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************/
+                       /* Enable Port B */
+                      /*****************/
+
+                       outb(0xF4,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+               }               //  if (data[1] == APCI1500_OR)
+               else {
+                       printk("\nThe choice for interrupt logic does not exist\n");
+                       return -EINVAL;
+               }               //elseif (data[1] == APCI1500_OR)
+       }                       //if(data[0]==2)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_StartStopInputEvent                     |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              :  Allows or disallows a port event                      |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                            UINT ui_Channel : Channel number to read       |
+|                     lsampl_t *data          : Data Pointer to read status  |
+                      data[0]                 :0 Start input event
+                                               1 Stop input event
+                      data[1]                 :No of port (1 or 2)
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_StartStopInputEvent(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
+               0, i_RegValue;
+       switch (data[0]) {
+       case START:
+             /*************************/
+               /* Tests the port number */
+             /*************************/
+
+               if (data[1] == 1 || data[1] == 2) {
+                 /***************************/
+                       /* Test if port 1 selected */
+                 /***************************/
+
+                       if (data[1] == 1) {
+                   /*****************************/
+                               /* Test if event initialised */
+                   /*****************************/
+                               if (i_Event1Status == 1) {
+                      /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /******************/
+                                       /* Disable Port A */
+                      /******************/
+                                       outb(0xF0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /***************************************************/
+                                       /* Selects the command and status register of      */
+                                       /* port 1                                          */
+                      /***************************************************/
+                                       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*************************************/
+                                       /* Allows the pattern interrupt      */
+                      /*************************************/
+                                       outb(0xC0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************/
+                                       /* Enable Port A */
+                      /*****************/
+                                       outb(0xF4,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                       i_Event1InterruptStatus = 1;
+                                       outb(APCI1500_RW_PORT_A_SPECIFICATION,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                       i_RegValue =
+                                               inb(devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                                       /* Selects the master interrupt control register */
+                      /*************************************************/
+                                       outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /**********************************************/
+                                       /* Authorizes the main interrupt on the board */
+                      /**********************************************/
+                                       outb(0xD0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                               }       // if(i_Event1Status==1)
+                               else {
+                                       printk("\nEvent 1 not initialised\n");
+                                       return -EINVAL;
+                               }       //else if(i_Event1Status==1)
+                       }       //if (data[1]==1)
+                       if (data[1] == 2) {
+
+                               if (i_Event2Status == 1) {
+                           /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                           /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /******************/
+                                       /* Disable Port B */
+                      /******************/
+                                       outb(0x74,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /***************************************************/
+                                       /* Selects the command and status register of      */
+                                       /* port 2                                          */
+                      /***************************************************/
+                                       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*************************************/
+                                       /* Allows the pattern interrupt      */
+                      /*************************************/
+                                       outb(0xC0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************/
+                                       /* Enable Port B */
+                      /*****************/
+                                       outb(0xF4,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                                       /* Selects the master interrupt control register */
+                      /*************************************************/
+                                       outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /**********************************************/
+                                       /* Authorizes the main interrupt on the board */
+                      /**********************************************/
+                                       outb(0xD0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                       i_Event2InterruptStatus = 1;
+                               }       // if(i_Event2Status==1)
+                               else {
+                                       printk("\nEvent 2 not initialised\n");
+                                       return -EINVAL;
+                               }       //else if(i_Event2Status==1)
+                       }       // if(data[1]==2)
+               }               // if (data[1] == 1 || data[0] == 2)
+               else {
+                       printk("\nThe port parameter is in error\n");
+                       return -EINVAL;
+               }               //else if (data[1] == 1 || data[0] == 2)
+
+               break;
+
+       case STOP:
+                 /*************************/
+               /* Tests the port number */
+                 /*************************/
+
+               if (data[1] == 1 || data[1] == 2) {
+                 /***************************/
+                       /* Test if port 1 selected */
+                 /***************************/
+
+                       if (data[1] == 1) {
+                   /*****************************/
+                               /* Test if event initialised */
+                   /*****************************/
+                               if (i_Event1Status == 1) {
+                      /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /******************/
+                                       /* Disable Port A */
+                      /******************/
+                                       outb(0xF0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /***************************************************/
+                                       /* Selects the command and status register of      */
+                                       /* port 1                                          */
+                      /***************************************************/
+                                       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*************************************/
+                                       /* Inhibits the pattern interrupt      */
+                      /*************************************/
+                                       outb(0xE0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************/
+                                       /* Enable Port A */
+                      /*****************/
+                                       outb(0xF4,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                       i_Event1InterruptStatus = 0;
+                               }       // if(i_Event1Status==1)
+                               else {
+                                       printk("\nEvent 1 not initialised\n");
+                                       return -EINVAL;
+                               }       //else if(i_Event1Status==1)
+                       }       //if (data[1]==1)
+                       if (data[1] == 2) {
+                        /*****************************/
+                               /* Test if event initialised */
+                        /*****************************/
+                               if (i_Event2Status == 1) {
+                         /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                         /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                         /******************/
+                                       /* Disable Port B */
+                         /******************/
+                                       outb(0x74,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                         /***************************************************/
+                                       /* Selects the command and status register of      */
+                                       /* port 2                                         */
+                         /***************************************************/
+                                       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*************************************/
+                                       /* Inhibits the pattern interrupt      */
+                      /*************************************/
+                                       outb(0xE0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************************************************************/
+                                       /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+                      /*****************************************************************/
+                                       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+                      /*****************/
+                                       /* Enable Port B */
+                      /*****************/
+                                       outb(0xF4,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                       i_Event2InterruptStatus = 0;
+                               }       // if(i_Event2Status==1)
+                               else {
+                                       printk("\nEvent 2 not initialised\n");
+                                       return -EINVAL;
+                               }       //else if(i_Event2Status==1)
+                       }       //if(data[1]==2)
+
+               }               // if (data[1] == 1 || data[1] == 2)
+               else {
+                       printk("\nThe port parameter is in error\n");
+                       return -EINVAL;
+               }               //else if (data[1] == 1 || data[1] == 2)
+               break;
+       default:
+               printk("\nThe option of START/STOP logic does not exist\n");
+               return -EINVAL;
+       }                       //switch(data[0])
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_Initialisation                          |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the digital input                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                            UINT ui_Channel : Channel number to read       |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       int i_DummyRead = 0;
+    /******************/
+       /* Software reset */
+    /******************/
+       i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+       /* Selects the master configuration control register */
+ /*****************************************************/
+       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /*****************************************************/
+       /* Selects the mode specification register of port A */
+       /*****************************************************/
+       outb(APCI1500_RW_PORT_A_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /* Selects the data path polarity register of port A */
+       outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* High level of port A means 1 */
+       outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /* Selects the data direction register of port A */
+       outb(APCI1500_RW_PORT_A_DATA_DIRECTION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* All bits used as inputs */
+       outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of port A */
+       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /*  Selects the command and status register of port A */
+       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates the interrupt management of port A:  */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the handshake specification register of port A */
+       outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes the register */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+        /*****************************************************/
+       /* Selects the mode specification register of port B */
+        /*****************************************************/
+       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the data path polarity register of port B */
+       outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* A high level of port B means 1 */
+       outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the data direction register of port B */
+       outb(APCI1500_RW_PORT_B_DATA_DIRECTION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* All bits used as inputs */
+       outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of port B */
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of port B */
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates the interrupt management of port B:         */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the handshake specification register of port B */
+       outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes the register */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+          /*****************************************************/
+       /* Selects the data path polarity register of port C */
+          /*****************************************************/
+       outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* High level of port C means 1 */
+       outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the data direction register of port C */
+       outb(APCI1500_RW_PORT_C_DATA_DIRECTION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* All bits used as inputs except channel 1 */
+       outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the special IO register of port C */
+       outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes it */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+          /******************************************************/
+       /* Selects the command and status register of timer 1 */
+          /******************************************************/
+       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of timer 1 */
+       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates the interrupt management of timer 1         */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+          /******************************************************/
+       /* Selects the command and status register of timer 2 */
+          /******************************************************/
+       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of timer 2 */
+       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates Timer 2 interrupt management:               */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+         /******************************************************/
+       /* Selects the command and status register of timer 3 */
+         /******************************************************/
+       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of Timer 3 */
+       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates interrupt management of timer 3:            */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+        /*************************************************/
+       /* Selects the master interrupt control register */
+        /*************************************************/
+       outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes all interrupts */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_ReadMoreDigitalInput                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                     comedi_insn *insn,lsampl_t *data)                      |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the Requested digital inputs      |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+|                      UINT *data             : Data Pointer
+                      data[0]                 : 0 Read a single channel
+                                                1 read a port value
+                      data[1]                 : port value
++----------------------------------------------------------------------------+
+| Output Parameters :  --      data[0]    :The read status value
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_PortValue = data[1];
+       UINT ui_Mask = 0;
+       UINT ui_Channel;
+       UINT ui_TmpValue = 0;
+       ui_Channel = CR_CHAN(insn->chanspec);
+
+       switch (data[0]) {
+       case 0:
+               if (ui_Channel >= 0 && ui_Channel <= 15) {
+                       ui_TmpValue =
+                               (UINT) inw(devpriv->i_IobaseAddon +
+                               APCI1500_DIGITAL_IP);
+                       *data = (ui_TmpValue >> ui_Channel) & 0x1;
+               }               //if(ui_Channel >= 0 && ui_Channel <=15)
+               else {
+                       printk("\nThe channel specification are in error\n");
+                       return -EINVAL; // "sorry channel spec wrong "
+               }               //else if(ui_Channel >= 0 && ui_Channel <=15)
+               break;
+       case 1:
+
+               *data = (UINT) inw(devpriv->i_IobaseAddon +
+                       APCI1500_DIGITAL_IP);
+               switch (ui_Channel) {
+               case 2:
+                       ui_Mask = 3;
+                       *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 4:
+                       ui_Mask = 15;
+                       *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 8:
+                       ui_Mask = 255;
+                       *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 15:
+                       break;
+
+               default:
+                       printk("\nSpecified channel cannot be read \n");
+                       return -EINVAL; // "sorry channel spec wrong "
+                       break;
+               }               //switch(ui_Channel)
+               break;
+       default:
+               printk("\nThe specified functionality does not exist\n");
+               return -EINVAL;
+       }                       //switch(data[0])
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
+                      (comedi_device *dev,comedi_subdevice *s comedi_insn
+                      *insn,lsampl_t *data)                                  |
+|                                                                                   |
++----------------------------------------------------------------------------+
+| Task              : Configures the digital output memory and the digital
+                      output error interrupt                                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     lsampl_t *data         : Data Pointer contains         |
+|                                          configuration parameters as below |
+|                      comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure                                                                                                                |
+|                                        data[0]  :1:Memory on                          |
+|                                                  0:Memory off                         |
+                              data[1]  :1 Enable the voltage error interrupt
+|                                                         :0 Disable the voltage error interrupt                                                                                                                   |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       devpriv->b_OutputMemoryStatus = data[0];
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_WriteDigitalOutput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       static UINT ui_Temp = 0;
+       UINT ui_Temp1;
+
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+
+       if (!devpriv->b_OutputMemoryStatus) {
+               ui_Temp = 0;
+
+       }                       //if(!devpriv->b_OutputMemoryStatus )
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outw(data[0],
+                               devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP);
+               }               //if(data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               switch (ui_NoOfChannel) {
+
+                               case 2:
+                                       data[0] =
+                                               (data[0] << (2 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 4:
+                                       data[0] =
+                                               (data[0] << (4 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 8:
+                                       data[0] =
+                                               (data[0] << (8 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 15:
+                                       data[0] = data[0] | ui_Temp;
+                                       break;
+
+                               default:
+                                       comedi_error(dev, " chan spec wrong");
+                                       return -EINVAL; // "sorry channel spec wrong "
+
+                               }       //switch(ui_NoOfChannels)
+
+                               outw(data[0],
+                                       devpriv->i_IobaseAddon +
+                                       APCI1500_DIGITAL_OP);
+                       }       // if(data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       //else if(data[1]==1)
+               }               //elseif(data[1]==0)
+       }                       //if(data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] =
+                                       (data[0] << ui_NoOfChannel) ^
+                                       0xffffffff;
+                               data[0] = data[0] & ui_Temp;
+                               outw(data[0],
+                                       devpriv->i_IobaseAddon +
+                                       APCI1500_DIGITAL_OP);
+                       }       //if(data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       switch (ui_NoOfChannel) {
+
+                                       case 2:
+                                               data[0] = ~data[0] & 0x3;
+                                               ui_Temp1 = 3;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 2 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (2 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+
+                                       case 4:
+                                               data[0] = ~data[0] & 0xf;
+                                               ui_Temp1 = 15;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 4 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (4 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+
+                                       case 8:
+                                               data[0] = ~data[0] & 0xff;
+                                               ui_Temp1 = 255;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 8 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (8 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+
+                                       case 15:
+                                               break;
+
+                                       default:
+                                               comedi_error(dev,
+                                                       " chan spec wrong");
+                                               return -EINVAL; // "sorry channel spec wrong "
+
+                                       }       //switch(ui_NoOfChannels)
+
+                                       outw(data[0],
+                                               devpriv->i_IobaseAddon +
+                                               APCI1500_DIGITAL_OP);
+                               }       // if(data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       //else if(data[1]==1)
+                       }       //elseif(data[1]==0)
+               }               //if(data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               //if else data[3]==1)
+       }                       //if else data[3]==0)
+       ui_Temp = data[0];
+       return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device
+                   *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)|
+|                                                                                   |
++----------------------------------------------------------------------------+
+| Task              : Configures The Watchdog                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data         : Data Pointer to read status                                                       data[0]                : 2     APCI1500_1_8_KHZ
+|                                              1     APCI1500_3_6_KHZ        |
+|                                              0     APCI1500_115_KHZ
+                      data[1]                : 0     Counter1/Timer1
+                                               1     Counter2/Timer2
+                                               2     Counter3/Watchdog
+                      data[2]                : 0     Counter
+                                               1     Timer/Watchdog
+                      data[3]                :         This parameter has    |
+|                                                      two meanings.         |
+|                                                    - If the counter/timer  |
+|                                                      is used as a counter  |
+|                                                      the limit value of    |
+|                                                      the counter is given  |
+|                                                                            |
+|                                                    - If the counter/timer  |
+|                                                      is used as a timer,   |
+|                                                      the divider factor    |
+|                                                      for the output is     |
+|                                                      given.
+                       data[4]                 : 0    APCI1500_CONTINUOUS
+                                                 1    APCI1500_SINGLE
+                       data[5]                 : 0    Software Trigger
+                                                 1    Hardware Trigger
+
+                       data[6]                  :0    Software gate
+                                                 1    Hardware gate
+                       data[7]                  :0    Interrupt Disable
+                                                 1    Interrupt Enable
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       int i_TimerCounterMode, i_MasterConfiguration;
+
+       devpriv->tsk_Current = current;
+
+//Selection of the input clock
+       if (data[0] == 0 || data[0] == 1 || data[0] == 2) {
+               outw(data[0], devpriv->i_IobaseAddon + APCI1500_CLK_SELECT);
+       }                       // if(data[0]==0||data[0]==1||data[0]==2)
+       else {
+               if (data[0] != 3) {
+                       printk("\nThe option for input clock selection does not exist\n");
+                       return -EINVAL;
+               }               // if(data[0]!=3)
+       }                       //elseif(data[0]==0||data[0]==1||data[0]==2)
+       //Select the counter/timer
+       switch (data[1]) {
+       case COUNTER1:
+               //selecting counter or timer
+               switch (data[2]) {
+               case 0:
+                       data[2] = APCI1500_COUNTER;
+                       break;
+               case 1:
+                       data[2] = APCI1500_TIMER;
+                       break;
+               default:
+                       printk("\nThis choice is not a timer nor a counter\n");
+                       return -EINVAL;
+               }               // switch(data[2])
+
+               //Selecting  single or continuous mode
+               switch (data[4]) {
+               case 0:
+                       data[4] = APCI1500_CONTINUOUS;
+                       break;
+               case 1:
+                       data[4] = APCI1500_SINGLE;
+                       break;
+               default:
+                       printk("\nThis option for single/continuous mode does not exist\n");
+                       return -EINVAL;
+               }               // switch(data[4])
+
+               i_TimerCounterMode = data[2] | data[4] | 7;
+                        /*************************/
+               /* Test the reload value */
+                        /*************************/
+
+               if ((data[3] >= 0) && (data[3] <= 65535)) {
+                       if (data[7] == APCI1500_ENABLE
+                               || data[7] == APCI1500_DISABLE) {
+
+                               /************************************************/
+                               /* Selects the mode register of timer/counter 1 */
+                               /************************************************/
+                               outb(APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               /***********************/
+                               /* Writes the new mode */
+                               /***********************/
+                               outb(i_TimerCounterMode,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                               /****************************************************/
+                               /* Selects the constant register of timer/counter 1 */
+                               /****************************************************/
+
+                               outb(APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                 /*************************/
+                               /* Writes the low value  */
+                                 /*************************/
+
+                               outb(data[3],
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                  /****************************************************/
+                               /* Selects the constant register of timer/counter 1 */
+                                  /****************************************************/
+
+                               outb(APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                 /**************************/
+                               /* Writes the high value  */
+                                 /**************************/
+
+                               data[3] = data[3] >> 8;
+                               outb(data[3],
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                    /*********************************************/
+                               /* Selects the master configuration register */
+                                    /*********************************************/
+
+                               outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                    /**********************/
+                               /* Reads the register */
+                                    /**********************/
+
+                               i_MasterConfiguration =
+                                       inb(devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                      /********************************************************/
+                               /* Enables timer/counter 1 and triggers timer/counter 1 */
+                                      /********************************************************/
+
+                               i_MasterConfiguration =
+                                       i_MasterConfiguration | 0x40;
+
+                                   /*********************************************/
+                               /* Selects the master configuration register */
+                                   /*********************************************/
+                               outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                     /********************************/
+                               /* Writes the new configuration */
+                                     /********************************/
+                               outb(i_MasterConfiguration,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                                        /****************************************/
+                               /* Selects the commands register of     */
+                               /* timer/counter 1                      */
+                                        /****************************************/
+
+                               outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                      /***************************/
+                               /* Disable timer/counter 1 */
+                                      /***************************/
+
+                               outb(0x0,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                                         /****************************************/
+                               /* Selects the commands register of     */
+                               /* timer/counter 1                      */
+                                         /****************************************/
+                               outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                     /***************************/
+                               /* Trigger timer/counter 1 */
+                                     /***************************/
+                               outb(0x2,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                       }       //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+                       else {
+                               printk("\nError in selection of interrupt enable or disable\n");
+                               return -EINVAL;
+                       }       //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+               }               // if ((data[3]>= 0) && (data[3] <= 65535))
+               else {
+                       printk("\nError in selection of reload value\n");
+                       return -EINVAL;
+               }               //else if ((data[3]>= 0) && (data[3] <= 65535))
+               i_TimerCounterWatchdogInterrupt = data[7];
+               i_TimerCounter1Init = 1;
+               break;
+
+       case COUNTER2:          //selecting counter or timer
+               switch (data[2]) {
+               case 0:
+                       data[2] = APCI1500_COUNTER;
+                       break;
+               case 1:
+                       data[2] = APCI1500_TIMER;
+                       break;
+               default:
+                       printk("\nThis choice is not a timer nor a counter\n");
+                       return -EINVAL;
+               }               // switch(data[2])
+
+               //Selecting  single or continuous mode
+               switch (data[4]) {
+               case 0:
+                       data[4] = APCI1500_CONTINUOUS;
+                       break;
+               case 1:
+                       data[4] = APCI1500_SINGLE;
+                       break;
+               default:
+                       printk("\nThis option for single/continuous mode does not exist\n");
+                       return -EINVAL;
+               }               // switch(data[4])
+
+               //Selecting  software or hardware trigger
+               switch (data[5]) {
+               case 0:
+                       data[5] = APCI1500_SOFTWARE_TRIGGER;
+                       break;
+               case 1:
+                       data[5] = APCI1500_HARDWARE_TRIGGER;
+                       break;
+               default:
+                       printk("\nThis choice for software or hardware trigger does not exist\n");
+                       return -EINVAL;
+               }               // switch(data[5])
+
+               //Selecting  software or hardware gate
+               switch (data[6]) {
+               case 0:
+                       data[6] = APCI1500_SOFTWARE_GATE;
+                       break;
+               case 1:
+                       data[6] = APCI1500_HARDWARE_GATE;
+                       break;
+               default:
+                       printk("\nThis choice for software or hardware gate does not exist\n");
+                       return -EINVAL;
+               }               // switch(data[6])
+
+               i_TimerCounterMode = data[2] | data[4] | data[5] | data[6] | 7;
+
+                            /*************************/
+               /* Test the reload value */
+                            /*************************/
+
+               if ((data[3] >= 0) && (data[3] <= 65535)) {
+                       if (data[7] == APCI1500_ENABLE
+                               || data[7] == APCI1500_DISABLE) {
+
+                               /************************************************/
+                               /* Selects the mode register of timer/counter 2 */
+                               /************************************************/
+                               outb(APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               /***********************/
+                               /* Writes the new mode */
+                               /***********************/
+                               outb(i_TimerCounterMode,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                               /****************************************************/
+                               /* Selects the constant register of timer/counter 2 */
+                               /****************************************************/
+
+                               outb(APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                 /*************************/
+                               /* Writes the low value  */
+                                 /*************************/
+
+                               outb(data[3],
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                  /****************************************************/
+                               /* Selects the constant register of timer/counter 2 */
+                                  /****************************************************/
+
+                               outb(APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                 /**************************/
+                               /* Writes the high value  */
+                                 /**************************/
+
+                               data[3] = data[3] >> 8;
+                               outb(data[3],
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                    /*********************************************/
+                               /* Selects the master configuration register */
+                                    /*********************************************/
+
+                               outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                    /**********************/
+                               /* Reads the register */
+                                    /**********************/
+
+                               i_MasterConfiguration =
+                                       inb(devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                      /********************************************************/
+                               /* Enables timer/counter 2 and triggers timer/counter 2 */
+                                      /********************************************************/
+
+                               i_MasterConfiguration =
+                                       i_MasterConfiguration | 0x20;
+
+                                   /*********************************************/
+                               /* Selects the master configuration register */
+                                   /*********************************************/
+                               outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                     /********************************/
+                               /* Writes the new configuration */
+                                     /********************************/
+                               outb(i_MasterConfiguration,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                                        /****************************************/
+                               /* Selects the commands register of     */
+                               /* timer/counter 2                      */
+                                        /****************************************/
+
+                               outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                      /***************************/
+                               /* Disable timer/counter 2 */
+                                      /***************************/
+
+                               outb(0x0,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                                         /****************************************/
+                               /* Selects the commands register of     */
+                               /* timer/counter 2                      */
+                                         /****************************************/
+                               outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                     /***************************/
+                               /* Trigger timer/counter 1 */
+                                     /***************************/
+                               outb(0x2,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                       }       //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+                       else {
+                               printk("\nError in selection of interrupt enable or disable\n");
+                               return -EINVAL;
+                       }       //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+               }               // if ((data[3]>= 0) && (data[3] <= 65535))
+               else {
+                       printk("\nError in selection of reload value\n");
+                       return -EINVAL;
+               }               //else if ((data[3]>= 0) && (data[3] <= 65535))
+               i_TimerCounterWatchdogInterrupt = data[7];
+               i_TimerCounter2Init = 1;
+               break;
+
+       case COUNTER3:          //selecting counter or watchdog
+               switch (data[2]) {
+               case 0:
+                       data[2] = APCI1500_COUNTER;
+                       break;
+               case 1:
+                       data[2] = APCI1500_WATCHDOG;
+                       break;
+               default:
+                       printk("\nThis choice is not a watchdog nor a counter\n");
+                       return -EINVAL;
+               }               // switch(data[2])
+
+               //Selecting  single or continuous mode
+               switch (data[4]) {
+               case 0:
+                       data[4] = APCI1500_CONTINUOUS;
+                       break;
+               case 1:
+                       data[4] = APCI1500_SINGLE;
+                       break;
+               default:
+                       printk("\nThis option for single/continuous mode does not exist\n");
+                       return -EINVAL;
+               }               // switch(data[4])
+
+               //Selecting  software or hardware gate
+               switch (data[6]) {
+               case 0:
+                       data[6] = APCI1500_SOFTWARE_GATE;
+                       break;
+               case 1:
+                       data[6] = APCI1500_HARDWARE_GATE;
+                       break;
+               default:
+                       printk("\nThis choice for software or hardware gate does not exist\n");
+                       return -EINVAL;
+               }               // switch(data[6])
+
+                     /*****************************/
+               /* Test if used for watchdog */
+                         /*****************************/
+
+               if (data[2] == APCI1500_WATCHDOG) {
+                            /*****************************/
+                       /* - Enables the output line */
+                       /* - Enables retrigger       */
+                       /* - Pulses output           */
+                            /*****************************/
+                       i_TimerCounterMode = data[2] | data[4] | 0x54;
+               }               //if (data[2] == APCI1500_WATCHDOG)
+               else {
+                       i_TimerCounterMode = data[2] | data[4] | data[6] | 7;
+               }               //elseif (data[2] == APCI1500_WATCHDOG)
+                                /*************************/
+               /* Test the reload value */
+                            /*************************/
+
+               if ((data[3] >= 0) && (data[3] <= 65535)) {
+                       if (data[7] == APCI1500_ENABLE
+                               || data[7] == APCI1500_DISABLE) {
+
+                               /************************************************/
+                               /* Selects the mode register of watchdog/counter 3 */
+                               /************************************************/
+                               outb(APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               /***********************/
+                               /* Writes the new mode */
+                               /***********************/
+                               outb(i_TimerCounterMode,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                               /****************************************************/
+                               /* Selects the constant register of watchdog/counter 3 */
+                               /****************************************************/
+
+                               outb(APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                 /*************************/
+                               /* Writes the low value  */
+                                 /*************************/
+
+                               outb(data[3],
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                  /****************************************************/
+                               /* Selects the constant register of watchdog/counter 3 */
+                                  /****************************************************/
+
+                               outb(APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                 /**************************/
+                               /* Writes the high value  */
+                                 /**************************/
+
+                               data[3] = data[3] >> 8;
+                               outb(data[3],
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                    /*********************************************/
+                               /* Selects the master configuration register */
+                                    /*********************************************/
+
+                               outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                    /**********************/
+                               /* Reads the register */
+                                    /**********************/
+
+                               i_MasterConfiguration =
+                                       inb(devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                      /********************************************************/
+                               /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */
+                                      /********************************************************/
+
+                               i_MasterConfiguration =
+                                       i_MasterConfiguration | 0x10;
+
+                                   /*********************************************/
+                               /* Selects the master configuration register */
+                                   /*********************************************/
+                               outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                     /********************************/
+                               /* Writes the new configuration */
+                                     /********************************/
+                               outb(i_MasterConfiguration,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                                     /********************/
+                               /* Test if COUNTER */
+                                         /********************/
+                               if (data[2] == APCI1500_COUNTER) {
+
+                                           /*************************************/
+                                       /* Selects the command register of   */
+                                       /* watchdog/counter 3                */
+                                                /*************************************/
+                                       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                             /*************************************************/
+                                       /* Disable the  watchdog/counter 3 and starts it */
+                                                 /*************************************************/
+                                       outb(0x0,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                                             /*************************************/
+                                       /* Selects the command register of   */
+                                       /* watchdog/counter 3                */
+                                                 /*************************************/
+
+                                       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                            /*************************************************/
+                                       /* Trigger the  watchdog/counter 3 and starts it */
+                                                /*************************************************/
+                                       outb(0x2,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                               }       //elseif(data[2]==APCI1500_COUNTER)
+
+                       }       //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+                       else {
+                               printk("\nError in selection of interrupt enable or disable\n");
+                               return -EINVAL;
+                       }       //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+               }               // if ((data[3]>= 0) && (data[3] <= 65535))
+               else {
+                       printk("\nError in selection of reload value\n");
+                       return -EINVAL;
+               }               //else if ((data[3]>= 0) && (data[3] <= 65535))
+               i_TimerCounterWatchdogInterrupt = data[7];
+               i_WatchdogCounter3Init = 1;
+               break;
+
+       default:
+               printk("\nThe specified counter\timer option does not exist\n");
+       }                       //switch(data[1])
+       i_CounterLogic = data[2];
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_StartStopTriggerTimerCounterWatchdog      |
+|                              (comedi_device *dev,comedi_subdevice *s,
+                         comedi_insn *insn,lsampl_t *data);                  |
++----------------------------------------------------------------------------+
+| Task              : Start / Stop or trigger the timer counter or Watchdog  |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev     : Driver handle                 |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data         : Data Pointer to read status   |
+                      data[0]                : 0     Counter1/Timer1
+                                               1     Counter2/Timer2
+                                               2     Counter3/Watchdog
+                      data[1]                : 0     start
+                                               1     stop
+                                               2     Trigger
+                      data[2]                : 0     Counter
+                                               1     Timer/Watchdog
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       int i_CommandAndStatusValue;
+
+       switch (data[0]) {
+       case COUNTER1:
+               switch (data[1]) {
+               case START:
+                       if (i_TimerCounter1Init == 1) {
+                               if (i_TimerCounterWatchdogInterrupt == 1) {
+                                       i_CommandAndStatusValue = 0xC4; //Enable the interrupt
+                               }       // if(i_TimerCounterWatchdogInterrupt==1)
+                               else {
+                                       i_CommandAndStatusValue = 0xE4; //disable the interrupt
+                               }       //elseif(i_TimerCounterWatchdogInterrupt==1)
+                                             /**************************/
+                               /* Starts timer/counter 1 */
+                                             /**************************/
+                               i_TimerCounter1Enabled = 1;
+                                               /********************************************/
+                               /* Selects the commands and status register */
+                                               /********************************************/
+                               outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               outb(i_CommandAndStatusValue,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                       }       //if( i_TimerCounter1Init==1)
+                       else {
+                               printk("\nCounter/Timer1 not configured\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               case STOP:
+
+                                             /**************************/
+                       /* Stop timer/counter 1 */
+                                             /**************************/
+
+                                               /********************************************/
+                       /* Selects the commands and status register */
+                                               /********************************************/
+                       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(0x00,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_TimerCounter1Enabled = 0;
+                       break;
+
+               case TRIGGER:
+                       if (i_TimerCounter1Init == 1) {
+                               if (i_TimerCounter1Enabled == 1) {
+                                                /************************/
+                                       /* Set Trigger and gate */
+                                                /************************/
+
+                                       i_CommandAndStatusValue = 0x6;
+                               }       //if( i_TimerCounter1Enabled==1)
+                               else {
+                                                  /***************/
+                                       /* Set Trigger */
+                                                  /***************/
+
+                                       i_CommandAndStatusValue = 0x2;
+                               }       //elseif(i_TimerCounter1Enabled==1)
+
+                                               /********************************************/
+                               /* Selects the commands and status register */
+                                               /********************************************/
+                               outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               outb(i_CommandAndStatusValue,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                       }       //if( i_TimerCounter1Init==1)
+                       else {
+                               printk("\nCounter/Timer1 not configured\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               default:
+                       printk("\nThe specified option for start/stop/trigger does not exist\n");
+                       return -EINVAL;
+               }               //switch(data[1])
+               break;
+
+       case COUNTER2:
+               switch (data[1]) {
+               case START:
+                       if (i_TimerCounter2Init == 1) {
+                               if (i_TimerCounterWatchdogInterrupt == 1) {
+                                       i_CommandAndStatusValue = 0xC4; //Enable the interrupt
+                               }       // if(i_TimerCounterWatchdogInterrupt==1)
+                               else {
+                                       i_CommandAndStatusValue = 0xE4; //disable the interrupt
+                               }       //elseif(i_TimerCounterWatchdogInterrupt==1)
+                                             /**************************/
+                               /* Starts timer/counter 2 */
+                                             /**************************/
+                               i_TimerCounter2Enabled = 1;
+                                               /********************************************/
+                               /* Selects the commands and status register */
+                                               /********************************************/
+                               outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               outb(i_CommandAndStatusValue,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                       }       //if( i_TimerCounter2Init==1)
+                       else {
+                               printk("\nCounter/Timer2 not configured\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               case STOP:
+
+                                             /**************************/
+                       /* Stop timer/counter 2 */
+                                             /**************************/
+
+                                               /********************************************/
+                       /* Selects the commands and status register */
+                                               /********************************************/
+                       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(0x00,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_TimerCounter2Enabled = 0;
+                       break;
+               case TRIGGER:
+                       if (i_TimerCounter2Init == 1) {
+                               if (i_TimerCounter2Enabled == 1) {
+                                                /************************/
+                                       /* Set Trigger and gate */
+                                                /************************/
+
+                                       i_CommandAndStatusValue = 0x6;
+                               }       //if( i_TimerCounter2Enabled==1)
+                               else {
+                                                  /***************/
+                                       /* Set Trigger */
+                                                  /***************/
+
+                                       i_CommandAndStatusValue = 0x2;
+                               }       //elseif(i_TimerCounter2Enabled==1)
+
+                                               /********************************************/
+                               /* Selects the commands and status register */
+                                               /********************************************/
+                               outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               outb(i_CommandAndStatusValue,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                       }       //if( i_TimerCounter2Init==1)
+                       else {
+                               printk("\nCounter/Timer2 not configured\n");
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       printk("\nThe specified option for start/stop/trigger does not exist\n");
+                       return -EINVAL;
+               }               //switch(data[1])
+               break;
+       case COUNTER3:
+               switch (data[1]) {
+               case START:
+                       if (i_WatchdogCounter3Init == 1) {
+
+                               if (i_TimerCounterWatchdogInterrupt == 1) {
+                                       i_CommandAndStatusValue = 0xC4; //Enable the interrupt
+                               }       // if(i_TimerCounterWatchdogInterrupt==1)
+                               else {
+                                       i_CommandAndStatusValue = 0xE4; //disable the interrupt
+                               }       //elseif(i_TimerCounterWatchdogInterrupt==1)
+                                             /**************************/
+                               /* Starts Watchdog/counter 3 */
+                                             /**************************/
+                               i_WatchdogCounter3Enabled = 1;
+                                               /********************************************/
+                               /* Selects the commands and status register */
+                                               /********************************************/
+                               outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               outb(i_CommandAndStatusValue,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                       }       // if( i_WatchdogCounter3init==1)
+                       else {
+                               printk("\nWatchdog/Counter3 not configured\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               case STOP:
+
+                                             /**************************/
+                       /* Stop Watchdog/counter 3 */
+                                             /**************************/
+
+                                               /********************************************/
+                       /* Selects the commands and status register */
+                                               /********************************************/
+                       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(0x00,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_WatchdogCounter3Enabled = 0;
+                       break;
+
+               case TRIGGER:
+                       switch (data[2]) {
+                       case 0: //triggering counter 3
+                               if (i_WatchdogCounter3Init == 1) {
+                                       if (i_WatchdogCounter3Enabled == 1) {
+                                                              /************************/
+                                               /* Set Trigger and gate */
+                                                              /************************/
+
+                                               i_CommandAndStatusValue = 0x6;
+                                       }       //if( i_WatchdogCounter3Enabled==1)
+                                       else {
+                                                          /***************/
+                                               /* Set Trigger */
+                                                          /***************/
+
+                                               i_CommandAndStatusValue = 0x2;
+                                       }       //elseif(i_WatchdogCounter3Enabled==1)
+
+                                               /********************************************/
+                                       /* Selects the commands and status register */
+                                               /********************************************/
+                                       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                       outb(i_CommandAndStatusValue,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                               }       //if( i_WatchdogCounter3Init==1)
+                               else {
+                                       printk("\nCounter3 not configured\n");
+                                       return -EINVAL;
+                               }
+                               break;
+                       case 1:
+                               //triggering Watchdog 3
+                               if (i_WatchdogCounter3Init == 1) {
+
+                                               /********************************************/
+                                       /* Selects the commands and status register */
+                                               /********************************************/
+                                       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                                       outb(0x6,
+                                               devpriv->iobase +
+                                               APCI1500_Z8536_CONTROL_REGISTER);
+                               }       //if( i_WatchdogCounter3Init==1)
+                               else {
+                                       printk("\nWatchdog 3 not configured\n");
+                                       return -EINVAL;
+                               }
+                               break;
+                       default:
+                               printk("\nWrong choice of watchdog/counter3\n");
+                               return -EINVAL;
+                       }       //switch(data[2])
+                       break;
+               default:
+                       printk("\nThe specified option for start/stop/trigger does not exist\n");
+                       return -EINVAL;
+               }               //switch(data[1])
+               break;
+       default:
+               printk("\nThe specified choice for counter/watchdog/timer does not exist\n");
+               return -EINVAL;
+       }                       //switch(data[0])
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_ReadCounterTimerWatchdog                |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data);                                        |
++----------------------------------------------------------------------------+
+| Task              : Read The Watchdog                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
+                      data[0]                : 0     Counter1/Timer1
+                                               1     Counter2/Timer2
+                                               2     Counter3/Watchdog
+
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       int i_CommandAndStatusValue;
+       switch (data[0]) {
+       case COUNTER1:
+               //Read counter/timer1
+               if (i_TimerCounter1Init == 1) {
+                       if (i_TimerCounter1Enabled == 1) {
+                 /************************/
+                               /* Set RCC and gate */
+                 /************************/
+
+                               i_CommandAndStatusValue = 0xC;
+                       }       //if( i_TimerCounter1Init==1)
+                       else {
+                   /***************/
+                               /* Set RCC */
+                   /***************/
+
+                               i_CommandAndStatusValue = 0x8;
+                       }       //elseif(i_TimerCounter1Init==1)
+
+               /********************************************/
+                       /* Selects the commands and status register */
+               /********************************************/
+                       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_CommandAndStatusValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                /***************************************/
+                       /* Selects the counter register (high) */
+                /***************************************/
+                       outb(APCI1500_R_CPT_TMR1_VALUE_HIGH,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] =
+                               inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] = data[0] << 8;
+                       data[0] = data[0] & 0xff00;
+                       outb(APCI1500_R_CPT_TMR1_VALUE_LOW,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] =
+                               data[0] | inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+               }               //if( i_TimerCounter1Init==1)
+               else {
+                       printk("\nTimer/Counter1 not configured\n");
+                       return -EINVAL;
+               }               //elseif( i_TimerCounter1Init==1)
+               break;
+       case COUNTER2:
+               //Read counter/timer2
+               if (i_TimerCounter2Init == 1) {
+                       if (i_TimerCounter2Enabled == 1) {
+                 /************************/
+                               /* Set RCC and gate */
+                 /************************/
+
+                               i_CommandAndStatusValue = 0xC;
+                       }       //if( i_TimerCounter2Init==1)
+                       else {
+                   /***************/
+                               /* Set RCC */
+                   /***************/
+
+                               i_CommandAndStatusValue = 0x8;
+                       }       //elseif(i_TimerCounter2Init==1)
+
+               /********************************************/
+                       /* Selects the commands and status register */
+               /********************************************/
+                       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_CommandAndStatusValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                /***************************************/
+                       /* Selects the counter register (high) */
+                /***************************************/
+                       outb(APCI1500_R_CPT_TMR2_VALUE_HIGH,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] =
+                               inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] = data[0] << 8;
+                       data[0] = data[0] & 0xff00;
+                       outb(APCI1500_R_CPT_TMR2_VALUE_LOW,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] =
+                               data[0] | inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+               }               //if( i_TimerCounter2Init==1)
+               else {
+                       printk("\nTimer/Counter2 not configured\n");
+                       return -EINVAL;
+               }               //elseif( i_TimerCounter2Init==1)
+               break;
+       case COUNTER3:
+               //Read counter/watchdog2
+               if (i_WatchdogCounter3Init == 1) {
+                       if (i_WatchdogCounter3Enabled == 1) {
+                 /************************/
+                               /* Set RCC and gate */
+                 /************************/
+
+                               i_CommandAndStatusValue = 0xC;
+                       }       //if( i_TimerCounter2Init==1)
+                       else {
+                   /***************/
+                               /* Set RCC */
+                   /***************/
+
+                               i_CommandAndStatusValue = 0x8;
+                       }       //elseif(i_WatchdogCounter3Init==1)
+
+               /********************************************/
+                       /* Selects the commands and status register */
+               /********************************************/
+                       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       outb(i_CommandAndStatusValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+
+                /***************************************/
+                       /* Selects the counter register (high) */
+                /***************************************/
+                       outb(APCI1500_R_CPT_TMR3_VALUE_HIGH,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] =
+                               inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] = data[0] << 8;
+                       data[0] = data[0] & 0xff00;
+                       outb(APCI1500_R_CPT_TMR3_VALUE_LOW,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       data[0] =
+                               data[0] | inb(devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+               }               //if( i_WatchdogCounter3Init==1)
+               else {
+                       printk("\nWatchdogCounter3 not configured\n");
+                       return -EINVAL;
+               }               //elseif( i_WatchdogCounter3Init==1)
+               break;
+       default:
+               printk("\nThe choice of timer/counter/watchdog does not exist\n");
+               return -EINVAL;
+       }                       //switch(data[0])
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int  i_APCI1500_ReadInterruptMask                      |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data);                                        |
++----------------------------------------------------------------------------+
+| Task              : Read the interrupt mask                                |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
+
+
++----------------------------------------------------------------------------+
+| Output Parameters :  --      data[0]:The interrupt mask value                                                                                                                           data[1]:Channel no
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_ReadInterruptMask(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       data[0] = i_InterruptMask;
+       data[1] = i_InputChannel;
+       i_InterruptMask = 0;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int  i_APCI1500_ConfigureInterrupt                     |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data);                                        |
++----------------------------------------------------------------------------+
+| Task              : Configures the interrupt registers                     |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer                 |
+
+
++----------------------------------------------------------------------------+
+| Output Parameters :  --
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_ConfigureInterrupt(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Status;
+       int i_RegValue;
+       int i_Constant;
+       devpriv->tsk_Current = current;
+       outl(0x0, devpriv->i_IobaseAmcc + 0x38);
+       if (data[0] == 1) {
+               i_Constant = 0xC0;
+       }                       //if(data[0]==1)
+       else {
+               if (data[0] == 0) {
+                       i_Constant = 0x00;
+               }               //if{data[0]==0)
+               else {
+                       printk("\nThe parameter passed to driver is in error for enabling the voltage interrupt\n");
+                       return -EINVAL;
+               }               //else if(data[0]==0)
+       }                       //elseif(data[0]==1)
+
+        /*****************************************************/
+       /* Selects the mode specification register of port B */
+        /*****************************************************/
+       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+      /*********************************************/
+       /* Writes the new configuration (APCI1500_OR) */
+      /*********************************************/
+       i_RegValue = (i_RegValue & 0xF9) | APCI1500_OR;
+
+       outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /*****************************************************/
+       /* Selects the command and status register of port B */
+       /*****************************************************/
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /*****************************************/
+       /* Authorises the interrupt on the board */
+       /*****************************************/
+       outb(0xC0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /***************************************************/
+       /* Selects the pattern polarity register of port B */
+       /***************************************************/
+       outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /*****************************************************/
+       /* Selects the pattern transition register of port B */
+       /*****************************************************/
+       outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /***********************************************/
+       /* Selects the pattern mask register of port B */
+       /***********************************************/
+       outb(APCI1500_RW_PORT_B_PATTERN_MASK,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /*****************************************************/
+       /* Selects the command and status register of port A */
+       /*****************************************************/
+       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+        /***********************************/
+       /* Deletes the interrupt of port A */
+        /***********************************/
+
+       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+       outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /*****************************************************/
+       /* Selects the command and status register of port  B */
+       /*****************************************************/
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+        /***********************************/
+       /* Deletes the interrupt of port B */
+        /***********************************/
+
+       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+       outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /*****************************************************/
+       /* Selects the command and status register of timer 1 */
+       /*****************************************************/
+       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+        /***********************************/
+       /* Deletes the interrupt of timer 1 */
+        /***********************************/
+
+       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+       outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+        /*****************************************************/
+       /* Selects the command and status register of timer 2 */
+       /*****************************************************/
+       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+        /***********************************/
+       /* Deletes the interrupt of timer 2 */
+        /***********************************/
+
+       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+       outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /*****************************************************/
+       /* Selects the command and status register of timer 3 */
+       /*****************************************************/
+       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+        /***********************************/
+       /* Deletes the interrupt of timer 3 */
+        /***********************************/
+
+       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+       outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+        /*************************************************/
+       /* Selects the master interrupt control register */
+        /*************************************************/
+       outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /**********************************************/
+       /* Authorizes the main interrupt on the board */
+       /**********************************************/
+       outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+      /***************************/
+       /* Enables the PCI interrupt */
+      /*****************************/
+       outl(0x3000, devpriv->i_IobaseAmcc + 0x38);
+       ui_Status = inl(devpriv->i_IobaseAmcc + 0x10);
+       ui_Status = inl(devpriv->i_IobaseAmcc + 0x38);
+       outl(0x23000, devpriv->i_IobaseAmcc + 0x38);
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : static void v_APCI1500_Interrupt                                      |
+|                                        (int irq , void *d)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt handler                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+static VOID v_APCI1500_Interrupt(int irq, void *d)
+{
+
+       comedi_device *dev = d;
+       UINT ui_InterruptStatus = 0;
+       int i_RegValue = 0;
+       i_InterruptMask = 0;
+
+ /***********************************/
+       /* Read the board interrupt status */
+ /***********************************/
+       ui_InterruptStatus = inl(devpriv->i_IobaseAmcc + 0x38);
+
+  /***************************************/
+       /* Test if board generated a interrupt */
+  /***************************************/
+       if ((ui_InterruptStatus & 0x800000) == 0x800000) {
+      /************************/
+               /* Disable all Interrupt */
+      /************************/
+      /*************************************************/
+               /* Selects the master interrupt control register */
+      /*************************************************/
+               //outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER);
+       /**********************************************/
+               /* Disables  the main interrupt on the board */
+       /**********************************************/
+               //outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER);
+
+   /*****************************************************/
+               /* Selects the command and status register of port A */
+   /*****************************************************/
+               outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+                       devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               i_RegValue =
+                       inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               if ((i_RegValue & 0x60) == 0x60) {
+          /*****************************************************/
+                       /* Selects the command and status register of port A */
+          /*****************************************************/
+                       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+           /***********************************/
+                       /* Deletes the interrupt of port A */
+           /***********************************/
+                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_InterruptMask = i_InterruptMask | 1;
+                       if (i_Logic == APCI1500_OR_PRIORITY) {
+                               outb(APCI1500_RW_PORT_A_SPECIFICATION,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               i_RegValue =
+                                       inb(devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+             /***************************************************/
+                               /* Selects the interrupt vector register of port A */
+             /***************************************************/
+                               outb(APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
+                                       devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+                               i_RegValue =
+                                       inb(devpriv->iobase +
+                                       APCI1500_Z8536_CONTROL_REGISTER);
+
+                               i_InputChannel = 1 + (i_RegValue >> 1);
+
+                       }       // if(i_Logic==APCI1500_OR_PRIORITY)
+                       else {
+                               i_InputChannel = 0;
+                       }       //elseif(i_Logic==APCI1500_OR_PRIORITY)
+               }               // if ((i_RegValue & 0x60) == 0x60)
+
+          /*****************************************************/
+               /* Selects the command and status register of port B */
+          /*****************************************************/
+               outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+                       devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               i_RegValue =
+                       inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               if ((i_RegValue & 0x60) == 0x60) {
+            /*****************************************************/
+                       /* Selects the command and status register of port B */
+            /*****************************************************/
+                       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+            /***********************************/
+                       /* Deletes the interrupt of port B */
+            /***********************************/
+                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       printk("\n\n\n");
+            /****************/
+                       /* Reads port B */
+            /****************/
+                       i_RegValue =
+                               inb((UINT) devpriv->iobase +
+                               APCI1500_Z8536_PORT_B);
+
+                       i_RegValue = i_RegValue & 0xC0;
+             /**************************************/
+                       /* Tests if this is an external error */
+             /**************************************/
+
+                       if (i_RegValue) {
+                               //Disable the interrupt
+                    /*****************************************************/
+                               /* Selects the command and status register of port B */
+                    /*****************************************************/
+                               outl(0x0, devpriv->i_IobaseAmcc + 0x38);
+
+                               if (i_RegValue & 0x80) {
+                                       i_InterruptMask =
+                                               i_InterruptMask | 0x40;
+                               }       //if (i_RegValue & 0x80)
+
+                               if (i_RegValue & 0x40) {
+                                       i_InterruptMask =
+                                               i_InterruptMask | 0x80;
+                               }       //if (i_RegValue & 0x40)
+                       }       // if (i_RegValue)
+                       else {
+                               i_InterruptMask = i_InterruptMask | 2;
+                       }       // if (i_RegValue)
+               }               //if ((i_RegValue & 0x60) == 0x60)
+
+               /*****************************************************/
+               /* Selects the command and status register of timer 1 */
+               /*****************************************************/
+               outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                       devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               i_RegValue =
+                       inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               if ((i_RegValue & 0x60) == 0x60) {
+                  /*****************************************************/
+                       /* Selects the command and status register of timer 1 */
+                  /*****************************************************/
+                       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                  /***********************************/
+                       /* Deletes the interrupt of timer 1 */
+                  /***********************************/
+                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_InterruptMask = i_InterruptMask | 4;
+               }               // if ((i_RegValue & 0x60) == 0x60)
+               /*****************************************************/
+               /* Selects the command and status register of timer 2 */
+               /*****************************************************/
+               outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                       devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               i_RegValue =
+                       inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               if ((i_RegValue & 0x60) == 0x60) {
+                  /*****************************************************/
+                       /* Selects the command and status register of timer 2 */
+                  /*****************************************************/
+                       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                  /***********************************/
+                       /* Deletes the interrupt of timer 2 */
+                  /***********************************/
+                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       i_InterruptMask = i_InterruptMask | 8;
+               }               // if ((i_RegValue & 0x60) == 0x60)
+
+               /*****************************************************/
+               /* Selects the command and status register of timer 3 */
+               /*****************************************************/
+               outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                       devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               i_RegValue =
+                       inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+               if ((i_RegValue & 0x60) == 0x60) {
+                  /*****************************************************/
+                       /* Selects the command and status register of timer 3 */
+                  /*****************************************************/
+                       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                  /***********************************/
+                       /* Deletes the interrupt of timer 3 */
+                  /***********************************/
+                       i_RegValue = (i_RegValue & 0x0F) | 0x20;
+                       outb(i_RegValue,
+                               devpriv->iobase +
+                               APCI1500_Z8536_CONTROL_REGISTER);
+                       if (i_CounterLogic == APCI1500_COUNTER) {
+                               i_InterruptMask = i_InterruptMask | 0x10;
+                       }       //if(i_CounterLogic==APCI1500_COUNTER)
+                       else {
+                               i_InterruptMask = i_InterruptMask | 0x20;
+                       }
+               }               // if ((i_RegValue & 0x60) == 0x60)
+
+               send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+              /***********************/
+               /* Enable all Interrupts */
+              /***********************/
+
+              /*************************************************/
+               /* Selects the master interrupt control register */
+              /*************************************************/
+               outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+                       devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+              /**********************************************/
+               /* Authorizes the main interrupt on the board */
+              /**********************************************/
+               outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       }                       //  if ((ui_InterruptStatus & 0x800000) == 0x800000)
+       else {
+               printk("\nInterrupt from unknown source\n");
+
+       }                       //else if ((ui_InterruptStatus & 0x800000) == 0x800000)
+       return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1500_Reset(comedi_device *dev)               |                                                       |
++----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_Reset(comedi_device * dev)
+{
+       int i_DummyRead = 0;
+       i_TimerCounter1Init = 0;
+       i_TimerCounter2Init = 0;
+       i_WatchdogCounter3Init = 0;
+       i_Event1Status = 0;
+       i_Event2Status = 0;
+       i_TimerCounterWatchdogInterrupt = 0;
+       i_Logic = 0;
+       i_CounterLogic = 0;
+       i_InterruptMask = 0;
+       i_InputChannel = 0;;
+       i_TimerCounter1Enabled = 0;
+       i_TimerCounter2Enabled = 0;
+       i_WatchdogCounter3Enabled = 0;
+
+    /******************/
+       /* Software reset */
+    /******************/
+       i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+       /* Selects the master configuration control register */
+ /*****************************************************/
+       outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /*****************************************************/
+       /* Selects the mode specification register of port A */
+       /*****************************************************/
+       outb(APCI1500_RW_PORT_A_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /* Selects the data path polarity register of port A */
+       outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* High level of port A means 1 */
+       outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+       /* Selects the data direction register of port A */
+       outb(APCI1500_RW_PORT_A_DATA_DIRECTION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* All bits used as inputs */
+       outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of port A */
+       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /*  Selects the command and status register of port A */
+       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates the interrupt management of port A:  */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the handshake specification register of port A */
+       outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes the register */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+        /*****************************************************/
+       /* Selects the mode specification register of port B */
+        /*****************************************************/
+       outb(APCI1500_RW_PORT_B_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the data path polarity register of port B */
+       outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* A high level of port B means 1 */
+       outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the data direction register of port B */
+       outb(APCI1500_RW_PORT_B_DATA_DIRECTION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* All bits used as inputs */
+       outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of port B */
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of port B */
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates the interrupt management of port B:         */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the handshake specification register of port B */
+       outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes the register */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+          /*****************************************************/
+       /* Selects the data path polarity register of port C */
+          /*****************************************************/
+       outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* High level of port C means 1 */
+       outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the data direction register of port C */
+       outb(APCI1500_RW_PORT_C_DATA_DIRECTION,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* All bits used as inputs except channel 1 */
+       outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the special IO register of port C */
+       outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes it */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+          /******************************************************/
+       /* Selects the command and status register of timer 1 */
+          /******************************************************/
+       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of timer 1 */
+       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates the interrupt management of timer 1         */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+          /******************************************************/
+       /* Selects the command and status register of timer 2 */
+          /******************************************************/
+       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of timer 2 */
+       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates Timer 2 interrupt management:               */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+         /******************************************************/
+       /* Selects the command and status register of timer 3 */
+         /******************************************************/
+       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes IP and IUS */
+       outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Selects the command and status register of Timer 3 */
+       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deactivates interrupt management of timer 3:            */
+       outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+        /*************************************************/
+       /* Selects the master interrupt control register */
+        /*************************************************/
+       outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       /* Deletes all interrupts */
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       //reset all the digital outputs
+       outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP);
+/*******************************/
+/* Disable the board interrupt */
+/*******************************/
+ /*************************************************/
+       /* Selects the master interrupt control register */
+ /*************************************************/
+       outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+       outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************/
+       /* Selects the command and status register of port A */
+ /*****************************************************/
+       outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+       outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+       /* Selects the command and status register of port B */
+ /*****************************************************/
+       outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+       outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+       /* Selects the command and status register of timer 1 */
+ /*****************************************************/
+       outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+       outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+       /* Selects the command and status register of timer 2 */
+ /*****************************************************/
+       outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+       outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+/* Selects the command and status register of timer 3*/
+/*****************************************************/
+       outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+               devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+       outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
new file mode 100644 (file)
index 0000000..9166294
--- /dev/null
@@ -0,0 +1,157 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+/*********      Definitions for APCI-1500 card  *****/
+
+// Card Specific information
+#define APCI1500_BOARD_VENDOR_ID           0x10e8
+#define APCI1500_ADDRESS_RANGE              4
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define  APCI1500_DIGITAL_OP                   2
+#define  APCI1500_DIGITAL_IP                    0
+#define  APCI1500_AND                              2
+#define  APCI1500_OR                               4
+#define  APCI1500_OR_PRIORITY                      6
+#define  APCI1500_CLK_SELECT                    0
+#define  COUNTER1                               0
+#define  COUNTER2                               1
+#define  COUNTER3                               2
+#define  APCI1500_COUNTER                              0x20
+#define  APCI1500_TIMER                                0
+#define  APCI1500_WATCHDOG                         0
+#define  APCI1500_SINGLE                           0
+#define  APCI1500_CONTINUOUS                       0x80
+#define  APCI1500_DISABLE                              0
+#define  APCI1500_ENABLE                               1
+#define  APCI1500_SOFTWARE_TRIGGER                 0x4
+#define  APCI1500_HARDWARE_TRIGGER                 0x10
+#define  APCI1500_SOFTWARE_GATE                    0
+#define  APCI1500_HARDWARE_GATE                    0x8
+#define  START                                     0
+#define  STOP                                      1
+#define  TRIGGER                                           2
+   /**************************/
+   /* Zillog I/O enumeration */
+   /**************************/
+enum {
+       APCI1500_Z8536_PORT_C,
+       APCI1500_Z8536_PORT_B,
+       APCI1500_Z8536_PORT_A,
+       APCI1500_Z8536_CONTROL_REGISTER
+};
+
+      /******************************/
+      /* Z8536 CIO Internal Address */
+      /******************************/
+
+enum {
+       APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+       APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+       APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
+       APCI1500_RW_PORT_B_INTERRUPT_CONTROL,
+       APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR,
+       APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+       APCI1500_RW_PORT_C_DATA_DIRECTION,
+       APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
+
+       APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+       APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+       APCI1500_RW_CPT_TMR1_CMD_STATUS,
+       APCI1500_RW_CPT_TMR2_CMD_STATUS,
+       APCI1500_RW_CPT_TMR3_CMD_STATUS,
+       APCI1500_RW_PORT_A_DATA,
+       APCI1500_RW_PORT_B_DATA,
+       APCI1500_RW_PORT_C_DATA,
+
+       APCI1500_R_CPT_TMR1_VALUE_HIGH,
+       APCI1500_R_CPT_TMR1_VALUE_LOW,
+       APCI1500_R_CPT_TMR2_VALUE_HIGH,
+       APCI1500_R_CPT_TMR2_VALUE_LOW,
+       APCI1500_R_CPT_TMR3_VALUE_HIGH,
+       APCI1500_R_CPT_TMR3_VALUE_LOW,
+       APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
+       APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
+       APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
+       APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
+       APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
+       APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
+       APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
+       APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
+       APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
+       APCI1500_R_CURRENT_VECTOR,
+
+       APCI1500_RW_PORT_A_SPECIFICATION,
+       APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
+       APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
+       APCI1500_RW_PORT_A_DATA_DIRECTION,
+       APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL,
+       APCI1500_RW_PORT_A_PATTERN_POLARITY,
+       APCI1500_RW_PORT_A_PATTERN_TRANSITION,
+       APCI1500_RW_PORT_A_PATTERN_MASK,
+
+       APCI1500_RW_PORT_B_SPECIFICATION,
+       APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
+       APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
+       APCI1500_RW_PORT_B_DATA_DIRECTION,
+       APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL,
+       APCI1500_RW_PORT_B_PATTERN_POLARITY,
+       APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+       APCI1500_RW_PORT_B_PATTERN_MASK
+};
+
+ /*----------DIGITAL INPUT----------------*/
+static int i_APCI1500_Initialisation(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+static int i_APCI1500_ConfigDigitalInputEvent(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+static int i_APCI1500_StartStopInputEvent(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+static int i_APCI1500_ReadMoreDigitalInput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*----------   DIGITAL OUTPUT------------*/
+static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+static int i_APCI1500_WriteDigitalOutput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*----------TIMER----------------*/
+static int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+static int i_APCI1500_ReadCounterTimerWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+static int i_APCI1500_ReadInterruptMask(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*----------INTERRUPT HANDLER------*/
+static void v_APCI1500_Interrupt(int irq, void *d);
+static int i_APCI1500_ConfigureInterrupt(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+/*----------RESET---------------*/
+static int i_APCI1500_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
new file mode 100644 (file)
index 0000000..57e53f4
--- /dev/null
@@ -0,0 +1,542 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-1516       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci1516.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-1516                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci1516.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_Read1DigitalInput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the digital input                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure     |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_TmpValue = 0;
+       UINT ui_Channel;
+       ui_Channel = CR_CHAN(insn->chanspec);
+       if (ui_Channel >= 0 && ui_Channel <= 7) {
+               ui_TmpValue = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+               //  since only 1 channel reqd  to bring it to last bit it is rotated
+               //  8 +(chan - 1) times then ANDed with 1 for last bit.
+               *data = (ui_TmpValue >> ui_Channel) & 0x1;
+       }                       //if(ui_Channel >= 0 && ui_Channel <=7)
+       else {
+               //comedi_error(dev," \n chan spec wrong\n");
+               return -EINVAL; // "sorry channel spec wrong "
+       }                       //else if(ui_Channel >= 0 && ui_Channel <=7)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_ReadMoreDigitalInput                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                     comedi_insn *insn,lsampl_t *data)                      |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the Requested digital inputs      |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                      comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure     |
+|                      lsampl_t *data         : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ui_PortValue = data[0];
+       UINT ui_Mask = 0;
+       UINT ui_NoOfChannels;
+
+       ui_NoOfChannels = CR_CHAN(insn->chanspec);
+
+       *data = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+       switch (ui_NoOfChannels) {
+       case 2:
+               ui_Mask = 3;
+               *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+               break;
+       case 4:
+               ui_Mask = 15;
+               *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+               break;
+       case 7:
+               break;
+
+       default:
+               printk("\nWrong parameters\n");
+               return -EINVAL; // "sorry channel spec wrong "
+               break;
+       }                       //switch(ui_NoOfChannels)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_ConfigDigitalOutput (comedi_device *dev,
+                    comedi_subdevice *s comedi_insn *insn,lsampl_t *data)    |
+|                                                                                   |
++----------------------------------------------------------------------------+
+| Task              : Configures The Digital Output Subdevice.               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     lsampl_t *data         : Data Pointer contains         |
+|                                          configuration parameters as below |
+|                      comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure                                                           |
+|                                        data[0]  :1:Memory on                          |
+|                                                  0:Memory off                         |
+|                                                                                                           |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       devpriv->b_OutputMemoryStatus = data[0];
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_WriteDigitalOutput                      |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     lsampl_t *data)                                         |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                    lsampl_t *data           : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp, ui_Temp1;
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+
+       printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP);
+
+       if (devpriv->b_OutputMemoryStatus) {
+               ui_Temp = inw(devpriv->iobase + APCI1516_DIGITAL_OP);
+
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       else {
+               ui_Temp = 0;
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outw(data[0], devpriv->iobase + APCI1516_DIGITAL_OP);
+
+                       printk("EL311003 : d=%d @=%x\n", data[0],
+                               devpriv->iobase + APCI1516_DIGITAL_OP);
+
+               }               //if(data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               switch (ui_NoOfChannel) {
+
+                               case 2:
+                                       data[0] =
+                                               (data[0] << (2 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 4:
+                                       data[0] =
+                                               (data[0] << (4 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 7:
+                                       data[0] = data[0] | ui_Temp;
+                                       break;
+
+                               default:
+                                       comedi_error(dev, " chan spec wrong");
+                                       return -EINVAL; // "sorry channel spec wrong "
+
+                               }       //switch(ui_NoOfChannels)
+
+                               outw(data[0],
+                                       devpriv->iobase + APCI1516_DIGITAL_OP);
+
+                               printk("EL311003 : d=%d @=%x\n", data[0],
+                                       devpriv->iobase + APCI1516_DIGITAL_OP);
+                       }       // if(data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       //else if(data[1]==1)
+               }               //elseif(data[1]==0)
+       }                       //if(data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] = (data[0] << ui_NoOfChannel) ^ 0xff;
+                               data[0] = data[0] & ui_Temp;
+                               outw(data[0],
+                                       devpriv->iobase + APCI1516_DIGITAL_OP);
+
+                               printk("EL311003 : d=%d @=%x\n", data[0],
+                                       devpriv->iobase + APCI1516_DIGITAL_OP);
+
+                       }       //if(data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       switch (ui_NoOfChannel) {
+
+                                       case 2:
+                                               data[0] = ~data[0] & 0x3;
+                                               ui_Temp1 = 3;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 2 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (2 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xff) & ui_Temp;
+                                               break;
+
+                                       case 4:
+                                               data[0] = ~data[0] & 0xf;
+                                               ui_Temp1 = 15;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 4 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (4 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xff) & ui_Temp;
+                                               break;
+
+                                       case 7:
+                                               break;
+
+                                       default:
+                                               comedi_error(dev,
+                                                       " chan spec wrong");
+                                               return -EINVAL; // "sorry channel spec wrong "
+
+                                       }       //switch(ui_NoOfChannels)
+
+                                       outw(data[0],
+                                               devpriv->iobase +
+                                               APCI1516_DIGITAL_OP);
+
+                                       printk("EL311003 : d=%d @=%x\n",
+                                               data[0],
+                                               devpriv->iobase +
+                                               APCI1516_DIGITAL_OP);
+                               }       // if(data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       //else if(data[1]==1)
+                       }       //elseif(data[1]==0)
+               }               //if(data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               //if else data[3]==1)
+       }                       //if else data[3]==0)
+       return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_ReadDigitalOutput                       |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data)                                         |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel or port           |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ui_Temp;
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+       ui_Temp = data[0];
+       *data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       //if(ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       switch (ui_NoOfChannel) {
+
+                       case 2:
+                               *data = (*data >> (2 * data[1])) & 3;
+                               break;
+
+                       case 4:
+                               *data = (*data >> (4 * data[1])) & 15;
+                               break;
+
+                       case 7:
+                               break;
+
+                       default:
+                               comedi_error(dev, " chan spec wrong");
+                               return -EINVAL; // "sorry channel spec wrong "
+
+                       }       //switch(ui_NoOfChannels)
+               }               //if(ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               //elseif(ui_Temp==1)
+       }                       //elseif(ui_Temp==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_ConfigWatchdog(comedi_device *dev,
+                      comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)  |
+|                                                                                   |
++----------------------------------------------------------------------------+
+| Task              : Configures The Watchdog                                |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status                                                     |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       if (data[0] == 0) {
+               //Disable the watchdog
+               outw(0x0,
+                       devpriv->i_IobaseAddon +
+                       APCI1516_WATCHDOG_ENABLEDISABLE);
+               //Loading the Reload value
+               outw(data[1],
+                       devpriv->i_IobaseAddon +
+                       APCI1516_WATCHDOG_RELOAD_VALUE);
+               data[1] = data[1] >> 16;
+               outw(data[1],
+                       devpriv->i_IobaseAddon +
+                       APCI1516_WATCHDOG_RELOAD_VALUE + 2);
+       }                       //if(data[0]==0)
+       else {
+               printk("\nThe input parameters are wrong\n");
+               return -EINVAL;
+       }                       //elseif(data[0]==0)
+
+       return insn->n;
+}
+
+ /*
+    +----------------------------------------------------------------------------+
+    | Function   Name   : int i_APCI1516_StartStopWriteWatchdog                  |
+    |                           (comedi_device *dev,comedi_subdevice *s,
+    comedi_insn *insn,lsampl_t *data);                      |
+    +----------------------------------------------------------------------------+
+    | Task              : Start / Stop The Watchdog                              |
+    +----------------------------------------------------------------------------+
+    | Input Parameters  : comedi_device *dev      : Driver handle                |
+    |                     comedi_subdevice *s,   :pointer to subdevice structure
+    comedi_insn *insn      :pointer to insn structure      |
+    |                     lsampl_t *data          : Data Pointer to read status  |
+    +----------------------------------------------------------------------------+
+    | Output Parameters :       --                                                                                                       |
+    +----------------------------------------------------------------------------+
+    | Return Value      : TRUE  : No error occur                                 |
+    |                       : FALSE : Error occur. Return the error          |
+    |                                                                            |
+    +----------------------------------------------------------------------------+
+  */
+
+int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       switch (data[0]) {
+       case 0:         //stop the watchdog
+               outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);    //disable the watchdog
+               break;
+       case 1:         //start the watchdog
+               outw(0x0001,
+                       devpriv->i_IobaseAddon +
+                       APCI1516_WATCHDOG_ENABLEDISABLE);
+               break;
+       case 2:         //Software trigger
+               outw(0x0201,
+                       devpriv->i_IobaseAddon +
+                       APCI1516_WATCHDOG_ENABLEDISABLE);
+               break;
+       default:
+               printk("\nSpecified functionality does not exist\n");
+               return -EINVAL;
+       }                       // switch(data[0])
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_ReadWatchdog                            |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data);                                        |
++----------------------------------------------------------------------------+
+| Task              : Read The Watchdog                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1516_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1516_Reset(comedi_device *dev)               |                                                                                                          |
++----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_Reset(comedi_device * dev)
+{
+       outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);       //RESETS THE DIGITAL OUTPUTS
+       outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
+       outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE);
+       outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE + 2);
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
new file mode 100644 (file)
index 0000000..7c77d67
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+/*********      Definitions for APCI-1516 card  *****/
+
+// Card Specific information
+#define APCI1516_BOARD_VENDOR_ID                 0x15B8
+#define APCI1516_ADDRESS_RANGE                   8
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI1516_DIGITAL_OP                    4
+#define APCI1516_DIGITAL_OP_RW                         4
+#define APCI1516_DIGITAL_IP                     0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_WATCHDOG                          2
+#define APCI1516_DIGITAL_OP_WATCHDOG               0
+#define APCI1516_WATCHDOG_ENABLEDISABLE            12
+#define APCI1516_WATCHDOG_RELOAD_VALUE             4
+#define APCI1516_WATCHDOG_STATUS                   16
+
+// Hardware Layer  functions for Apci1516
+
+//Digital Input
+INT i_APCI1516_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1516_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//Digital Output
+int i_APCI1516_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1516_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1516_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// TIMER
+// timer value is passed as u seconds
+int i_APCI1516_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI1516_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI1516_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//reset
+INT i_APCI1516_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
new file mode 100644 (file)
index 0000000..f922534
--- /dev/null
@@ -0,0 +1,1105 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-1564       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci1564.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-1564                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include <linux/delay.h>
+#include "hwdrv_apci1564.h"
+
+//Global variables
+UINT ui_InterruptStatus_1564 = 0;
+UINT ui_InterruptData, ui_Type;
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_ConfigDigitalInput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures the digital input Subdevice                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     lsampl_t *data         : Data Pointer contains         |
+|                                          configuration parameters as below |
+|                                                                            |
+|                        data[0]            : 1 Enable  Digital Input Interrupt |
+|                                                                 0 Disable Digital Input Interrupt |
+|                        data[1]            : 0 ADDIDATA Interrupt OR LOGIC     |
+|                                                               : 1 ADDIDATA Interrupt AND LOGIC    |
+|                        data[2]                        : Interrupt mask for the mode 1         |
+|                        data[3]                        : Interrupt mask for the mode 2         |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       devpriv->tsk_Current = current;
+   /*******************************/
+       /* Set the digital input logic */
+   /*******************************/
+       if (data[0] == ADDIDATA_ENABLE) {
+               data[2] = data[2] << 4;
+               data[3] = data[3] << 4;
+               outl(data[2],
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
+               outl(data[3],
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
+               if (data[1] == ADDIDATA_OR) {
+                       outl(0x4,
+                               devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                               APCI1564_DIGITAL_IP_IRQ);
+               }               // if  (data[1] == ADDIDATA_OR)
+               else {
+                       outl(0x6,
+                               devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                               APCI1564_DIGITAL_IP_IRQ);
+               }               // else if  (data[1] == ADDIDATA_OR)
+       }                       // if  (data[0] == ADDIDATA_ENABLE)
+       else {
+               outl(0x0,
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
+               outl(0x0,
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
+               outl(0x0,
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_IRQ);
+       }                       // else if  (data[0] == ADDIDATA_ENABLE)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_Read1DigitalInput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the digital input                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                            UINT ui_Channel : Channel number to read       |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_TmpValue = 0;
+       UINT ui_Channel;
+
+       ui_Channel = CR_CHAN(insn->chanspec);
+       if (ui_Channel >= 0 && ui_Channel <= 31) {
+               ui_TmpValue =
+                       (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+               //  since only 1 channel reqd  to bring it to last bit it is rotated
+               //  8 +(chan - 1) times then ANDed with 1 for last bit.
+               *data = (ui_TmpValue >> ui_Channel) & 0x1;
+       }                       // if  (ui_Channel >= 0 && ui_Channel <=31)
+       else {
+               comedi_error(dev, "Not a valid channel number !!! \n");
+               return -EINVAL; // "sorry channel spec wrong "
+       }                       //else if  (ui_Channel >= 0 && ui_Channel <=31)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_ReadMoreDigitalInput                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                     comedi_insn *insn,lsampl_t *data)                      |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the Requested digital inputs      |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To be Read    |
+|                      UINT *data             : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_PortValue = data[0];
+       UINT ui_Mask = 0;
+       UINT ui_NoOfChannels;
+
+       ui_NoOfChannels = CR_CHAN(insn->chanspec);
+       if (data[1] == 0) {
+               *data = (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+               switch (ui_NoOfChannels) {
+               case 2:
+                       ui_Mask = 3;
+                       *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 4:
+                       ui_Mask = 15;
+                       *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 8:
+                       ui_Mask = 255;
+                       *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 16:
+                       ui_Mask = 65535;
+                       *data = (*data >> (16 * ui_PortValue)) & ui_Mask;
+                       break;
+               case 31:
+                       break;
+               default:
+                       comedi_error(dev, "Not a valid Channel number !!!\n");
+                       return -EINVAL; // "sorry channel spec wrong "
+                       break;
+               }               // switch  (ui_NoOfChannels)
+       }                       // if  (data[1]==0)
+       else {
+               if (data[1] == 1) {
+                       *data = ui_InterruptStatus_1564;
+               }               // if  (data[1]==1)
+       }                       // else if  (data[1]==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_ConfigDigitalOutput                     |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Digital Output Subdevice.               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[1]            : 1 Enable  VCC  Interrupt  |
+|                                                                                 0 Disable VCC  Interrupt  |
+|                                        data[2]            : 1 Enable  CC  Interrupt   |
+|                                                                                 0 Disable CC  Interrupt   |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command = 0;
+
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Not a valid Data !!! ,Data should be 1 or 0\n");
+               return -EINVAL;
+       }                       // if  ((data[0]!=0) && (data[0]!=1))
+       if (data[0]) {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+       }                       // if  (data[0])
+       else {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+       }                       // else if  (data[0])
+       if (data[1] == ADDIDATA_ENABLE) {
+               ul_Command = ul_Command | 0x1;
+       }                       // if  (data[1] == ADDIDATA_ENABLE)
+       else {
+               ul_Command = ul_Command & 0xFFFFFFFE;
+       }                       // else if  (data[1] == ADDIDATA_ENABLE)
+       if (data[2] == ADDIDATA_ENABLE) {
+               ul_Command = ul_Command | 0x2;
+       }                       // if  (data[2] == ADDIDATA_ENABLE)
+       else {
+               ul_Command = ul_Command & 0xFFFFFFFD;
+       }                       // else if  (data[2] == ADDIDATA_ENABLE)
+       outl(ul_Command,
+               devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+               APCI1564_DIGITAL_OP_INTERRUPT);
+       ui_InterruptData =
+               inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+               APCI1564_DIGITAL_OP_INTERRUPT);
+       devpriv->tsk_Current = current;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_WriteDigitalOutput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp, ui_Temp1;
+       UINT ui_NoOfChannel;
+
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       if (devpriv->b_OutputMemoryStatus) {
+               ui_Temp =
+                       inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+                       APCI1564_DIGITAL_OP_RW);
+       }                       // if  (devpriv->b_OutputMemoryStatus )
+       else {
+               ui_Temp = 0;
+       }                       // else if  (devpriv->b_OutputMemoryStatus )
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outl(data[0],
+                               devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+                               APCI1564_DIGITAL_OP_RW);
+               }               // if  (data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               switch (ui_NoOfChannel) {
+                               case 2:
+                                       data[0] =
+                                               (data[0] << (2 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 4:
+                                       data[0] =
+                                               (data[0] << (4 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 8:
+                                       data[0] =
+                                               (data[0] << (8 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 16:
+                                       data[0] =
+                                               (data[0] << (16 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 31:
+                                       data[0] = data[0] | ui_Temp;
+                                       break;
+                               default:
+                                       comedi_error(dev, " chan spec wrong");
+                                       return -EINVAL; // "sorry channel spec wrong "
+                               }       // switch (ui_NoOfChannels)
+                               outl(data[0],
+                                       devpriv->i_IobaseAmcc +
+                                       APCI1564_DIGITAL_OP +
+                                       APCI1564_DIGITAL_OP_RW);
+                       }       // if  (data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       // else if  (data[1]==1)
+               }               // else if (data[1]==0)
+       }                       //if(data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] =
+                                       (data[0] << ui_NoOfChannel) ^
+                                       0xffffffff;
+                               data[0] = data[0] & ui_Temp;
+                               outl(data[0],
+                                       devpriv->i_IobaseAmcc +
+                                       APCI1564_DIGITAL_OP +
+                                       APCI1564_DIGITAL_OP_RW);
+                       }       // if  (data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       switch (ui_NoOfChannel) {
+                                       case 2:
+                                               data[0] = ~data[0] & 0x3;
+                                               ui_Temp1 = 3;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 2 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (2 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+                                       case 4:
+                                               data[0] = ~data[0] & 0xf;
+                                               ui_Temp1 = 15;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 4 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (4 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+                                       case 8:
+                                               data[0] = ~data[0] & 0xff;
+                                               ui_Temp1 = 255;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 8 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (8 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+                                       case 16:
+                                               data[0] = ~data[0] & 0xffff;
+                                               ui_Temp1 = 65535;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 16 *
+                                                       data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (16 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+                                       case 31:
+                                               break;
+                                       default:
+                                               comedi_error(dev,
+                                                       " chan spec wrong");
+                                               return -EINVAL; // "sorry channel spec wrong "
+                                       }       //switch(ui_NoOfChannels)
+                                       outl(data[0],
+                                               devpriv->i_IobaseAmcc +
+                                               APCI1564_DIGITAL_OP +
+                                               APCI1564_DIGITAL_OP_RW);
+                               }       // if  (data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       // else if  (data[1]==1)
+                       }       // else if  (data[1]==0)
+               }               // if  (data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               // else if (data[3]==1)
+       }                       // else if (data[3]==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_ReadDigitalOutput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel or port           |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp;
+       UINT ui_NoOfChannel;
+
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       ui_Temp = data[0];
+       *data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+               APCI1564_DIGITAL_OP_RW);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       // if  (ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       switch (ui_NoOfChannel) {
+                       case 2:
+                               *data = (*data >> (2 * data[1])) & 3;
+                               break;
+
+                       case 4:
+                               *data = (*data >> (4 * data[1])) & 15;
+                               break;
+
+                       case 8:
+                               *data = (*data >> (8 * data[1])) & 255;
+                               break;
+
+                       case 16:
+                               *data = (*data >> (16 * data[1])) & 65535;
+                               break;
+
+                       case 31:
+                               break;
+
+                       default:
+                               comedi_error(dev, " chan spec wrong");
+                               return -EINVAL; // "sorry channel spec wrong "
+                               break;
+                       }       // switch(ui_NoOfChannels)
+               }               // if  (ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               // else if (ui_Temp==1)
+       }                       // else if  (ui_Temp==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_ConfigTimerCounterWatchdog              |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Timer , Counter or Watchdog             |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[0]            : 0 Configure As Timer      |
+|                                                                                 1 Configure As Counter    |
+|                                                                                 2 Configure As Watchdog   |
+|                                        data[1]            : 1 Enable  Interrupt       |
+|                                                                                 0 Disable Interrupt       |
+|                                        data[2]            : Time Unit                 |
+|                                        data[3]                        : Reload Value                      |
+|                                        data[4]            : Timer Mode                |
+|                                        data[5]                        : Timer Counter Watchdog Number|
+                              data[6]            :  Counter Direction
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command1 = 0;
+       devpriv->tsk_Current = current;
+       if (data[0] == ADDIDATA_WATCHDOG) {
+               devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+
+               //Disable the watchdog
+               outl(0x0,
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+                       APCI1564_TCW_PROG);
+               //Loading the Reload value
+               outl(data[3],
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+                       APCI1564_TCW_RELOAD_VALUE);
+       }                       // if  (data[0]==ADDIDATA_WATCHDOG)
+       else if (data[0] == ADDIDATA_TIMER) {
+               //First Stop The Timer
+               ul_Command1 =
+                       inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_PROG);
+               ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+               outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);  //Stop The Timer
+
+               devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+               if (data[1] == 1) {
+                       outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
+                       outl(0x0,
+                               devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                               APCI1564_DIGITAL_IP_IRQ);
+                       outl(0x0,
+                               devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+                               APCI1564_DIGITAL_OP_IRQ);
+                       outl(0x0,
+                               devpriv->i_IobaseAmcc +
+                               APCI1564_DIGITAL_OP_WATCHDOG +
+                               APCI1564_TCW_IRQ);
+                       outl(0x0,
+                               devpriv->iobase + APCI1564_COUNTER1 +
+                               APCI1564_TCW_IRQ);
+                       outl(0x0,
+                               devpriv->iobase + APCI1564_COUNTER2 +
+                               APCI1564_TCW_IRQ);
+                       outl(0x0,
+                               devpriv->iobase + APCI1564_COUNTER3 +
+                               APCI1564_TCW_IRQ);
+                       outl(0x0,
+                               devpriv->iobase + APCI1564_COUNTER4 +
+                               APCI1564_TCW_IRQ);
+               }               // if  (data[1]==1)
+               else {
+                       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);  //disable Timer interrupt
+               }               // else if  (data[1]==1)
+
+               // Loading Timebase
+
+               outl(data[2],
+                       devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_TIMEBASE);
+
+               //Loading the Reload value
+               outl(data[3],
+                       devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_RELOAD_VALUE);
+
+               ul_Command1 =
+                       inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_PROG);
+               ul_Command1 =
+                       (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
+               outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);  //mode 2
+       }                       // else if  (data[0]==ADDIDATA_TIMER)
+       else if (data[0] == ADDIDATA_COUNTER) {
+               devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
+               devpriv->b_ModeSelectRegister = data[5];
+
+               //First Stop The Counter
+               ul_Command1 =
+                       inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
+                       APCI1564_TCW_PROG);
+               ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+               outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG);        //Stop The Timer
+
+      /************************/
+               /* Set the reload value */
+      /************************/
+               outl(data[3],
+                       devpriv->iobase + ((data[5] - 1) * 0x20) +
+                       APCI1564_TCW_RELOAD_VALUE);
+
+      /******************************/
+               /* Set the mode :             */
+               /* - Disable the hardware     */
+               /* - Disable the counter mode */
+               /* - Disable the warning      */
+               /* - Disable the reset        */
+               /* - Disable the timer mode   */
+               /* - Enable the counter mode  */
+      /******************************/
+               ul_Command1 =
+                       (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
+                       (ULONG) ((ULONG) data[4] << 16UL);
+               outl(ul_Command1,
+                       devpriv->iobase + ((data[5] - 1) * 0x20) +
+                       APCI1564_TCW_PROG);
+
+               // Enable or Disable Interrupt
+               ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
+               outl(ul_Command1,
+                       devpriv->iobase + ((data[5] - 1) * 0x20) +
+                       APCI1564_TCW_PROG);
+
+      /*****************************/
+               /* Set the Up/Down selection */
+      /*****************************/
+               ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
+               outl(ul_Command1,
+                       devpriv->iobase + ((data[5] - 1) * 0x20) +
+                       APCI1564_TCW_PROG);
+       }                       // else if  (data[0]==ADDIDATA_COUNTER)
+       else {
+               printk(" Invalid subdevice.");
+       }                       // else if  (data[0]==ADDIDATA_WATCHDOG)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_StartStopWriteTimerCounterWatchdog      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[0]            : 0 Timer                   |
+|                                                                                 1 Counter                 |
+|                                                                                 2 Watchdog                    |                             |                                                 data[1]            : 1 Start                   |
+|                                                                                 0 Stop                    |
+|                                                  2 Trigger                    |
+|                                                    Clear (Only Counter)    |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command1 = 0;
+       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+               switch (data[1]) {
+               case 0: //stop the watchdog
+                       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG);    //disable the watchdog
+                       break;
+               case 1: //start the watchdog
+                       outl(0x0001,
+                               devpriv->i_IobaseAmcc +
+                               APCI1564_DIGITAL_OP_WATCHDOG +
+                               APCI1564_TCW_PROG);
+                       break;
+               case 2: //Software trigger
+                       outl(0x0201,
+                               devpriv->i_IobaseAmcc +
+                               APCI1564_DIGITAL_OP_WATCHDOG +
+                               APCI1564_TCW_PROG);
+                       break;
+               default:
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               // switch (data[1])
+       }                       // if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+       if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+               if (data[1] == 1) {
+                       ul_Command1 =
+                               inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                               APCI1564_TCW_PROG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+
+                       //Enable the Timer
+                       outl(ul_Command1,
+                               devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                               APCI1564_TCW_PROG);
+               }               // if  (data[1]==1)
+               else if (data[1] == 0) {
+                       //Stop The Timer
+
+                       ul_Command1 =
+                               inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                               APCI1564_TCW_PROG);
+                       ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+                       outl(ul_Command1,
+                               devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                               APCI1564_TCW_PROG);
+               }               // else if(data[1]==0)
+       }                       // if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+       if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+               ul_Command1 =
+                       inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+                                       1) * 0x20) + APCI1564_TCW_PROG);
+               if (data[1] == 1) {
+                       //Start the Counter subdevice
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+               }               // if  (data[1] == 1)
+               else if (data[1] == 0) {
+                       // Stops the Counter subdevice
+                       ul_Command1 = 0;
+
+               }               // else if  (data[1] == 0)
+               else if (data[1] == 2) {
+                       // Clears the Counter subdevice
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
+               }               // else if  (data[1] == 3)
+               outl(ul_Command1,
+                       devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+                                       1) * 0x20) + APCI1564_TCW_PROG);
+       }                       // if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_ReadTimerCounterWatchdog                |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read The Selected Timer , Counter or Watchdog          |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command1 = 0;
+
+       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+               // Stores the status of the Watchdog
+               data[0] =
+                       inl(devpriv->i_IobaseAmcc +
+                       APCI1564_DIGITAL_OP_WATCHDOG +
+                       APCI1564_TCW_TRIG_STATUS) & 0x1;
+               data[1] =
+                       inl(devpriv->i_IobaseAmcc +
+                       APCI1564_DIGITAL_OP_WATCHDOG);
+       }                       // if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+       else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+               // Stores the status of the Timer
+               data[0] =
+                       inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_TRIG_STATUS) & 0x1;
+
+               // Stores the Actual value of the Timer
+               data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
+       }                       // else if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+       else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+               // Read the Counter Actual Value.
+               data[0] =
+                       inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+                                       1) * 0x20) +
+                       APCI1564_TCW_SYNC_ENABLEDISABLE);
+               ul_Command1 =
+                       inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+                                       1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
+
+      /***********************************/
+               /* Get the software trigger status */
+      /***********************************/
+               data[1] = (BYTE) ((ul_Command1 >> 1) & 1);
+
+      /***********************************/
+               /* Get the hardware trigger status */
+      /***********************************/
+               data[2] = (BYTE) ((ul_Command1 >> 2) & 1);
+
+      /*********************************/
+               /* Get the software clear status */
+      /*********************************/
+               data[3] = (BYTE) ((ul_Command1 >> 3) & 1);
+
+      /***************************/
+               /* Get the overflow status */
+      /***************************/
+               data[4] = (BYTE) ((ul_Command1 >> 0) & 1);
+       }                       // else  if  (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
+       else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+               && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
+               && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
+               printk("\n Invalid Subdevice !!!\n");
+       }                       // else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER))
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   :  int i_APCI1564_ReadInterruptStatus                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              :Reads the interrupt status register                     |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                        |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1564_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       *data = ui_Type;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : static void v_APCI1564_Interrupt                                      |
+|                                        (int irq , void *d)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt handler for the interruptible digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+static VOID v_APCI1564_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+       UINT ui_DO, ui_DI;
+       UINT ui_Timer;
+       UINT ui_C1, ui_C2, ui_C3, ui_C4;
+       ULONG ul_Command2 = 0;
+       ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+               APCI1564_DIGITAL_IP_IRQ) & 0x01;
+       ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+               APCI1564_DIGITAL_OP_IRQ) & 0x01;
+       ui_Timer =
+               inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+               APCI1564_TCW_IRQ) & 0x01;
+       ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 +
+               APCI1564_TCW_IRQ) & 0x1;
+       ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 +
+               APCI1564_TCW_IRQ) & 0x1;
+       ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 +
+               APCI1564_TCW_IRQ) & 0x1;
+       ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 +
+               APCI1564_TCW_IRQ) & 0x1;
+       if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
+               && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
+               printk("\nInterrupt from unknown source\n");
+       }                       // if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0)
+
+       if (ui_DI == 1) {
+               ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_IRQ);
+               outl(0x0,
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_IRQ);
+               ui_InterruptStatus_1564 =
+                       inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+                       APCI1564_DIGITAL_IP_INTERRUPT_STATUS);
+               ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
+               send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+               outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ);     //enable the interrupt
+               return;
+       }
+
+       if (ui_DO == 1) {
+               // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
+               ui_Type =
+                       inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+                       APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
+               //Disable the  Interrupt
+               outl(0x0,
+                       devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+                       APCI1564_DIGITAL_OP_INTERRUPT);
+
+               //Sends signal to user space
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+       }                       // if  (ui_DO)
+
+       if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_TIMER)) {
+               // Disable Timer Interrupt
+               ul_Command2 =
+                       inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_PROG);
+               outl(0x0,
+                       devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_PROG);
+
+               //Send a signal to from kernel to user space
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+               // Enable Timer Interrupt
+
+               outl(ul_Command2,
+                       devpriv->i_IobaseAmcc + APCI1564_TIMER +
+                       APCI1564_TCW_PROG);
+       }                       // if  ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER))
+
+       if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+               // Disable Counter Interrupt
+               ul_Command2 =
+                       inl(devpriv->iobase + APCI1564_COUNTER1 +
+                       APCI1564_TCW_PROG);
+               outl(0x0,
+                       devpriv->iobase + APCI1564_COUNTER1 +
+                       APCI1564_TCW_PROG);
+
+               //Send a signal to from kernel to user space
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+               // Enable Counter Interrupt
+               outl(ul_Command2,
+                       devpriv->iobase + APCI1564_COUNTER1 +
+                       APCI1564_TCW_PROG);
+       }                       // if  ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER))
+
+       if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+               // Disable Counter Interrupt
+               ul_Command2 =
+                       inl(devpriv->iobase + APCI1564_COUNTER2 +
+                       APCI1564_TCW_PROG);
+               outl(0x0,
+                       devpriv->iobase + APCI1564_COUNTER2 +
+                       APCI1564_TCW_PROG);
+
+               //Send a signal to from kernel to user space
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+               // Enable Counter Interrupt
+               outl(ul_Command2,
+                       devpriv->iobase + APCI1564_COUNTER2 +
+                       APCI1564_TCW_PROG);
+       }                       // if  ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
+
+       if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+               // Disable Counter Interrupt
+               ul_Command2 =
+                       inl(devpriv->iobase + APCI1564_COUNTER3 +
+                       APCI1564_TCW_PROG);
+               outl(0x0,
+                       devpriv->iobase + APCI1564_COUNTER3 +
+                       APCI1564_TCW_PROG);
+
+               //Send a signal to from kernel to user space
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+               // Enable Counter Interrupt
+               outl(ul_Command2,
+                       devpriv->iobase + APCI1564_COUNTER3 +
+                       APCI1564_TCW_PROG);
+       }                       // if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
+
+       if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+               // Disable Counter Interrupt
+               ul_Command2 =
+                       inl(devpriv->iobase + APCI1564_COUNTER4 +
+                       APCI1564_TCW_PROG);
+               outl(0x0,
+                       devpriv->iobase + APCI1564_COUNTER4 +
+                       APCI1564_TCW_PROG);
+
+               //Send a signal to from kernel to user space
+               send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+               // Enable Counter Interrupt
+               outl(ul_Command2,
+                       devpriv->iobase + APCI1564_COUNTER4 +
+                       APCI1564_TCW_PROG);
+       }                       // if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
+       return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI1564_Reset(comedi_device *dev)               |                                                       |
++----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1564_Reset(comedi_device * dev)
+{
+       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);     //disable the interrupts
+       inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);      //Reset the interrupt status register
+       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt
+       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
+       devpriv->b_DigitalOutputRegister = 0;
+       ui_Type = 0;
+       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); //Resets the output channels
+       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT);       //Disables the interrupt.
+       outl(0x0,
+               devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+               APCI1564_TCW_RELOAD_VALUE);
+       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER);
+       outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);
+
+       outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG);
+       outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG);
+       outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG);
+       outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG);
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
new file mode 100644 (file)
index 0000000..bb226b9
--- /dev/null
@@ -0,0 +1,122 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+/*********      Definitions for APCI-1564 card  *****/
+
+#define APCI1564_BOARD_VENDOR_ID                0x15B8
+#define APCI1564_ADDRESS_RANGE                  128
+
+//DIGITAL INPUT-OUTPUT DEFINE
+// Input defines
+#define APCI1564_DIGITAL_IP                     0x04
+#define APCI1564_DIGITAL_IP_INTERRUPT_MODE1     4
+#define APCI1564_DIGITAL_IP_INTERRUPT_MODE2     8
+#define APCI1564_DIGITAL_IP_IRQ                 16
+
+// Output defines
+#define APCI1564_DIGITAL_OP                    0x18
+#define APCI1564_DIGITAL_OP_RW                 0
+#define APCI1564_DIGITAL_OP_INTERRUPT           4
+#define APCI1564_DIGITAL_OP_IRQ                 12
+
+//Digital Input IRQ Function Selection
+#define ADDIDATA_OR                             0
+#define ADDIDATA_AND                            1
+
+//Digital Input Interrupt Status
+#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS    12
+
+//Digital Output Interrupt Status
+#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS    8
+
+//Digital Input Interrupt Enable Disable.
+#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE    0x4
+#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE   0xFFFFFFFB
+
+//Digital Output Interrupt Enable Disable.
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE                            1
+#define ADDIDATA_DISABLE                           0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_TIMER                             0
+#define ADDIDATA_COUNTER                           1
+#define ADDIDATA_WATCHDOG                          2
+#define APCI1564_DIGITAL_OP_WATCHDOG               0x28
+#define APCI1564_TIMER                             0x48
+#define APCI1564_COUNTER1                          0x0
+#define APCI1564_COUNTER2                          0x20
+#define APCI1564_COUNTER3                          0x40
+#define APCI1564_COUNTER4                          0x60
+#define APCI1564_TCW_SYNC_ENABLEDISABLE            0
+#define APCI1564_TCW_RELOAD_VALUE                  4
+#define APCI1564_TCW_TIMEBASE                      8
+#define APCI1564_TCW_PROG                          12
+#define APCI1564_TCW_TRIG_STATUS                   16
+#define APCI1564_TCW_IRQ                           20
+#define APCI1564_TCW_WARN_TIMEVAL                  24
+#define APCI1564_TCW_WARN_TIMEBASE                 28
+
+// Hardware Layer  functions for Apci1564
+
+//DI
+// for di read
+INT i_APCI1564_ConfigDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1564_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1564_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//DO
+int i_APCI1564_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1564_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI1564_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI1564_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// TIMER
+// timer value is passed as u seconds
+INT i_APCI1564_ConfigTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+int i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+int i_APCI1564_ReadTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+// INTERRUPT
+static VOID v_APCI1564_Interrupt(int irq, void *d);
+
+// RESET
+INT i_APCI1564_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
new file mode 100644 (file)
index 0000000..f505d90
--- /dev/null
@@ -0,0 +1,780 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : API APCI1648    | Compiler : gcc                        |
+  | Module name : TTL.C           | Version  : 2.96                       |
+  +-------------------------------+---------------------------------------+
+  | Project manager: S. Weber     | Date     :  25/05/2005                |
+  +-----------------------------------------------------------------------+
+  | Description :   APCI-16XX TTL I/O module                              |
+  |                                                                       |
+  |                                                                       |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |25.05.2005| S.Weber   | Creation                                       |
+  |          |           |                                                |
+  +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "hwdrv_apci16xx.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT   i_APCI16XX_InsnConfigInitTTLIO                   |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task           APCI16XX_TTL_INIT (using defaults)   :                      |
+|                Configure the TTL I/O operating mode from all ports         |
+|                You must calling this function be                           |
+|                for you call any other function witch access of TTL.        |
+|                APCI16XX_TTL_INITDIRECTION(user inputs for direction)       |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_InitType    = (BYTE) data[0];                        |
+|                     b_Port0Mode   = (BYTE) data[1];                        |
+|                     b_Port1Mode   = (BYTE) data[2];                        |
+|                     b_Port2Mode   = (BYTE) data[3];                        |
+|                     b_Port3Mode   = (BYTE) data[4];                        |
+|                     ........                                               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :>0: No error                                            |
+|                    -1: Port 0 mode selection is wrong                      |
+|                    -2: Port 1 mode selection is wrong                      |
+|                    -3: Port 2 mode selection is wrong                      |
+|                    -4: Port 3 mode selection is wrong                      |
+|                    -X: Port X-1 mode selection is wrong                    |
+|                    ....                                                    |
+|                    -100 : Config command error                             |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Command = 0;
+       BYTE b_Cpt = 0;
+       BYTE b_NumberOfPort =
+               (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /*******************/
+               /* Get the command */
+               /* **************** */
+
+               b_Command = (BYTE) data[0];
+
+          /********************/
+               /* Test the command */
+          /********************/
+
+               if ((b_Command == APCI16XX_TTL_INIT) ||
+                       (b_Command == APCI16XX_TTL_INITDIRECTION) ||
+                       (b_Command == APCI16XX_TTL_OUTPUTMEMORY)) {
+             /***************************************/
+                       /* Test the initialisation buffer size */
+             /***************************************/
+
+                       if ((b_Command == APCI16XX_TTL_INITDIRECTION)
+                               && ((BYTE) (insn->n - 1) != b_NumberOfPort)) {
+                /*******************/
+                               /* Data size error */
+                /*******************/
+
+                               printk("\nBuffer size error");
+                               i_ReturnValue = -101;
+                       }
+
+                       if ((b_Command == APCI16XX_TTL_OUTPUTMEMORY)
+                               && ((BYTE) (insn->n) != 2)) {
+                /*******************/
+                               /* Data size error */
+                /*******************/
+
+                               printk("\nBuffer size error");
+                               i_ReturnValue = -101;
+                       }
+               } else {
+             /************************/
+                       /* Config command error */
+             /************************/
+
+                       printk("\nCommand selection error");
+                       i_ReturnValue = -100;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("\nBuffer size error");
+               i_ReturnValue = -101;
+       }
+
+       /**************************************************************************/
+       /* Test if no error occur and APCI16XX_TTL_INITDIRECTION command selected */
+       /**************************************************************************/
+
+       if ((i_ReturnValue >= 0) && (b_Command == APCI16XX_TTL_INITDIRECTION)) {
+               memset(devpriv->ul_TTLPortConfiguration, 0,
+                       sizeof(devpriv->ul_TTLPortConfiguration));
+
+          /*************************************/
+               /* Test the port direction selection */
+          /*************************************/
+
+               for (b_Cpt = 1;
+                       (b_Cpt <= b_NumberOfPort) && (i_ReturnValue >= 0);
+                       b_Cpt++) {
+             /**********************/
+                       /* Test the direction */
+             /**********************/
+
+                       if ((data[b_Cpt] != 0) && (data[b_Cpt] != 0xFF)) {
+                /************************/
+                               /* Port direction error */
+                /************************/
+
+                               printk("\nPort %d direction selection error",
+                                       (INT) b_Cpt);
+                               i_ReturnValue = -(INT) b_Cpt;
+                       }
+
+             /**************************/
+                       /* Save the configuration */
+             /**************************/
+
+                       devpriv->ul_TTLPortConfiguration[(b_Cpt - 1) / 4] =
+                               devpriv->ul_TTLPortConfiguration[(b_Cpt -
+                                       1) / 4] | (data[b_Cpt] << (8 * ((b_Cpt -
+                                                       1) % 4)));
+               }
+       }
+
+       /**************************/
+       /* Test if no error occur */
+       /**************************/
+
+       if (i_ReturnValue >= 0) {
+          /***********************************/
+               /* Test if TTL port initilaisation */
+          /***********************************/
+
+               if ((b_Command == APCI16XX_TTL_INIT)
+                       || (b_Command == APCI16XX_TTL_INITDIRECTION)) {
+             /******************************/
+                       /* Set all port configuration */
+             /******************************/
+
+                       for (b_Cpt = 0; b_Cpt <= b_NumberOfPort; b_Cpt++) {
+                               if ((b_Cpt % 4) == 0) {
+                   /*************************/
+                                       /* Set the configuration */
+                   /*************************/
+
+                                       outl(devpriv->
+                                               ul_TTLPortConfiguration[b_Cpt /
+                                                       4],
+                                               devpriv->iobase + 32 + b_Cpt);
+                               }
+                       }
+               }
+       }
+
+       /************************************************/
+       /* Test if output memory initialisation command */
+       /************************************************/
+
+       if (b_Command == APCI16XX_TTL_OUTPUTMEMORY) {
+               if (data[1]) {
+                       devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+               } else {
+                       devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+               }
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            INPUT FUNCTIONS                                 |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT     i_APCI16XX_InsnBitsReadTTLIO                   |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task              : Read the status from selected TTL digital input        |
+|                     (b_InputChannel)                                       |
++----------------------------------------------------------------------------+
+| Task              : Read the status from digital input port                |
+|                     (b_SelectedPort)                                       |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                        |
+|              APCI16XX_TTL_READCHANNEL                                      |
+|                    b_SelectedPort= CR_RANGE(insn->chanspec);               |
+|                    b_InputChannel= CR_CHAN(insn->chanspec);                |
+|                    b_ReadType          = (BYTE) data[0];                          |
+|                                                                            |
+|              APCI16XX_TTL_READPORT                                         |
+|                    b_SelectedPort= CR_RANGE(insn->chanspec);               |
+|                    b_ReadType          = (BYTE) data[0];                          |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0]    0 : Channle is not active                   |
+|                                1 : Channle is active                       |
++----------------------------------------------------------------------------+
+| Return Value      : >0  : No error                                         |
+|                    -100 : Config command error                             |
+|                    -101 : Data size error                                  |
+|                    -102 : The selected TTL input port is wrong             |
+|                    -103 : The selected TTL digital input is wrong          |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Command = 0;
+       BYTE b_NumberOfPort =
+               (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+       BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
+       BYTE b_InputChannel = CR_CHAN(insn->chanspec);
+       BYTE *pb_Status;
+       DWORD dw_Status;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /*******************/
+               /* Get the command */
+               /* **************** */
+
+               b_Command = (BYTE) data[0];
+
+          /********************/
+               /* Test the command */
+          /********************/
+
+               if ((b_Command == APCI16XX_TTL_READCHANNEL)
+                       || (b_Command == APCI16XX_TTL_READPORT)) {
+             /**************************/
+                       /* Test the selected port */
+             /**************************/
+
+                       if (b_SelectedPort < b_NumberOfPort) {
+                /**********************/
+                               /* Test if input port */
+                /**********************/
+
+                               if (((devpriv->ul_TTLPortConfiguration
+                                                       [b_SelectedPort /
+                                                               4] >> (8 *
+                                                               (b_SelectedPort
+                                                                       %
+                                                                       4))) &
+                                               0xFF) == 0) {
+                   /***************************/
+                                       /* Test the channel number */
+                   /***************************/
+
+                                       if ((b_Command ==
+                                                       APCI16XX_TTL_READCHANNEL)
+                                               && (b_InputChannel > 7)) {
+                      /*******************************************/
+                                               /* The selected TTL digital input is wrong */
+                      /*******************************************/
+
+                                               printk("\nChannel selection error");
+                                               i_ReturnValue = -103;
+                                       }
+                               } else {
+                   /****************************************/
+                                       /* The selected TTL input port is wrong */
+                   /****************************************/
+
+                                       printk("\nPort selection error");
+                                       i_ReturnValue = -102;
+                               }
+                       } else {
+                /****************************************/
+                               /* The selected TTL input port is wrong */
+                /****************************************/
+
+                               printk("\nPort selection error");
+                               i_ReturnValue = -102;
+                       }
+               } else {
+             /************************/
+                       /* Config command error */
+             /************************/
+
+                       printk("\nCommand selection error");
+                       i_ReturnValue = -100;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("\nBuffer size error");
+               i_ReturnValue = -101;
+       }
+
+       /**************************/
+       /* Test if no error occur */
+       /**************************/
+
+       if (i_ReturnValue >= 0) {
+               pb_Status = (PBYTE) & data[0];
+
+          /*******************************/
+               /* Get the digital inpu status */
+          /*******************************/
+
+               dw_Status =
+                       inl(devpriv->iobase + 8 + ((b_SelectedPort / 4) * 4));
+               dw_Status = (dw_Status >> (8 * (b_SelectedPort % 4))) & 0xFF;
+
+          /***********************/
+               /* Save the port value */
+          /***********************/
+
+               *pb_Status = (BYTE) dw_Status;
+
+          /***************************************/
+               /* Test if read channel status command */
+          /***************************************/
+
+               if (b_Command == APCI16XX_TTL_READCHANNEL) {
+                       *pb_Status = (*pb_Status >> b_InputChannel) & 1;
+               }
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT i_APCI16XX_InsnReadTTLIOAllPortValue               |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task              : Read the status from all digital input ports           |
++----------------------------------------------------------------------------+
+| Input Parameters  : -                                                      |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Port 0 to 3 data                             |
+|                     data[1] : Port 4 to 7 data                             |
+|                     ....                                                   |
++----------------------------------------------------------------------------+
+| Return Value      : 0: No error                                            |
+|                    -100 : Read command error                               |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
+       INT i_ReturnValue = insn->n;
+       BYTE b_Cpt = 0;
+       BYTE b_NumberOfPort = 0;
+       lsampl_t *pls_ReadData = data;
+
+       /********************/
+       /* Test the command */
+       /********************/
+
+       if ((b_Command == APCI16XX_TTL_READ_ALL_INPUTS)
+               || (b_Command == APCI16XX_TTL_READ_ALL_OUTPUTS)) {
+          /**********************************/
+               /* Get the number of 32-Bit ports */
+          /**********************************/
+
+               b_NumberOfPort =
+                       (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 32);
+               if ((b_NumberOfPort * 32) <
+                       devpriv->ps_BoardInfo->i_NbrTTLChannel) {
+                       b_NumberOfPort = b_NumberOfPort + 1;
+               }
+
+          /************************/
+               /* Test the buffer size */
+          /************************/
+
+               if (insn->n >= b_NumberOfPort) {
+                       if (b_Command == APCI16XX_TTL_READ_ALL_INPUTS) {
+                /**************************/
+                               /* Read all digital input */
+                /**************************/
+
+                               for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
+                   /************************/
+                                       /* Read the 32-Bit port */
+                   /************************/
+
+                                       pls_ReadData[b_Cpt] =
+                                               inl(devpriv->iobase + 8 +
+                                               (b_Cpt * 4));
+
+                   /**************************************/
+                                       /* Mask all channels used als outputs */
+                   /**************************************/
+
+                                       pls_ReadData[b_Cpt] =
+                                               pls_ReadData[b_Cpt] &
+                                               (~devpriv->
+                                               ul_TTLPortConfiguration[b_Cpt]);
+                               }
+                       } else {
+                /****************************/
+                               /* Read all digital outputs */
+                /****************************/
+
+                               for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
+                   /************************/
+                                       /* Read the 32-Bit port */
+                   /************************/
+
+                                       pls_ReadData[b_Cpt] =
+                                               inl(devpriv->iobase + 20 +
+                                               (b_Cpt * 4));
+
+                   /**************************************/
+                                       /* Mask all channels used als outputs */
+                   /**************************************/
+
+                                       pls_ReadData[b_Cpt] =
+                                               pls_ReadData[b_Cpt] & devpriv->
+                                               ul_TTLPortConfiguration[b_Cpt];
+                               }
+                       }
+               } else {
+             /*******************/
+                       /* Data size error */
+             /*******************/
+
+                       printk("\nBuffer size error");
+                       i_ReturnValue = -101;
+               }
+       } else {
+          /*****************/
+               /* Command error */
+          /*****************/
+
+               printk("\nCommand selection error");
+               i_ReturnValue = -100;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            OUTPUT FUNCTIONS                                |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT     i_APCI16XX_InsnBitsWriteTTLIO                  |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task              : Set the state from selected TTL digital output         |
+|                     (b_OutputChannel)                                      |
++----------------------------------------------------------------------------+
+| Task              : Set the state from digital output port                 |
+|                     (b_SelectedPort)                                       |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                        |
+|              APCI16XX_TTL_WRITECHANNEL_ON | APCI16XX_TTL_WRITECHANNEL_OFF  |
+|                    b_SelectedPort = CR_RANGE(insn->chanspec);              |
+|                    b_OutputChannel= CR_CHAN(insn->chanspec);               |
+|                    b_Command      = (BYTE) data[0];                        |
+|                                                                            |
+|              APCI16XX_TTL_WRITEPORT_ON | APCI16XX_TTL_WRITEPORT_OFF        |
+|                    b_SelectedPort = CR_RANGE(insn->chanspec);              |
+|                    b_Command      = (BYTE) data[0];                        |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : TTL output port 0 to 3 data                  |
+|                     data[1] : TTL output port 4 to 7 data                  |
+|                     ....                                                   |
++----------------------------------------------------------------------------+
+| Return Value      : >0  : No error                                         |
+|                    -100 : Command error                                    |
+|                    -101 : Data size error                                  |
+|                    -102 : The selected TTL output port is wrong            |
+|                    -103 : The selected TTL digital output is wrong         |
+|                    -104 : Output memory disabled                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Command = 0;
+       BYTE b_NumberOfPort =
+               (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+       BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
+       BYTE b_OutputChannel = CR_CHAN(insn->chanspec);
+       DWORD dw_Status = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /*******************/
+               /* Get the command */
+               /* **************** */
+
+               b_Command = (BYTE) data[0];
+
+          /********************/
+               /* Test the command */
+          /********************/
+
+               if ((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) ||
+                       (b_Command == APCI16XX_TTL_WRITEPORT_ON) ||
+                       (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) ||
+                       (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) {
+             /**************************/
+                       /* Test the selected port */
+             /**************************/
+
+                       if (b_SelectedPort < b_NumberOfPort) {
+                /***********************/
+                               /* Test if output port */
+                /***********************/
+
+                               if (((devpriv->ul_TTLPortConfiguration
+                                                       [b_SelectedPort /
+                                                               4] >> (8 *
+                                                               (b_SelectedPort
+                                                                       %
+                                                                       4))) &
+                                               0xFF) == 0xFF) {
+                   /***************************/
+                                       /* Test the channel number */
+                   /***************************/
+
+                                       if (((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) || (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF)) && (b_OutputChannel > 7)) {
+                      /********************************************/
+                                               /* The selected TTL digital output is wrong */
+                      /********************************************/
+
+                                               printk("\nChannel selection error");
+                                               i_ReturnValue = -103;
+                                       }
+
+                                       if (((b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE)) {
+                      /********************************************/
+                                               /* The selected TTL digital output is wrong */
+                      /********************************************/
+
+                                               printk("\nOutput memory disabled");
+                                               i_ReturnValue = -104;
+                                       }
+
+                   /************************/
+                                       /* Test the buffer size */
+                   /************************/
+
+                                       if (((b_Command == APCI16XX_TTL_WRITEPORT_ON) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (insn->n < 2)) {
+                      /*******************/
+                                               /* Data size error */
+                      /*******************/
+
+                                               printk("\nBuffer size error");
+                                               i_ReturnValue = -101;
+                                       }
+                               } else {
+                   /*****************************************/
+                                       /* The selected TTL output port is wrong */
+                   /*****************************************/
+
+                                       printk("\nPort selection error %lX",
+                                               (unsigned long)devpriv->
+                                               ul_TTLPortConfiguration[0]);
+                                       i_ReturnValue = -102;
+                               }
+                       } else {
+                /****************************************/
+                               /* The selected TTL output port is wrong */
+                /****************************************/
+
+                               printk("\nPort selection error %d %d",
+                                       b_SelectedPort, b_NumberOfPort);
+                               i_ReturnValue = -102;
+                       }
+               } else {
+             /************************/
+                       /* Config command error */
+             /************************/
+
+                       printk("\nCommand selection error");
+                       i_ReturnValue = -100;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("\nBuffer size error");
+               i_ReturnValue = -101;
+       }
+
+       /**************************/
+       /* Test if no error occur */
+       /**************************/
+
+       if (i_ReturnValue >= 0) {
+          /********************************/
+               /* Get the digital output state */
+          /********************************/
+
+               dw_Status =
+                       inl(devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
+
+          /**********************************/
+               /* Test if output memory not used */
+          /**********************************/
+
+               if (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE) {
+             /*********************************/
+                       /* Clear the selected port value */
+             /*********************************/
+
+                       dw_Status =
+                               dw_Status & (0xFFFFFFFFUL -
+                               (0xFFUL << (8 * (b_SelectedPort % 4))));
+               }
+
+          /******************************/
+               /* Test if setting channel ON */
+          /******************************/
+
+               if (b_Command == APCI16XX_TTL_WRITECHANNEL_ON) {
+                       dw_Status =
+                               dw_Status | (1UL << ((8 * (b_SelectedPort %
+                                                       4)) + b_OutputChannel));
+               }
+
+          /***************************/
+               /* Test if setting port ON */
+          /***************************/
+
+               if (b_Command == APCI16XX_TTL_WRITEPORT_ON) {
+                       dw_Status =
+                               dw_Status | ((data[1] & 0xFF) << (8 *
+                                       (b_SelectedPort % 4)));
+               }
+
+          /*******************************/
+               /* Test if setting channel OFF */
+          /*******************************/
+
+               if (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) {
+                       dw_Status =
+                               dw_Status & (0xFFFFFFFFUL -
+                               (1UL << ((8 * (b_SelectedPort % 4)) +
+                                               b_OutputChannel)));
+               }
+
+          /****************************/
+               /* Test if setting port OFF */
+          /****************************/
+
+               if (b_Command == APCI16XX_TTL_WRITEPORT_OFF) {
+                       dw_Status =
+                               dw_Status & (0xFFFFFFFFUL -
+                               ((data[1] & 0xFF) << (8 * (b_SelectedPort %
+                                                       4))));
+               }
+
+               outl(dw_Status,
+                       devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_Reset(comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                     |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : -                                                      |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_Reset(comedi_device * dev)
+{
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
new file mode 100644 (file)
index 0000000..d7b3de3
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO   11 /* Digital Input Output But TTL */
+#endif
+
+#ifndef ADDIDATA_ENABLE
+#define ADDIDATA_ENABLE  1
+#define ADDIDATA_DISABLE 0
+#endif
+
+#define APCI16XX_TTL_INIT           0
+#define APCI16XX_TTL_INITDIRECTION  1
+#define APCI16XX_TTL_OUTPUTMEMORY   2
+
+#define APCI16XX_TTL_READCHANNEL            0
+#define APCI16XX_TTL_READPORT               1
+
+#define APCI16XX_TTL_WRITECHANNEL_ON        0
+#define APCI16XX_TTL_WRITECHANNEL_OFF       1
+#define APCI16XX_TTL_WRITEPORT_ON           2
+#define APCI16XX_TTL_WRITEPORT_OFF          3
+
+#define APCI16XX_TTL_READ_ALL_INPUTS        0
+#define APCI16XX_TTL_READ_ALL_OUTPUTS       1
+
+#ifdef __KERNEL__
+
+static const comedi_lrange range_apci16xx_ttl = { 12,
+       {BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+               BIP_RANGE(1)}
+};
+
+/*
++----------------------------------------------------------------------------+
+|                       TTL INISIALISATION FUNCTION                          |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnConfigInitTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*
++----------------------------------------------------------------------------+
+|                       TTL INPUT FUNCTION                                   |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsReadTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+int i_APCI16XX_InsnReadTTLIOAllPortValue(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*
++----------------------------------------------------------------------------+
+|                            TTL OUTPUT FUNCTIONS                            |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsWriteTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+int i_APCI16XX_Reset(comedi_device * dev);
+#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
new file mode 100644 (file)
index 0000000..7fad966
--- /dev/null
@@ -0,0 +1,460 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-2016       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci2016.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-2016                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci2016.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Digital Output Subdevice.               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                        data[0]            : 1 Digital Memory On               |
+|                                                         0 Digital Memory Off              |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Not a valid Data !!! ,Data should be 1 or 0\n");
+               return -EINVAL;
+       }                       // if  ((data[0]!=0) && (data[0]!=1))
+       if (data[0]) {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+       }                       // if  (data[0]
+       else {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+       }                       // else if  (data[0]
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2016_WriteDigitalOutput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_NoOfChannel;
+       UINT ui_Temp, ui_Temp1;
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+               comedi_error(dev,
+                       "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+               return -EINVAL;
+       }                       // if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
+       if (devpriv->b_OutputMemoryStatus) {
+               ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP);
+       }                       // if  (devpriv->b_OutputMemoryStatus )
+       else {
+               ui_Temp = 0;
+       }                       // else if  (devpriv->b_OutputMemoryStatus )
+       if ((data[1] != 0) && (data[1] != 1)) {
+               comedi_error(dev,
+                       "Invalid Data[1] value !!!, Data[1] should be 0 or 1\n");
+               return -EINVAL;
+       }                       // if  ((data[1]!=0) && (data[1]!=1))
+
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP);
+               }               // if (data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               switch (ui_NoOfChannel) {
+                               case 2:
+                                       data[0] =
+                                               (data[0] << (2 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 4:
+                                       data[0] =
+                                               (data[0] << (4 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 8:
+                                       data[0] =
+                                               (data[0] << (8 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 15:
+                                       data[0] = data[0] | ui_Temp;
+                                       break;
+                               default:
+                                       comedi_error(dev, " chan spec wrong");
+                                       return -EINVAL; // "sorry channel spec wrong "
+                               }       //switch(ui_NoOfChannels)
+                               outw(data[0],
+                                       devpriv->iobase + APCI2016_DIGITAL_OP);
+                       }       // if  (data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       // else if  (data[1]==1)
+               }               // else if (data[1]==0)
+       }                       // if (data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
+                               data[0] = data[0] & ui_Temp;
+                               outw(data[0],
+                                       devpriv->iobase + APCI2016_DIGITAL_OP);
+                       }       // if  (data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       switch (ui_NoOfChannel) {
+                                       case 2:
+                                               data[0] = ~data[0] & 0x3;
+                                               ui_Temp1 = 3;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 2 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (2 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffff) & ui_Temp;
+                                               break;
+                                       case 4:
+                                               data[0] = ~data[0] & 0xf;
+                                               ui_Temp1 = 15;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 4 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (4 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffff) & ui_Temp;
+                                               break;
+                                       case 8:
+                                               data[0] = ~data[0] & 0xff;
+                                               ui_Temp1 = 255;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 8 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (8 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffff) & ui_Temp;
+                                               break;
+                                       case 15:
+                                               break;
+                                       default:
+                                               comedi_error(dev,
+                                                       " chan spec wrong");
+                                               return -EINVAL; // "sorry channel spec wrong "
+                                       }       //switch(ui_NoOfChannels)
+                                       outw(data[0],
+                                               devpriv->iobase +
+                                               APCI2016_DIGITAL_OP);
+                               }       // if(data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       //else if(data[1]==1)
+                       }       //elseif(data[1]==0)
+               }               //if(data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               //if else data[3]==1)
+       }                       //if else data[3]==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2016_BitsDigitalOutput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel or port           |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp;
+       UINT ui_NoOfChannel;
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+               comedi_error(dev,
+                       "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+               return -EINVAL;
+       }                       // if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Invalid Data[0] value !!!, Data[0] should be 0 or 1\n");
+               return -EINVAL;
+       }                       // if  ((data[0]!=0) && (data[0]!=1))
+       ui_Temp = data[0];
+       *data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       // if  (ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       switch (ui_NoOfChannel) {
+                       case 2:
+                               *data = (*data >> (2 * data[1])) & 3;
+                               break;
+
+                       case 4:
+                               *data = (*data >> (4 * data[1])) & 15;
+                               break;
+
+                       case 8:
+                               *data = (*data >> (8 * data[1])) & 255;
+                               break;
+
+                       case 15:
+                               break;
+
+                       default:
+                               comedi_error(dev, " chan spec wrong");
+                               return -EINVAL; // "sorry channel spec wrong "
+                       }       //switch(ui_NoOfChannel)
+               }               // if  (ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               // else if  (ui_Temp==1)
+       }                       // if  (ui_Temp==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2016_ConfigWatchdog                          |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Watchdog                                |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure |
+|                     comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       if (data[0] == 0) {
+               //Disable the watchdog
+               outw(0x0,
+                       devpriv->i_IobaseAddon +
+                       APCI2016_WATCHDOG_ENABLEDISABLE);
+               //Loading the Reload value
+               outw(data[1],
+                       devpriv->i_IobaseAddon +
+                       APCI2016_WATCHDOG_RELOAD_VALUE);
+               data[1] = data[1] >> 16;
+               outw(data[1],
+                       devpriv->i_IobaseAddon +
+                       APCI2016_WATCHDOG_RELOAD_VALUE + 2);
+       } else {
+               printk("\nThe input parameters are wrong\n");
+       }
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Start / Stop The Watchdog                              |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure |
+|                     comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       switch (data[0]) {
+       case 0:         //stop the watchdog
+               outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);    //disable the watchdog
+               break;
+       case 1:         //start the watchdog
+               outw(0x0001,
+                       devpriv->i_IobaseAddon +
+                       APCI2016_WATCHDOG_ENABLEDISABLE);
+               break;
+       case 2:         //Software trigger
+               outw(0x0201,
+                       devpriv->i_IobaseAddon +
+                       APCI2016_WATCHDOG_ENABLEDISABLE);
+               break;
+       default:
+               printk("\nSpecified functionality does not exist\n");
+               return -EINVAL;
+       }                       // switch(data[0])
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2016_ReadWatchdog                            |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read The Watchdog                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure |
+|                     comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2016_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       udelay(5);
+       data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2016_Reset(comedi_device *dev)               |                                                       |
++----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2016_Reset(comedi_device * dev)
+{
+       outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);       // Resets the digital output channels
+       outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
+       outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE);
+       outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2);
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
new file mode 100644 (file)
index 0000000..64d6212
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*********      Definitions for APCI-2016 card  *****/
+
+#define APCI2016_BOARD_VENDOR_ID 0x15B8
+#define APCI2016_ADDRESS_RANGE   8
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI2016_DIGITAL_OP                    0x04
+#define APCI2016_DIGITAL_OP_RW                         4
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE                            1
+#define ADDIDATA_DISABLE                           0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_WATCHDOG                          2
+#define APCI2016_DIGITAL_OP_WATCHDOG               0
+#define APCI2016_WATCHDOG_ENABLEDISABLE            12
+#define APCI2016_WATCHDOG_RELOAD_VALUE             4
+#define APCI2016_WATCHDOG_STATUS                   16
+
+// Hardware Layer  functions for Apci2016
+
+//DO
+int i_APCI2016_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+int i_APCI2016_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+int i_APCI2016_BitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// TIMER
+// timer value is passed as u seconds
+
+int i_APCI2016_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+int i_APCI2016_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+int i_APCI2016_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// Interrupt functions.....
+
+// VOID v_APCI2016_Interrupt(int irq, void *d) ;
+
+ //VOID v_APCI2016_Interrupt(int irq, void *d);
+// RESET
+INT i_APCI2016_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
new file mode 100644 (file)
index 0000000..117193c
--- /dev/null
@@ -0,0 +1,579 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-2032       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci2032.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-2032                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+
+#include "hwdrv_apci2032.h"
+UINT ui_InterruptData, ui_Type;
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2032_ConfigDigitalOutput                     |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Digital Output Subdevice.               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[1]            : 1 Enable  VCC  Interrupt  |
+|                                                                                 0 Disable VCC  Interrupt  |
+|                                        data[2]            : 1 Enable  CC  Interrupt   |
+|                                                                                 0 Disable CC  Interrupt   |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command = 0;
+       devpriv->tsk_Current = current;
+
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Not a valid Data !!! ,Data should be 1 or 0\n");
+               return -EINVAL;
+       }                       //if  ( (data[0]!=0) && (data[0]!=1) )
+       if (data[0]) {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+       }                       // if  (data[0])
+       else {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+       }                       //else if  (data[0])
+
+       if (data[1] == ADDIDATA_ENABLE) {
+               ul_Command = ul_Command | 0x1;
+       }                       //if  (data[1] == ADDIDATA_ENABLE)
+       else {
+               ul_Command = ul_Command & 0xFFFFFFFE;
+       }                       //elseif  (data[1] == ADDIDATA_ENABLE)
+       if (data[2] == ADDIDATA_ENABLE) {
+               ul_Command = ul_Command | 0x2;
+       }                       //if  (data[2] == ADDIDATA_ENABLE)
+       else {
+               ul_Command = ul_Command & 0xFFFFFFFD;
+       }                       //elseif  (data[2] == ADDIDATA_ENABLE)
+       outl(ul_Command, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
+       ui_InterruptData = inl(devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2032_WriteDigitalOutput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To Write      |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp, ui_Temp1;
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+       if (devpriv->b_OutputMemoryStatus) {
+               ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
+
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       else {
+               ui_Temp = 0;
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP);
+               }               //if(data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               switch (ui_NoOfChannel) {
+
+                               case 2:
+                                       data[0] =
+                                               (data[0] << (2 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 4:
+                                       data[0] =
+                                               (data[0] << (4 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 8:
+                                       data[0] =
+                                               (data[0] << (8 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 16:
+                                       data[0] =
+                                               (data[0] << (16 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 31:
+                                       data[0] = data[0] | ui_Temp;
+                                       break;
+
+                               default:
+                                       comedi_error(dev, " chan spec wrong");
+                                       return -EINVAL; // "sorry channel spec wrong "
+
+                               }       //switch(ui_NoOfChannels)
+
+                               outl(data[0],
+                                       devpriv->iobase + APCI2032_DIGITAL_OP);
+                       }       // if(data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       //else if(data[1]==1)
+               }               //elseif(data[1]==0)
+       }                       //if(data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] =
+                                       (data[0] << ui_NoOfChannel) ^
+                                       0xffffffff;
+                               data[0] = data[0] & ui_Temp;
+                               outl(data[0],
+                                       devpriv->iobase + APCI2032_DIGITAL_OP);
+                       }       //if(data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       switch (ui_NoOfChannel) {
+
+                                       case 2:
+                                               data[0] = ~data[0] & 0x3;
+                                               ui_Temp1 = 3;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 2 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (2 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+
+                                       case 4:
+                                               data[0] = ~data[0] & 0xf;
+                                               ui_Temp1 = 15;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 4 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (4 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+
+                                       case 8:
+                                               data[0] = ~data[0] & 0xff;
+                                               ui_Temp1 = 255;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 8 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (8 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+
+                                       case 16:
+                                               data[0] = ~data[0] & 0xffff;
+                                               ui_Temp1 = 65535;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 16 *
+                                                       data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (16 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffffffff) & ui_Temp;
+                                               break;
+
+                                       case 31:
+                                               break;
+                                       default:
+                                               comedi_error(dev,
+                                                       " chan spec wrong");
+                                               return -EINVAL; // "sorry channel spec wrong "
+
+                                       }       //switch(ui_NoOfChannels)
+
+                                       outl(data[0],
+                                               devpriv->iobase +
+                                               APCI2032_DIGITAL_OP);
+                               }       // if(data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       //else if(data[1]==1)
+                       }       //elseif(data[1]==0)
+               }               //if(data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               //if else data[3]==1)
+       }                       //if else data[3]==0)
+       return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2032_ReadDigitalOutput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel or port           |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp;
+       UINT ui_NoOfChannel;
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       ui_Temp = data[0];
+       *data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       //if  (ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       switch (ui_NoOfChannel) {
+
+                       case 2:
+                               *data = (*data >> (2 * data[1])) & 3;
+                               break;
+
+                       case 4:
+                               *data = (*data >> (4 * data[1])) & 15;
+                               break;
+
+                       case 8:
+                               *data = (*data >> (8 * data[1])) & 255;
+                               break;
+
+                       case 16:
+                               *data = (*data >> (16 * data[1])) & 65535;
+                               break;
+
+                       case 31:
+                               break;
+
+                       default:
+                               comedi_error(dev, " chan spec wrong");
+                               return -EINVAL; // "sorry channel spec wrong "
+
+                       }       //switch(ui_NoOfChannels)
+               }               //if  (ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               //elseif  (ui_Temp==1)
+       }
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : INT i_APCI2032_ConfigWatchdog(comedi_device
+                   *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)|
+|                                                                                   |
++----------------------------------------------------------------------------+
+| Task              : Configures The Watchdog                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status                                                                                                             |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       if (data[0] == 0) {
+               //Disable the watchdog
+               outl(0x0,
+                       devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+                       APCI2032_TCW_PROG);
+               //Loading the Reload value
+               outl(data[1],
+                       devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+                       APCI2032_TCW_RELOAD_VALUE);
+       } else {
+               printk("\nThe input parameters are wrong\n");
+               return -EINVAL;
+       }
+
+       return insn->n;
+}
+
+ /*
+    +----------------------------------------------------------------------------+
+    | Function   Name   : int i_APCI2032_StartStopWriteWatchdog                  |
+    |                           (comedi_device *dev,comedi_subdevice *s,
+    comedi_insn *insn,lsampl_t *data);                      |
+    +----------------------------------------------------------------------------+
+    | Task              : Start / Stop The Watchdog                              |
+    +----------------------------------------------------------------------------+
+    | Input Parameters  : comedi_device *dev      : Driver handle                |
+    |                     comedi_subdevice *s,   :pointer to subdevice structure
+    comedi_insn *insn      :pointer to insn structure      |
+    |                     lsampl_t *data          : Data Pointer to read status  |
+    +----------------------------------------------------------------------------+
+    | Output Parameters :       --                                                                                                       |
+    +----------------------------------------------------------------------------+
+    | Return Value      : TRUE  : No error occur                                 |
+    |                       : FALSE : Error occur. Return the error          |
+    |                                                                            |
+    +----------------------------------------------------------------------------+
+  */
+
+int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       switch (data[0]) {
+       case 0:         //stop the watchdog
+               outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);  //disable the watchdog
+               break;
+       case 1:         //start the watchdog
+               outl(0x0001,
+                       devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+                       APCI2032_TCW_PROG);
+               break;
+       case 2:         //Software trigger
+               outl(0x0201,
+                       devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+                       APCI2032_TCW_PROG);
+               break;
+       default:
+               printk("\nSpecified functionality does not exist\n");
+               return -EINVAL;
+       }
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2032_ReadWatchdog                            |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data);                                        |
++----------------------------------------------------------------------------+
+| Task              : Read The Watchdog                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2032_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       data[0] =
+               inl(devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+               APCI2032_TCW_TRIG_STATUS) & 0x1;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   :  void v_APCI2032_Interrupt                                                |
+|                                        (int irq , void *d)      |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+void v_APCI2032_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+       unsigned int ui_DO;
+
+       ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1;   //Check if VCC OR CC interrupt has occured.
+
+       if (ui_DO == 0) {
+               printk("\nInterrupt from unKnown source\n");
+       }                       // if(ui_DO==0)
+       if (ui_DO) {
+               // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
+               ui_Type =
+                       inl(devpriv->iobase +
+                       APCI2032_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
+               outl(0x0,
+                       devpriv->iobase + APCI2032_DIGITAL_OP +
+                       APCI2032_DIGITAL_OP_INTERRUPT);
+               if (ui_Type == 1) {
+                       //Sends signal to user space
+                       send_sig(SIGIO, devpriv->tsk_Current, 0);
+               }               // if (ui_Type==1)
+               else {
+                       if (ui_Type == 2) {
+                               // Sends signal to user space
+                               send_sig(SIGIO, devpriv->tsk_Current, 0);
+                       }       //if (ui_Type==2)
+               }               //else if (ui_Type==1)
+       }                       //if(ui_DO)
+
+       return;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   :  int i_APCI2032_ReadInterruptStatus                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              :Reads the interrupt status register                     |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                        |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2032_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       *data = ui_Type;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   :  int i_APCI2032_Reset(comedi_device *dev)                             |
+|                                                                                       |
++----------------------------------------------------------------------------+
+| Task              :Resets the registers of the card                        |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                        |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2032_Reset(comedi_device * dev)
+{
+       devpriv->b_DigitalOutputRegister = 0;
+       ui_Type = 0;
+       outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP);       //Resets the output channels
+       outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);     //Disables the interrupt.
+       outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);  //disable the watchdog
+       outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE);  //reload=0
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
new file mode 100644 (file)
index 0000000..26d21bd
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*********      Definitions for APCI-2032 card  *****/
+
+// Card Specific information
+#define APCI2032_BOARD_VENDOR_ID                 0x15B8
+#define APCI2032_ADDRESS_RANGE                   63
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI2032_DIGITAL_OP                    0
+#define APCI2032_DIGITAL_OP_RW                         0
+#define APCI2032_DIGITAL_OP_INTERRUPT           4
+#define APCI2032_DIGITAL_OP_IRQ                 12
+
+//Digital Output Interrupt Status
+#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS    8
+
+//Digital Output Interrupt Enable Disable.
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE                            1
+#define ADDIDATA_DISABLE                           0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_WATCHDOG                          2
+#define APCI2032_DIGITAL_OP_WATCHDOG               16
+#define APCI2032_TCW_RELOAD_VALUE                  4
+#define APCI2032_TCW_TIMEBASE                      8
+#define APCI2032_TCW_PROG                          12
+#define APCI2032_TCW_TRIG_STATUS                   16
+#define APCI2032_TCW_IRQ                           20
+
+// Hardware Layer  functions for Apci2032
+
+//DO
+int i_APCI2032_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI2032_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI2032_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI2032_ReadInterruptStatus(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// TIMER
+// timer value is passed as u seconds
+INT i_APCI2032_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI2032_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI2032_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// Interrupt functions.....
+
+void v_APCI2032_Interrupt(int irq, void *d);
+
+//Reset functions
+int i_APCI2032_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
new file mode 100644 (file)
index 0000000..9e81f43
--- /dev/null
@@ -0,0 +1,549 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-2200       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci2200.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-2200                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci2200.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_Read1DigitalInput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the digital input                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure     |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_TmpValue = 0;
+       UINT ui_Channel;
+       ui_Channel = CR_CHAN(insn->chanspec);
+       if (ui_Channel >= 0 && ui_Channel <= 7) {
+               ui_TmpValue = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+               *data = (ui_TmpValue >> ui_Channel) & 0x1;
+       }                       //if(ui_Channel >= 0 && ui_Channel <=7)
+       else {
+               printk("\nThe specified channel does not exist\n");
+               return -EINVAL; // "sorry channel spec wrong "
+       }                       //else if(ui_Channel >= 0 && ui_Channel <=7)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                     comedi_insn *insn,lsampl_t *data)                      |
++----------------------------------------------------------------------------+
+| Task              : Return the status of the Requested digital inputs      |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                      comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure     |
+|                      lsampl_t *data         : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ui_PortValue = data[0];
+       UINT ui_Mask = 0;
+       UINT ui_NoOfChannels;
+
+       ui_NoOfChannels = CR_CHAN(insn->chanspec);
+
+       *data = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+       switch (ui_NoOfChannels) {
+       case 2:
+               ui_Mask = 3;
+               *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+               break;
+       case 4:
+               ui_Mask = 15;
+               *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+               break;
+       case 7:
+               break;
+
+       default:
+               printk("\nWrong parameters\n");
+               return -EINVAL; // "sorry channel spec wrong "
+               break;
+       }                       //switch(ui_NoOfChannels)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_ConfigDigitalOutput (comedi_device *dev,
+                    comedi_subdevice *s comedi_insn *insn,lsampl_t *data)    |
+|                                                                                   |
++----------------------------------------------------------------------------+
+| Task              : Configures The Digital Output Subdevice.               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     lsampl_t *data         : Data Pointer contains         |
+|                                          configuration parameters as below |
+|                      comedi_subdevice *s,   :pointer to subdevice structure
+                       comedi_insn *insn      :pointer to insn structure                                                           |
+|                                        data[0]  :1:Memory on                          |
+|                                                  0:Memory off                         |
+|                                                                                                           |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       devpriv->b_OutputMemoryStatus = data[0];
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                     lsampl_t *data)                                         |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                    lsampl_t *data           : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp, ui_Temp1;
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+       if (devpriv->b_OutputMemoryStatus) {
+               ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       else {
+               ui_Temp = 0;
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP);
+               }               //if(data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               switch (ui_NoOfChannel) {
+
+                               case 2:
+                                       data[0] =
+                                               (data[0] << (2 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 4:
+                                       data[0] =
+                                               (data[0] << (4 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+
+                               case 8:
+                                       data[0] =
+                                               (data[0] << (8 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 15:
+                                       data[0] = data[0] | ui_Temp;
+                                       break;
+                               default:
+                                       comedi_error(dev, " chan spec wrong");
+                                       return -EINVAL; // "sorry channel spec wrong "
+
+                               }       //switch(ui_NoOfChannels)
+
+                               outw(data[0],
+                                       devpriv->iobase + APCI2200_DIGITAL_OP);
+                       }       // if(data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       //else if(data[1]==1)
+               }               //elseif(data[1]==0)
+       }                       //if(data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
+                               data[0] = data[0] & ui_Temp;
+                               outw(data[0],
+                                       devpriv->iobase + APCI2200_DIGITAL_OP);
+                       }       //if(data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       switch (ui_NoOfChannel) {
+
+                                       case 2:
+                                               data[0] = ~data[0] & 0x3;
+                                               ui_Temp1 = 3;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 2 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (2 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffff) & ui_Temp;
+                                               break;
+
+                                       case 4:
+                                               data[0] = ~data[0] & 0xf;
+                                               ui_Temp1 = 15;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 4 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (4 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffff) & ui_Temp;
+                                               break;
+
+                                       case 8:
+                                               data[0] = ~data[0] & 0xff;
+                                               ui_Temp1 = 255;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 8 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (8 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xffff) & ui_Temp;
+                                               break;
+                                       case 15:
+                                               break;
+
+                                       default:
+                                               comedi_error(dev,
+                                                       " chan spec wrong");
+                                               return -EINVAL; // "sorry channel spec wrong "
+
+                                       }       //switch(ui_NoOfChannels)
+
+                                       outw(data[0],
+                                               devpriv->iobase +
+                                               APCI2200_DIGITAL_OP);
+                               }       // if(data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       //else if(data[1]==1)
+                       }       //elseif(data[1]==0)
+               }               //if(data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               //if else data[3]==1)
+       }                       //if else data[3]==0)
+       return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data)                                         |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel or port           |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ui_Temp;
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+       ui_Temp = data[0];
+       *data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       //if(ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       switch (ui_NoOfChannel) {
+
+                       case 2:
+                               *data = (*data >> (2 * data[1])) & 3;
+                               break;
+
+                       case 4:
+                               *data = (*data >> (4 * data[1])) & 15;
+                               break;
+
+                       case 8:
+                               *data = (*data >> (8 * data[1])) & 255;
+                               break;
+
+                       case 15:
+                               break;
+
+                       default:
+                               comedi_error(dev, " chan spec wrong");
+                               return -EINVAL; // "sorry channel spec wrong "
+
+                       }       //switch(ui_NoOfChannels)
+               }               //if(ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               //elseif(ui_Temp==1)
+       }                       //elseif(ui_Temp==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_ConfigWatchdog(comedi_device *dev,
+                      comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)  |
+|                                                                                   |
++----------------------------------------------------------------------------+
+| Task              : Configures The Watchdog                                |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status                                                                                                             |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       if (data[0] == 0) {
+               //Disable the watchdog
+               outw(0x0,
+                       devpriv->iobase + APCI2200_WATCHDOG +
+                       APCI2200_WATCHDOG_ENABLEDISABLE);
+               //Loading the Reload value
+               outw(data[1],
+                       devpriv->iobase + APCI2200_WATCHDOG +
+                       APCI2200_WATCHDOG_RELOAD_VALUE);
+               data[1] = data[1] >> 16;
+               outw(data[1],
+                       devpriv->iobase + APCI2200_WATCHDOG +
+                       APCI2200_WATCHDOG_RELOAD_VALUE + 2);
+       }                       //if(data[0]==0)
+       else {
+               printk("\nThe input parameters are wrong\n");
+               return -EINVAL;
+       }                       //elseif(data[0]==0)
+
+       return insn->n;
+}
+
+ /*
+    +----------------------------------------------------------------------------+
+    | Function   Name   : int i_APCI2200_StartStopWriteWatchdog                  |
+    |                           (comedi_device *dev,comedi_subdevice *s,
+    comedi_insn *insn,lsampl_t *data);                      |
+    +----------------------------------------------------------------------------+
+    | Task              : Start / Stop The Watchdog                              |
+    +----------------------------------------------------------------------------+
+    | Input Parameters  : comedi_device *dev      : Driver handle                |
+    |                     comedi_subdevice *s,   :pointer to subdevice structure
+    comedi_insn *insn      :pointer to insn structure      |
+    |                     lsampl_t *data          : Data Pointer to read status  |
+    +----------------------------------------------------------------------------+
+    | Output Parameters :       --                                                                                                       |
+    +----------------------------------------------------------------------------+
+    | Return Value      : TRUE  : No error occur                                 |
+    |                       : FALSE : Error occur. Return the error          |
+    |                                                                            |
+    +----------------------------------------------------------------------------+
+  */
+
+int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       switch (data[0]) {
+       case 0:         //stop the watchdog
+               outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);       //disable the watchdog
+               break;
+       case 1:         //start the watchdog
+               outw(0x0001,
+                       devpriv->iobase + APCI2200_WATCHDOG +
+                       APCI2200_WATCHDOG_ENABLEDISABLE);
+               break;
+       case 2:         //Software trigger
+               outw(0x0201,
+                       devpriv->iobase + APCI2200_WATCHDOG +
+                       APCI2200_WATCHDOG_ENABLEDISABLE);
+               break;
+       default:
+               printk("\nSpecified functionality does not exist\n");
+               return -EINVAL;
+       }                       // switch(data[0])
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_ReadWatchdog                            |
+|                      (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,
+                    lsampl_t *data);                                        |
++----------------------------------------------------------------------------+
+| Task              : Read The Watchdog                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  :   comedi_device *dev      : Driver handle              |
+|                     comedi_subdevice *s,   :pointer to subdevice structure
+                      comedi_insn *insn      :pointer to insn structure      |
+|                     lsampl_t *data          : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2200_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       data[0] =
+               inw(devpriv->iobase + APCI2200_WATCHDOG +
+               APCI2200_WATCHDOG_STATUS) & 0x1;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI2200_Reset(comedi_device *dev)               |                                                                                                          |
++----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_Reset(comedi_device * dev)
+{
+       outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);       //RESETS THE DIGITAL OUTPUTS
+       outw(0x0,
+               devpriv->iobase + APCI2200_WATCHDOG +
+               APCI2200_WATCHDOG_ENABLEDISABLE);
+       outw(0x0,
+               devpriv->iobase + APCI2200_WATCHDOG +
+               APCI2200_WATCHDOG_RELOAD_VALUE);
+       outw(0x0,
+               devpriv->iobase + APCI2200_WATCHDOG +
+               APCI2200_WATCHDOG_RELOAD_VALUE + 2);
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
new file mode 100644 (file)
index 0000000..c62250b
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*********      Definitions for APCI-2200 card  *****/
+
+// Card Specific information
+#define APCI2200_BOARD_VENDOR_ID                 0x15b8
+#define APCI2200_ADDRESS_RANGE                   64
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI2200_DIGITAL_OP                    4
+#define APCI2200_DIGITAL_IP                     0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define APCI2200_WATCHDOG                          0x08
+#define APCI2200_WATCHDOG_ENABLEDISABLE            12
+#define APCI2200_WATCHDOG_RELOAD_VALUE             4
+#define APCI2200_WATCHDOG_STATUS                   16
+
+// Hardware Layer  functions for Apci2200
+
+//Digital Input
+INT i_APCI2200_ReadMoreDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI2200_Read1DigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//Digital Output
+int i_APCI2200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI2200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI2200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// TIMER
+int i_APCI2200_ConfigWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI2200_StartStopWriteWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI2200_ReadWatchdog(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//reset
+INT i_APCI2200_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
new file mode 100644 (file)
index 0000000..32b7f24
--- /dev/null
@@ -0,0 +1,2688 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : APCI-3120       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci3120.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-----------------------------------------------------------------------+
+  | Description :APCI3120 Module.  Hardware abstraction Layer for APCI3120|
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |                  |                                                |
+  |          |           |                                               |
+  +----------+-----------+------------------------------------------------+
+*/
+
+#include "hwdrv_apci3120.h"
+static UINT ui_Temp = 0;
+
+// FUNCTION DEFINITIONS
+
+/*
++----------------------------------------------------------------------------+
+|                           ANALOG INPUT SUBDEVICE                              |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev,|
+|  comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                                        |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Calls card specific function                                          |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                    |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT i;
+
+       if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
+               return -1;
+
+       // Check for Conversion time to be added ??
+       devpriv->ui_EocEosConversionTime = data[2];
+
+       if (data[0] == APCI3120_EOS_MODE) {
+
+               //Test the number of the channel
+               for (i = 0; i < data[3]; i++) {
+
+                       if (CR_CHAN(data[4 + i]) >= this_board->i_NbrAiChannel) {
+                               printk("bad channel list\n");
+                               return -2;
+                       }
+               }
+
+               devpriv->b_InterruptMode = APCI3120_EOS_MODE;
+
+               if (data[1]) {
+                       devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+               } else
+                       devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+               // Copy channel list and Range List to devpriv
+
+               devpriv->ui_AiNbrofChannels = data[3];
+               for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) {
+                       devpriv->ui_AiChannelList[i] = data[4 + i];
+               }
+
+       } else                  // EOC
+       {
+               devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+               if (data[1]) {
+                       devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+               } else {
+                       devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+               }
+       }
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnReadAnalogInput(comedi_device *dev,  |
+|                      comedi_subdevice *s,comedi_insn *insn, lsampl_t *data)   |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :  card specific function                                                           |
+|                              Reads analog input in synchronous mode               |
+|                        EOC and EOS is selected as per configured              |
+|                     if no conversion time is set uses default conversion   |
+|                        time 10 microsec.                                                                      |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       USHORT us_ConvertTiming, us_TmpValue, i;
+       BYTE b_Tmp;
+
+       // fix convertion time to 10 us
+       if (!devpriv->ui_EocEosConversionTime) {
+               printk("No timer0 Value using 10 us\n");
+               us_ConvertTiming = 10;
+       } else
+               us_ConvertTiming = (USHORT) (devpriv->ui_EocEosConversionTime / 1000);  // nano to useconds
+
+       // this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]);
+
+       // Clear software registers
+       devpriv->b_TimerSelectMode = 0;
+       devpriv->b_ModeSelectRegister = 0;
+       devpriv->us_OutputRegister = 0;
+//        devpriv->b_DigitalOutputRegister=0;
+
+       if (insn->unused[0] == 222)     // second insn read
+       {
+
+               for (i = 0; i < insn->n; i++) {
+                       data[i] = devpriv->ui_AiReadData[i];
+               }
+
+       } else {
+               devpriv->tsk_Current = current; // Save the current process task structure
+               //Testing if board have the new Quartz and calculate the time value
+               //to set in the timer
+
+               us_TmpValue =
+                       (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+               //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+               if ((us_TmpValue & 0x00B0) == 0x00B0
+                       || !strcmp(this_board->pc_DriverName, "apci3001")) {
+                       us_ConvertTiming = (us_ConvertTiming * 2) - 2;
+               } else {
+                       us_ConvertTiming =
+                               ((us_ConvertTiming * 12926) / 10000) - 1;
+               }
+
+               us_TmpValue = (USHORT) devpriv->b_InterruptMode;
+
+               switch (us_TmpValue) {
+
+               case APCI3120_EOC_MODE:
+
+                       // Testing the interrupt flag and set the EOC bit
+                       // Clears the FIFO
+                       inw(devpriv->iobase + APCI3120_RESET_FIFO);
+
+                       // Initialize the sequence array
+
+                       //if (!i_APCI3120_SetupChannelList(dev,s,1,chanlist,0))  return -EINVAL;
+
+                       if (!i_APCI3120_SetupChannelList(dev, s, 1,
+                                       &insn->chanspec, 0))
+                               return -EINVAL;
+
+                       //Initialize Timer 0 mode 4
+                       devpriv->b_TimerSelectMode =
+                               (devpriv->
+                               b_TimerSelectMode & 0xFC) |
+                               APCI3120_TIMER_0_MODE_4;
+                       outb(devpriv->b_TimerSelectMode,
+                               devpriv->iobase + APCI3120_TIMER_CRT1);
+
+                       // Reset the scan bit and Disables the  EOS, DMA, EOC interrupt
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister & APCI3120_DISABLE_SCAN;
+
+                       if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+
+                               //Disables the EOS,DMA and enables the EOC interrupt
+                               devpriv->b_ModeSelectRegister =
+                                       (devpriv->
+                                       b_ModeSelectRegister &
+                                       APCI3120_DISABLE_EOS_INT) |
+                                       APCI3120_ENABLE_EOC_INT;
+                               inw(devpriv->iobase);
+
+                       } else {
+                               devpriv->b_ModeSelectRegister =
+                                       devpriv->
+                                       b_ModeSelectRegister &
+                                       APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
+                       }
+
+                       outb(devpriv->b_ModeSelectRegister,
+                               devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+                       // Sets gate 0
+                       devpriv->us_OutputRegister =
+                               (devpriv->
+                               us_OutputRegister & APCI3120_CLEAR_PA_PR) |
+                               APCI3120_ENABLE_TIMER0;
+                       outw(devpriv->us_OutputRegister,
+                               devpriv->iobase + APCI3120_WR_ADDRESS);
+
+                       // Select Timer 0
+                       b_Tmp = ((devpriv->
+                                       b_DigitalOutputRegister) & 0xF0) |
+                               APCI3120_SELECT_TIMER_0_WORD;
+                       outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+                       //Set the convertion time
+                       outw(us_ConvertTiming,
+                               devpriv->iobase + APCI3120_TIMER_VALUE);
+
+                       us_TmpValue =
+                               (USHORT) inw(dev->iobase + APCI3120_RD_STATUS);
+
+                       if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
+
+                               do {
+                                       // Waiting for the end of conversion
+                                       us_TmpValue =
+                                               inw(devpriv->iobase +
+                                               APCI3120_RD_STATUS);
+                               } while ((us_TmpValue & APCI3120_EOC) ==
+                                       APCI3120_EOC);
+
+                               //Read the result in FIFO  and put it in insn data pointer
+                               us_TmpValue = inw(devpriv->iobase + 0);
+                               *data = us_TmpValue;
+
+                               inw(devpriv->iobase + APCI3120_RESET_FIFO);
+                       }
+
+                       break;
+
+               case APCI3120_EOS_MODE:
+
+                       inw(devpriv->iobase);
+                       // Clears the FIFO
+                       inw(devpriv->iobase + APCI3120_RESET_FIFO);
+                       // clear PA PR  and disable timer 0
+
+                       devpriv->us_OutputRegister =
+                               (devpriv->
+                               us_OutputRegister & APCI3120_CLEAR_PA_PR) |
+                               APCI3120_DISABLE_TIMER0;
+
+                       outw(devpriv->us_OutputRegister,
+                               devpriv->iobase + APCI3120_WR_ADDRESS);
+
+                       if (!i_APCI3120_SetupChannelList(dev, s,
+                                       devpriv->ui_AiNbrofChannels,
+                                       devpriv->ui_AiChannelList, 0))
+                               return -EINVAL;
+
+                       //Initialize Timer 0 mode 2
+                       devpriv->b_TimerSelectMode =
+                               (devpriv->
+                               b_TimerSelectMode & 0xFC) |
+                               APCI3120_TIMER_0_MODE_2;
+                       outb(devpriv->b_TimerSelectMode,
+                               devpriv->iobase + APCI3120_TIMER_CRT1);
+
+                       //Select Timer 0
+                       b_Tmp = ((devpriv->
+                                       b_DigitalOutputRegister) & 0xF0) |
+                               APCI3120_SELECT_TIMER_0_WORD;
+                       outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+                       //Set the convertion time
+                       outw(us_ConvertTiming,
+                               devpriv->iobase + APCI3120_TIMER_VALUE);
+
+                       //Set the scan bit
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister | APCI3120_ENABLE_SCAN;
+                       outb(devpriv->b_ModeSelectRegister,
+                               devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+                       //If Interrupt function is loaded
+                       if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+                               //Disables the EOC,DMA and enables the EOS interrupt
+                               devpriv->b_ModeSelectRegister =
+                                       (devpriv->
+                                       b_ModeSelectRegister &
+                                       APCI3120_DISABLE_EOC_INT) |
+                                       APCI3120_ENABLE_EOS_INT;
+                               inw(devpriv->iobase);
+
+                       } else
+                               devpriv->b_ModeSelectRegister =
+                                       devpriv->
+                                       b_ModeSelectRegister &
+                                       APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
+
+                       outb(devpriv->b_ModeSelectRegister,
+                               devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+                       inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+                       //Sets gate 0
+
+                       devpriv->us_OutputRegister =
+                               devpriv->
+                               us_OutputRegister | APCI3120_ENABLE_TIMER0;
+                       outw(devpriv->us_OutputRegister,
+                               devpriv->iobase + APCI3120_WR_ADDRESS);
+
+                       //Start conversion
+                       outw(0, devpriv->iobase + APCI3120_START_CONVERSION);
+
+                       //Waiting of end of convertion if interrupt is not installed
+                       if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
+                               //Waiting the end of convertion
+                               do {
+                                       us_TmpValue =
+                                               inw(devpriv->iobase +
+                                               APCI3120_RD_STATUS);
+                               }
+                               while ((us_TmpValue & APCI3120_EOS) !=
+                                       APCI3120_EOS);
+
+                               for (i = 0; i < devpriv->ui_AiNbrofChannels;
+                                       i++) {
+                                       //Read the result in FIFO and write them in shared memory
+                                       us_TmpValue = inw(devpriv->iobase);
+                                       data[i] = (UINT) us_TmpValue;
+                               }
+
+                               devpriv->b_InterruptMode = APCI3120_EOC_MODE;   // Restore defaults.
+                       }
+                       break;
+
+               default:
+                       printk("inputs wrong\n");
+
+               }
+               devpriv->ui_EocEosConversionTime = 0;   // re initializing the variable;
+       }
+
+       return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_StopCyclicAcquisition(comedi_device *dev,|
+|                                                                                           comedi_subdevice *s)|
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Stops Cyclic acquisition                                                      |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :0                                                                      |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+{
+       // Disable A2P Fifo write and AMWEN signal
+       outw(0, devpriv->i_IobaseAddon + 4);
+
+       //Disable Bus Master ADD ON
+       outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+       outw(0, devpriv->i_IobaseAddon + 2);
+       outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+       outw(0, devpriv->i_IobaseAddon + 2);
+
+       //Disable BUS Master PCI
+       outl(0, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+
+       //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR)&(~AINT_WRITE_COMPL), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);    // stop amcc irqs
+       //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR)&(~EN_A2P_TRANSFERS), devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR); // stop DMA
+
+       //Disable ext trigger
+       i_APCI3120_ExttrigDisable(dev);
+
+       devpriv->us_OutputRegister = 0;
+       //stop  counters
+       outw(devpriv->
+               us_OutputRegister & APCI3120_DISABLE_TIMER0 &
+               APCI3120_DISABLE_TIMER1, dev->iobase + APCI3120_WR_ADDRESS);
+
+       outw(APCI3120_DISABLE_ALL_TIMER, dev->iobase + APCI3120_WR_ADDRESS);
+
+       //DISABLE_ALL_INTERRUPT
+       outb(APCI3120_DISABLE_ALL_INTERRUPT,
+               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+       //Flush FIFO
+       inb(dev->iobase + APCI3120_RESET_FIFO);
+       inw(dev->iobase + APCI3120_RD_STATUS);
+       devpriv->ui_AiActualScan = 0;
+       devpriv->ui_AiActualScanPosition = 0;
+       s->async->cur_chan = 0;
+       devpriv->ui_AiBufferPtr = 0;
+       devpriv->b_AiContinuous = 0;
+       devpriv->ui_DmaActualBuffer = 0;
+
+       devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+       devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+       devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+       i_APCI3120_Reset(dev);
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_CommandTestAnalogInput(comedi_device *dev|
+|                      ,comedi_subdevice *s,comedi_cmd *cmd)                                    |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Test validity for a command for cyclic anlog input     |
+|                       acquisition                                                                     |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_cmd *cmd                                                           |
++----------------------------------------------------------------------------+
+| Return Value      :0                                                                      |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_cmd * cmd)
+{
+       int err = 0;
+       int tmp;                // divisor1,divisor2;
+
+       // step 1: make sure trigger sources are trivially valid
+
+       tmp = cmd->start_src;
+       cmd->start_src &= TRIG_NOW | TRIG_EXT;
+       if (!cmd->start_src || tmp != cmd->start_src)
+               err++;
+
+       tmp = cmd->scan_begin_src;
+       cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
+       if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+               err++;
+
+       tmp = cmd->convert_src;
+       cmd->convert_src &= TRIG_TIMER;
+       if (!cmd->convert_src || tmp != cmd->convert_src)
+               err++;
+
+       tmp = cmd->scan_end_src;
+       cmd->scan_end_src &= TRIG_COUNT;
+       if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+               err++;
+
+       tmp = cmd->stop_src;
+       cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+       if (!cmd->stop_src || tmp != cmd->stop_src)
+               err++;
+
+       if (err)
+               return 1;
+
+       //step 2: make sure trigger sources are unique and mutually compatible
+
+       if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
+               err++;
+       }
+
+       if (cmd->scan_begin_src != TRIG_TIMER &&
+               cmd->scan_begin_src != TRIG_FOLLOW)
+               err++;
+
+       if (cmd->convert_src != TRIG_TIMER)
+               err++;
+
+       if (cmd->scan_end_src != TRIG_COUNT) {
+               cmd->scan_end_src = TRIG_COUNT;
+               err++;
+       }
+
+       if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
+               err++;
+
+       if (err)
+               return 2;
+
+       // step 3: make sure arguments are trivially compatible
+
+       if (cmd->start_arg != 0) {
+               cmd->start_arg = 0;
+               err++;
+       }
+
+       if (cmd->scan_begin_src == TRIG_TIMER)  // Test Delay timing
+       {
+               if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) {
+                       cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs;
+                       err++;
+               }
+       }
+
+       if (cmd->convert_src == TRIG_TIMER)     // Test Acquisition timing
+       {
+               if (cmd->scan_begin_src == TRIG_TIMER) {
+                       if ((cmd->convert_arg)
+                               && (cmd->convert_arg <
+                                       this_board->ui_MinAcquisitiontimeNs)) {
+                               cmd->convert_arg =
+                                       this_board->ui_MinAcquisitiontimeNs;
+                               err++;
+                       }
+               } else {
+                       if (cmd->convert_arg <
+                               this_board->ui_MinAcquisitiontimeNs) {
+                               cmd->convert_arg =
+                                       this_board->ui_MinAcquisitiontimeNs;
+                               err++;
+
+                       }
+               }
+       }
+
+       if (!cmd->chanlist_len) {
+               cmd->chanlist_len = 1;
+               err++;
+       }
+       if (cmd->chanlist_len > this_board->i_AiChannelList) {
+               cmd->chanlist_len = this_board->i_AiChannelList;
+               err++;
+       }
+       if (cmd->stop_src == TRIG_COUNT) {
+               if (!cmd->stop_arg) {
+                       cmd->stop_arg = 1;
+                       err++;
+               }
+       } else {                // TRIG_NONE
+               if (cmd->stop_arg != 0) {
+                       cmd->stop_arg = 0;
+                       err++;
+               }
+       }
+
+       if (err)
+               return 3;
+
+       // step 4: fix up any arguments
+
+       if (cmd->convert_src == TRIG_TIMER) {
+
+               if (cmd->scan_begin_src == TRIG_TIMER &&
+                       cmd->scan_begin_arg <
+                       cmd->convert_arg * cmd->scan_end_arg) {
+                       cmd->scan_begin_arg =
+                               cmd->convert_arg * cmd->scan_end_arg;
+                       err++;
+               }
+       }
+
+       if (err)
+               return 4;
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : int i_APCI3120_CommandAnalogInput(comedi_device *dev,  |
+|                                                                                              comedi_subdevice *s) |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Does asynchronous acquisition                          |
+|                     Determines the mode 1 or 2.                                                   |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                                                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
+{
+       comedi_cmd *cmd = &s->async->cmd;
+
+       //loading private structure with cmd structure inputs
+       devpriv->ui_AiFlags = cmd->flags;
+       devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
+       devpriv->ui_AiScanLength = cmd->scan_end_arg;
+       devpriv->pui_AiChannelList = cmd->chanlist;
+
+       //UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data;
+       devpriv->AiData = s->async->prealloc_buf;
+       //UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len;
+       devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
+
+       if (cmd->stop_src == TRIG_COUNT) {
+               devpriv->ui_AiNbrofScans = cmd->stop_arg;
+       } else {
+               devpriv->ui_AiNbrofScans = 0;
+       }
+
+       devpriv->ui_AiTimer0 = 0;       // variables changed to timer0,timer1
+       devpriv->ui_AiTimer1 = 0;
+       if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1))
+               devpriv->b_AiContinuous = 1;    // user want neverending analog acquisition
+       // stopped using cancel
+
+       if (cmd->start_src == TRIG_EXT)
+               devpriv->b_ExttrigEnable = APCI3120_ENABLE;
+       else
+               devpriv->b_ExttrigEnable = APCI3120_DISABLE;
+
+       if (cmd->scan_begin_src == TRIG_FOLLOW) {
+               // mode 1 or 3
+               if (cmd->convert_src == TRIG_TIMER) {
+                       // mode 1
+
+                       devpriv->ui_AiTimer0 = cmd->convert_arg;        // timer constant in nano seconds
+                       //return this_board->i_hwdrv_CommandAnalogInput(1,dev,s);
+                       return i_APCI3120_CyclicAnalogInput(1, dev, s);
+               }
+
+       }
+       if ((cmd->scan_begin_src == TRIG_TIMER)
+               && (cmd->convert_src == TRIG_TIMER)) {
+               // mode 2
+               devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
+               devpriv->ui_AiTimer0 = cmd->convert_arg;        // variable changed timer2 to timer0
+               //return this_board->i_hwdrv_CommandAnalogInput(2,dev,s);
+               return i_APCI3120_CyclicAnalogInput(2, dev, s);
+       }
+       return -1;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :  int i_APCI3120_CyclicAnalogInput(int mode,            |
+|                         comedi_device * dev,comedi_subdevice * s)                     |
++----------------------------------------------------------------------------+
+| Task              : This is used for analog input cyclic acquisition       |
+|                        Performs the command operations.                       |
+|                        If DMA is configured does DMA initialization           |
+|                        otherwise does the acquisition with EOS interrupt.     |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                                                                           |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,
+       comedi_subdevice * s)
+{
+       BYTE b_Tmp;
+       UINT ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
+               0, dmalen1 = 0, ui_TimerValue2 =
+               0, ui_TimerValue0, ui_ConvertTiming;
+       USHORT us_TmpValue;
+
+       //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+       //devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE;
+       //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+       /*******************/
+       /* Resets the FIFO */
+       /*******************/
+       inb(dev->iobase + APCI3120_RESET_FIFO);
+
+       //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+       //inw(dev->iobase+APCI3120_RD_STATUS);
+       //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+       /***************************/
+       /* Acquisition initialized */
+       /***************************/
+       //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+       devpriv->b_AiCyclicAcquisition = APCI3120_ENABLE;
+       //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+       // clear software  registers
+       devpriv->b_TimerSelectMode = 0;
+       devpriv->us_OutputRegister = 0;
+       devpriv->b_ModeSelectRegister = 0;
+       //devpriv->b_DigitalOutputRegister=0;
+
+       //COMMENT JK 07.05.04: Followings calls are in i_APCI3120_StartAnalogInputAcquisition
+
+   /****************************/
+       /* Clear Timer Write TC INT */
+   /****************************/
+       outl(APCI3120_CLEAR_WRITE_TC_INT,
+               devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR);
+
+   /************************************/
+       /* Clears the timer status register */
+   /************************************/
+       //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+       //inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER);
+       inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+       //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+   /**************************/
+       /* Disables All Timer     */
+       /* Sets PR and PA to 0    */
+   /**************************/
+       devpriv->us_OutputRegister = devpriv->us_OutputRegister &
+               APCI3120_DISABLE_TIMER0 &
+               APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR;
+
+       outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
+   /*******************/
+       /* Resets the FIFO */
+   /*******************/
+       //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+       inb(devpriv->iobase + APCI3120_RESET_FIFO);
+       //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+       devpriv->ui_AiActualScan = 0;
+       devpriv->ui_AiActualScanPosition = 0;
+       s->async->cur_chan = 0;
+       devpriv->ui_AiBufferPtr = 0;
+       devpriv->ui_DmaActualBuffer = 0;
+
+       // value for timer2  minus -2 has to be done .....dunno y??
+       ui_TimerValue2 = devpriv->ui_AiNbrofScans - 2;
+       ui_ConvertTiming = devpriv->ui_AiTimer0;
+
+       if (mode == 2)
+               ui_DelayTiming = devpriv->ui_AiTimer1;
+
+   /**********************************/
+       /* Initializes the sequence array */
+   /**********************************/
+       if (!i_APCI3120_SetupChannelList(dev, s, devpriv->ui_AiNbrofChannels,
+                       devpriv->pui_AiChannelList, 0))
+               return -EINVAL;
+
+       us_TmpValue = (USHORT) inw(dev->iobase + APCI3120_RD_STATUS);
+/*** EL241003 : add this section in comment because floats must not be used
+        if((us_TmpValue & 0x00B0)==0x00B0)
+        {
+           f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2);
+               ui_TimerValue0=(UINT)f_ConvertValue;
+               if (mode==2)
+               {
+                       f_DelayValue     = (((float)ui_DelayTiming * 0.00002) - 2);
+                       ui_TimerValue1  =   (UINT) f_DelayValue;
+               }
+        }
+        else
+        {
+               f_ConvertValue=(((float)ui_ConvertTiming * 0.0012926) - 1);
+               ui_TimerValue0=(UINT)f_ConvertValue;
+               if (mode == 2)
+               {
+                    f_DelayValue     = (((float)ui_DelayTiming * 0.000012926) - 1);
+                    ui_TimerValue1  =   (UINT) f_DelayValue;
+               }
+       }
+***********************************************************************************************/
+/*** EL241003 Begin : add this section to replace floats calculation by integer calculations **/
+       //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+       if ((us_TmpValue & 0x00B0) == 0x00B0
+               || !strcmp(this_board->pc_DriverName, "apci3001")) {
+               ui_TimerValue0 = ui_ConvertTiming * 2 - 2000;
+               ui_TimerValue0 = ui_TimerValue0 / 1000;
+
+               if (mode == 2) {
+                       ui_DelayTiming = ui_DelayTiming / 1000;
+                       ui_TimerValue1 = ui_DelayTiming * 2 - 200;
+                       ui_TimerValue1 = ui_TimerValue1 / 100;
+               }
+       } else {
+               ui_ConvertTiming = ui_ConvertTiming / 1000;
+               ui_TimerValue0 = ui_ConvertTiming * 12926 - 10000;
+               ui_TimerValue0 = ui_TimerValue0 / 10000;
+
+               if (mode == 2) {
+                       ui_DelayTiming = ui_DelayTiming / 1000;
+                       ui_TimerValue1 = ui_DelayTiming * 12926 - 1;
+                       ui_TimerValue1 = ui_TimerValue1 / 1000000;
+               }
+       }
+/*** EL241003 End ******************************************************************************/
+
+       if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+               i_APCI3120_ExttrigEnable(dev);  // activate EXT trigger
+       }
+       switch (mode) {
+       case 1:
+               // init timer0 in mode 2
+               devpriv->b_TimerSelectMode =
+                       (devpriv->
+                       b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
+               outb(devpriv->b_TimerSelectMode,
+                       dev->iobase + APCI3120_TIMER_CRT1);
+
+               //Select Timer 0
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_0_WORD;
+               outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+               //Set the convertion time
+               outw(((USHORT) ui_TimerValue0),
+                       dev->iobase + APCI3120_TIMER_VALUE);
+               break;
+
+       case 2:
+               // init timer1 in mode 2
+               devpriv->b_TimerSelectMode =
+                       (devpriv->
+                       b_TimerSelectMode & 0xF3) | APCI3120_TIMER_1_MODE_2;
+               outb(devpriv->b_TimerSelectMode,
+                       dev->iobase + APCI3120_TIMER_CRT1);
+
+               //Select Timer 1
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_1_WORD;
+               outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+               //Set the convertion time
+               outw(((USHORT) ui_TimerValue1),
+                       dev->iobase + APCI3120_TIMER_VALUE);
+
+               // init timer0 in mode 2
+               devpriv->b_TimerSelectMode =
+                       (devpriv->
+                       b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
+               outb(devpriv->b_TimerSelectMode,
+                       dev->iobase + APCI3120_TIMER_CRT1);
+
+               //Select Timer 0
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_0_WORD;
+               outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+
+               //Set the convertion time
+               outw(((USHORT) ui_TimerValue0),
+                       dev->iobase + APCI3120_TIMER_VALUE);
+               break;
+
+       }
+       //   ##########common for all modes#################
+
+       /***********************/
+       /* Clears the SCAN bit */
+       /***********************/
+       //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+       //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN;
+       devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
+               APCI3120_DISABLE_SCAN;
+       //END JK 07.05.04: Comparison between WIN32 and Linux driver
+       outb(devpriv->b_ModeSelectRegister,
+               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+       // If DMA is disabled
+       if (devpriv->us_UseDma == APCI3120_DISABLE) {
+               // disable EOC and enable EOS
+               devpriv->b_InterruptMode = APCI3120_EOS_MODE;
+               devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+
+               devpriv->b_ModeSelectRegister =
+                       (devpriv->
+                       b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) |
+                       APCI3120_ENABLE_EOS_INT;
+               outb(devpriv->b_ModeSelectRegister,
+                       dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+               if (!devpriv->b_AiContinuous) {
+                       // configure Timer2 For counting  EOS
+                       //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0)
+                       devpriv->us_OutputRegister =
+                               devpriv->
+                               us_OutputRegister & APCI3120_DISABLE_TIMER2;
+                       outw(devpriv->us_OutputRegister,
+                               dev->iobase + APCI3120_WR_ADDRESS);
+
+                       // DISABLE TIMER INTERRUPT
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister &
+                               APCI3120_DISABLE_TIMER_INT & 0xEF;
+                       outb(devpriv->b_ModeSelectRegister,
+                               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+                       //(1) Init timer 2 in mode 0 and write timer value
+                       devpriv->b_TimerSelectMode =
+                               (devpriv->
+                               b_TimerSelectMode & 0x0F) |
+                               APCI3120_TIMER_2_MODE_0;
+                       outb(devpriv->b_TimerSelectMode,
+                               dev->iobase + APCI3120_TIMER_CRT1);
+
+                       //Writing LOW WORD
+                       b_Tmp = ((devpriv->
+                                       b_DigitalOutputRegister) & 0xF0) |
+                               APCI3120_SELECT_TIMER_2_LOW_WORD;
+                       outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+                       outw(LOWORD(ui_TimerValue2),
+                               dev->iobase + APCI3120_TIMER_VALUE);
+
+                       //Writing HIGH WORD
+                       b_Tmp = ((devpriv->
+                                       b_DigitalOutputRegister) & 0xF0) |
+                               APCI3120_SELECT_TIMER_2_HIGH_WORD;
+                       outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+                       outw(HIWORD(ui_TimerValue2),
+                               dev->iobase + APCI3120_TIMER_VALUE);
+
+                       //(2) Reset FC_TIMER BIT  Clearing timer status register
+                       inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+                       // enable timer counter and disable watch dog
+                       devpriv->b_ModeSelectRegister =
+                               (devpriv->
+                               b_ModeSelectRegister |
+                               APCI3120_ENABLE_TIMER_COUNTER) &
+                               APCI3120_DISABLE_WATCHDOG;
+                       // select EOS clock input for timer 2
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister |
+                               APCI3120_TIMER2_SELECT_EOS;
+                       // Enable timer2  interrupt
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister |
+                               APCI3120_ENABLE_TIMER_INT;
+                       outb(devpriv->b_ModeSelectRegister,
+                               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+                       devpriv->b_Timer2Mode = APCI3120_COUNTER;
+                       devpriv->b_Timer2Interrupt = APCI3120_ENABLE;
+               }
+       } else {
+               // If DMA Enabled
+               //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+               //inw(dev->iobase+0);// reset EOC bit
+               //END JK 07.05.04: Comparison between WIN32 and Linux driver
+               devpriv->b_InterruptMode = APCI3120_DMA_MODE;
+
+      /************************************/
+               /* Disables the EOC, EOS interrupt  */
+         /************************************/
+               devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
+                       APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT;
+
+               outb(devpriv->b_ModeSelectRegister,
+                       dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+               dmalen0 = devpriv->ui_DmaBufferSize[0];
+               dmalen1 = devpriv->ui_DmaBufferSize[1];
+
+               if (!devpriv->b_AiContinuous) {
+
+                       if (dmalen0 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2)) {      // must we fill full first buffer?
+                               dmalen0 =
+                                       devpriv->ui_AiNbrofScans *
+                                       devpriv->ui_AiScanLength * 2;
+                       } else if (dmalen1 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2 - dmalen0))       // and must we fill full second buffer when first is once filled?
+                               dmalen1 =
+                                       devpriv->ui_AiNbrofScans *
+                                       devpriv->ui_AiScanLength * 2 - dmalen0;
+               }
+
+               if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) {
+                       // don't we want wake up every scan?
+                       if (dmalen0 > (devpriv->ui_AiScanLength * 2)) {
+                               dmalen0 = devpriv->ui_AiScanLength * 2;
+                               if (devpriv->ui_AiScanLength & 1)
+                                       dmalen0 += 2;
+                       }
+                       if (dmalen1 > (devpriv->ui_AiScanLength * 2)) {
+                               dmalen1 = devpriv->ui_AiScanLength * 2;
+                               if (devpriv->ui_AiScanLength & 1)
+                                       dmalen1 -= 2;
+                               if (dmalen1 < 4)
+                                       dmalen1 = 4;
+                       }
+               } else {        // isn't output buff smaller that our DMA buff?
+                       if (dmalen0 > (devpriv->ui_AiDataLength)) {
+                               dmalen0 = devpriv->ui_AiDataLength;
+                       }
+                       if (dmalen1 > (devpriv->ui_AiDataLength)) {
+                               dmalen1 = devpriv->ui_AiDataLength;
+                       }
+               }
+               devpriv->ui_DmaBufferUsesize[0] = dmalen0;
+               devpriv->ui_DmaBufferUsesize[1] = dmalen1;
+
+               //Initialize DMA
+
+               // Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS register
+               //1
+               ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+               outl(ui_Tmp, devpriv->i_IobaseAmcc + AMCC_OP_REG_AGCSTS);
+
+               // changed  since 16 bit interface for add on
+               /*********************/
+               /* ENABLE BUS MASTER */
+               /*********************/
+               outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+               outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+                       devpriv->i_IobaseAddon + 2);
+
+               outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+               outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH,
+                       devpriv->i_IobaseAddon + 2);
+
+               // TO VERIFIED
+               //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+               outw(0x1000, devpriv->i_IobaseAddon + 2);
+               //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+               //2  No change
+               // A2P FIFO MANAGEMENT
+               // A2P fifo reset  & transfer control enable
+                /***********************/
+               /* A2P FIFO MANAGEMENT */
+                /***********************/
+               outl(APCI3120_A2P_FIFO_MANAGEMENT, devpriv->i_IobaseAmcc +
+                       APCI3120_AMCC_OP_MCSR);
+
+               //3
+               //beginning address of dma buf
+               //The 32 bit address of dma buffer is converted into two 16 bit addresses
+               // Can done by using _attach and put into into an array
+               // array used may be for differnet pages
+
+               // DMA Start Adress Low
+               outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+               outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
+                       devpriv->i_IobaseAddon + 2);
+
+                /*************************/
+               /* DMA Start Adress High */
+                /*************************/
+               outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+               outw((devpriv->ul_DmaBufferHw[0] / 65536),
+                       devpriv->i_IobaseAddon + 2);
+
+               //4
+               // amount of bytes to be transfered  set transfer count
+               // used ADDON MWTC register
+               //commented testing             outl(devpriv->ui_DmaBufferUsesize[0], devpriv->i_IobaseAddon+AMCC_OP_REG_AMWTC);
+
+                /**************************/
+               /* Nbr of acquisition LOW */
+                /**************************/
+               outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+               outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF),
+                       devpriv->i_IobaseAddon + 2);
+
+                /***************************/
+               /* Nbr of acquisition HIGH */
+                /***************************/
+               outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+               outw((devpriv->ui_DmaBufferUsesize[0] / 65536),
+                       devpriv->i_IobaseAddon + 2);
+
+               //5
+               // To configure A2P FIFO
+               // testing outl( FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);
+
+               /******************/
+               /* A2P FIFO RESET */
+               /******************/
+               // TO VERIFY
+               //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+               outl(0x04000000UL, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+               //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+               //6
+               //ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+               // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+               //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+               //outw(3,devpriv->i_IobaseAddon + 4);
+               //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+               //7
+               //initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
+               /***************************************************/
+               /* A2P FIFO CONFIGURATE, END OF DMA INTERRUPT INIT */
+               /***************************************************/
+               outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+                               APCI3120_ENABLE_WRITE_TC_INT),
+                       devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+
+               //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+               /******************************************/
+               /* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */
+               /******************************************/
+               outw(3, devpriv->i_IobaseAddon + 4);
+               //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+               /******************/
+               /* A2P FIFO RESET */
+               /******************/
+               //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+               outl(0x04000000UL,
+                       devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR);
+               //END JK 07.05.04: Comparison between WIN32 and Linux driver
+       }
+
+       if ((devpriv->us_UseDma == APCI3120_DISABLE)
+               && !devpriv->b_AiContinuous) {
+               // set gate 2   to start conversion
+               devpriv->us_OutputRegister =
+                       devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2;
+               outw(devpriv->us_OutputRegister,
+                       dev->iobase + APCI3120_WR_ADDRESS);
+       }
+
+       switch (mode) {
+       case 1:
+               // set gate 0   to start conversion
+               devpriv->us_OutputRegister =
+                       devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
+               outw(devpriv->us_OutputRegister,
+                       dev->iobase + APCI3120_WR_ADDRESS);
+               break;
+       case 2:
+               // set  gate 0 and gate 1
+               devpriv->us_OutputRegister =
+                       devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1;
+               devpriv->us_OutputRegister =
+                       devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
+               outw(devpriv->us_OutputRegister,
+                       dev->iobase + APCI3120_WR_ADDRESS);
+               break;
+
+       }
+
+       return 0;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+|                      INTERNAL FUNCTIONS                                                               |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : int i_APCI3120_Reset(comedi_device *dev)               |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Hardware reset function                                                       |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :  comedi_device *dev                                                                       |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_Reset(comedi_device * dev)
+{
+       unsigned int i;
+       unsigned short us_TmpValue;
+
+       devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+       devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+       devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+       devpriv->ui_EocEosConversionTime = 0;   // set eoc eos conv time to 0
+       devpriv->b_OutputMemoryStatus = 0;
+
+       // variables used in timer subdevice
+       devpriv->b_Timer2Mode = 0;
+       devpriv->b_Timer2Interrupt = 0;
+       devpriv->b_ExttrigEnable = 0;   // Disable ext trigger
+
+       /* Disable all interrupts, watchdog for the anolog output */
+       devpriv->b_ModeSelectRegister = 0;
+       outb(devpriv->b_ModeSelectRegister,
+               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+       // Disables all counters, ext trigger and clears PA, PR
+       devpriv->us_OutputRegister = 0;
+       outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
+       //Code to set the all anolog o/p channel to 0v
+       //8191 is decimal value for zero(0 v)volt in bipolar mode(default)
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1);      //channel 1
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1);      //channel 2
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1);      //channel 3
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1);      //channel 4
+
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2);      //channel 5
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2);      //channel 6
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2);      //channel 7
+       outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2);      //channel 8
+
+       //  Reset digital output to L0W
+
+//ES05  outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT);
+       udelay(10);
+
+       inw(dev->iobase + 0);   //make a dummy read
+       inb(dev->iobase + APCI3120_RESET_FIFO); // flush FIFO
+       inw(dev->iobase + APCI3120_RD_STATUS);  // flush A/D status register
+
+       //code to reset the RAM sequence
+       for (i = 0; i < 16; i++) {
+               us_TmpValue = i << 8;   //select the location
+               outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+       }
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : int i_APCI3120_SetupChannelList(comedi_device * dev,   |
+|                     comedi_subdevice * s, int n_chan,unsigned int *chanlist|
+|                        ,char check)                                                                                   |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :This function will first check channel list is ok or not|
+|and then initialize the sequence RAM with the polarity, Gain,Channel number |
+|If the last argument of function "check"is 1 then it only checks the channel|
+|list is ok or not.                                                                                                             |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device * dev                                                                       |
+|                     comedi_subdevice * s                                                                      |
+|                     int n_chan                                                                |
+                         unsigned int *chanlist
+                         char check
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_SetupChannelList(comedi_device * dev, comedi_subdevice * s,
+       int n_chan, unsigned int *chanlist, char check)
+{
+       unsigned int i;         //, differencial=0, bipolar=0;
+       unsigned int gain;
+       unsigned short us_TmpValue;
+
+       /* correct channel and range number check itself comedi/range.c */
+       if (n_chan < 1) {
+               if (!check)
+                       comedi_error(dev, "range/channel list is empty!");
+               return 0;
+       }
+       // All is ok, so we can setup channel/range list
+       if (check)
+               return 1;
+
+       //Code  to set the PA and PR...Here it set PA to 0..
+       devpriv->us_OutputRegister =
+               devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR;
+       devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8;
+       outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
+       for (i = 0; i < n_chan; i++) {
+               // store range list to card
+               us_TmpValue = CR_CHAN(chanlist[i]);     // get channel number;
+
+               if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES) {
+                       us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff);   // set bipolar
+               } else {
+                       us_TmpValue |= APCI3120_UNIPOLAR;       // enable unipolar......
+               }
+
+               gain = CR_RANGE(chanlist[i]);   // get gain number
+               us_TmpValue |= ((gain & 0x03) << 4);    //<<4 for G0 and G1 bit in RAM
+               us_TmpValue |= i << 8;  //To select the RAM LOCATION....
+               outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+
+               printk("\n Gain = %i",
+                       (((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2));
+               printk("\n Channel = %i", CR_CHAN(chanlist[i]));
+               printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR);
+       }
+       return 1;               // we can serve this with scan logic
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :  int i_APCI3120_ExttrigEnable(comedi_device * dev)    |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :  Enable the external trigger                                                  |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :  comedi_device * dev                                                                      |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :      0                                                                    |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_ExttrigEnable(comedi_device * dev)
+{
+
+       devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
+       outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :  int i_APCI3120_ExttrigDisable(comedi_device * dev)   |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :  Disables the external trigger                                        |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :  comedi_device * dev                                                                      |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :    0                                                                      |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_ExttrigDisable(comedi_device * dev)
+{
+       devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
+       outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+|                    INTERRUPT FUNCTIONS                                                |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : void v_APCI3120_Interrupt(int irq, void *d)                                                               |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :Interrupt handler for APCI3120                             |
+|                       When interrupt occurs this gets called.                 |
+|                       First it finds which interrupt has been generated and   |
+|                       handles  corresponding interrupt                        |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :  int irq                                                                                          |
+|                        void *d                                                                                        |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      : void                                                                      |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+void v_APCI3120_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+       USHORT int_daq;
+
+       unsigned int int_amcc, ui_Check, i;
+       USHORT us_TmpValue;
+       BYTE b_DummyRead;
+
+       comedi_subdevice *s = dev->subdevices + 0;
+       ui_Check = 1;
+
+       int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;       // get IRQ reasons
+       int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);     // get AMCC INT register
+
+       if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
+               comedi_error(dev, "IRQ from unknow source");
+               return;
+       }
+
+       outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);        // shutdown IRQ reasons in AMCC
+
+       int_daq = (int_daq >> 12) & 0xF;
+
+       if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+               //Disable ext trigger
+               i_APCI3120_ExttrigDisable(dev);
+               devpriv->b_ExttrigEnable = APCI3120_DISABLE;
+       }
+       //clear the timer 2 interrupt
+       inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER);
+
+       if (int_amcc & MASTER_ABORT_INT)
+               comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
+       if (int_amcc & TARGET_ABORT_INT)
+               comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
+
+       // Ckeck if EOC interrupt
+       if (((int_daq & 0x8) == 0)
+               && (devpriv->b_InterruptMode == APCI3120_EOC_MODE)) {
+               if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+
+                       // Read the AI Value
+
+                       devpriv->ui_AiReadData[0] =
+                               (UINT) inw(devpriv->iobase + 0);
+                       devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+                       send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+               } else {
+                       //Disable EOC Interrupt
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT;
+                       outb(devpriv->b_ModeSelectRegister,
+                               devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+               }
+       }
+
+       // Check If EOS interrupt
+       if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) {
+
+               if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE)      // enable this in without DMA ???
+               {
+
+                       if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
+                               ui_Check = 0;
+                               i_APCI3120_InterruptHandleEos(dev);
+                               devpriv->ui_AiActualScan++;
+                               devpriv->b_ModeSelectRegister =
+                                       devpriv->
+                                       b_ModeSelectRegister |
+                                       APCI3120_ENABLE_EOS_INT;
+                               outb(devpriv->b_ModeSelectRegister,
+                                       dev->iobase +
+                                       APCI3120_WRITE_MODE_SELECT);
+                       } else {
+                               ui_Check = 0;
+                               for (i = 0; i < devpriv->ui_AiNbrofChannels;
+                                       i++) {
+                                       us_TmpValue = inw(devpriv->iobase + 0);
+                                       devpriv->ui_AiReadData[i] =
+                                               (UINT) us_TmpValue;
+                               }
+                               devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+                               devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+
+                               send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+
+                       }
+
+               } else {
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
+                       outb(devpriv->b_ModeSelectRegister,
+                               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+                       devpriv->b_EocEosInterrupt = APCI3120_DISABLE;  //Default settings
+                       devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+               }
+
+       }
+       //Timer2 interrupt
+       if (int_daq & 0x1) {
+
+               switch (devpriv->b_Timer2Mode) {
+               case APCI3120_COUNTER:
+
+                       devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
+                       outb(devpriv->b_ModeSelectRegister,
+                               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+                       // stop timer 2
+                       devpriv->us_OutputRegister =
+                               devpriv->
+                               us_OutputRegister & APCI3120_DISABLE_ALL_TIMER;
+                       outw(devpriv->us_OutputRegister,
+                               dev->iobase + APCI3120_WR_ADDRESS);
+
+                       //stop timer 0 and timer 1
+                       i_APCI3120_StopCyclicAcquisition(dev, s);
+                       devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+
+                       //UPDATE-0.7.57->0.7.68comedi_done(dev,s);
+                       s->async->events |= COMEDI_CB_EOA;
+                       comedi_event(dev, s);
+
+                       break;
+
+               case APCI3120_TIMER:
+
+                       //Send a signal to from kernel to user space
+                       send_sig(SIGIO, devpriv->tsk_Current, 0);
+                       break;
+
+               case APCI3120_WATCHDOG:
+
+                       //Send a signal to from kernel to user space
+                       send_sig(SIGIO, devpriv->tsk_Current, 0);
+                       break;
+
+               default:
+
+                       // disable Timer Interrupt
+
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister &
+                               APCI3120_DISABLE_TIMER_INT;
+
+                       outb(devpriv->b_ModeSelectRegister,
+                               dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+               }
+
+               b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+
+       }
+
+       if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) {
+               if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
+
+                       /****************************/
+                       /* Clear Timer Write TC INT */
+                       /****************************/
+
+                       outl(APCI3120_CLEAR_WRITE_TC_INT,
+                               devpriv->i_IobaseAmcc +
+                               APCI3120_AMCC_OP_REG_INTCSR);
+
+                       /************************************/
+                       /* Clears the timer status register */
+                       /************************************/
+                       inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+                       v_APCI3120_InterruptDma(irq, d);        // do some data transfer
+               } else {
+                       /* Stops the Timer */
+                       outw(devpriv->
+                               us_OutputRegister & APCI3120_DISABLE_TIMER0 &
+                               APCI3120_DISABLE_TIMER1,
+                               dev->iobase + APCI3120_WR_ADDRESS);
+               }
+
+       }
+
+       return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InterruptHandleEos(comedi_device *dev)   |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : This function handles EOS interrupt.                   |
+|                     This function copies the acquired data(from FIFO)      |
+|                              to Comedi buffer.                                                                        |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      : 0                                                                         |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+/*int i_APCI3120_InterruptHandleEos(comedi_device *dev)
+{
+       int n_chan,i;
+       sampl_t *data;
+       comedi_subdevice *s=dev->subdevices+0;
+       comedi_async *async = s->async;
+       data=async->data+async->buf_int_ptr;//new samples added from here onwards
+       n_chan=devpriv->ui_AiNbrofChannels;
+
+       for(i=0;i<n_chan;i++)
+         {
+           data[i]=inw(dev->iobase+0);
+         }
+       async->buf_int_count+=n_chan*sizeof(sampl_t);
+       async->buf_int_ptr+=n_chan*sizeof(sampl_t);
+       comedi_eos(dev,s);
+       if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over
+                        {
+*//* buffer rollover */
+/*             s->async->buf_int_ptr=0;
+               comedi_eobuf(dev,s);
+         }
+       return 0;
+}*/
+int i_APCI3120_InterruptHandleEos(comedi_device * dev)
+{
+       int n_chan, i;
+       comedi_subdevice *s = dev->subdevices + 0;
+       int err = 1;
+
+       n_chan = devpriv->ui_AiNbrofChannels;
+
+       s->async->events = 0;
+
+       for (i = 0; i < n_chan; i++)
+               err &= comedi_buf_put(s->async, inw(dev->iobase + 0));
+
+       s->async->events |= COMEDI_CB_EOS;
+
+       if (err == 0)
+               s->async->events |= COMEDI_CB_OVERFLOW;
+
+       comedi_event(dev, s);
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : void v_APCI3120_InterruptDma(int irq, void *d)                                                                    |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : This is a handler for the DMA interrupt                |
+|                        This function copies the data to Comedi Buffer.        |
+|                        For continuous DMA it reinitializes the DMA operation. |
+|                        For single mode DMA it stop the acquisition.           |
+|                                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq, void *d                          |
+|                                                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :  void                                                                     |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+void v_APCI3120_InterruptDma(int irq, void *d)
+{
+       comedi_device *dev = d;
+       comedi_subdevice *s = dev->subdevices + 0;
+       unsigned int next_dma_buf, samplesinbuf;
+       unsigned long low_word, high_word, var;
+
+       UINT ui_Tmp;
+       samplesinbuf =
+               devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
+               inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
+
+       if (samplesinbuf <
+               devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) {
+               comedi_error(dev, "Interrupted DMA transfer!");
+       }
+       if (samplesinbuf & 1) {
+               comedi_error(dev, "Odd count of bytes in DMA ring!");
+               i_APCI3120_StopCyclicAcquisition(dev, s);
+               devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+
+               return;
+       }
+       samplesinbuf = samplesinbuf >> 1;       // number of received samples
+       if (devpriv->b_DmaDoubleBuffer) {
+               // switch DMA buffers if is used double buffering
+               next_dma_buf = 1 - devpriv->ui_DmaActualBuffer;
+
+               ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+               outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
+
+               // changed  since 16 bit interface for add on
+               outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+               outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+                       devpriv->i_IobaseAddon + 2);
+               outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+               outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); // 0x1000 is out putted in windows driver
+
+               var = devpriv->ul_DmaBufferHw[next_dma_buf];
+               low_word = var & 0xffff;
+               var = devpriv->ul_DmaBufferHw[next_dma_buf];
+               high_word = var / 65536;
+
+               /* DMA Start Adress Low */
+               outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+               outw(low_word, devpriv->i_IobaseAddon + 2);
+
+               /* DMA Start Adress High */
+               outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+               outw(high_word, devpriv->i_IobaseAddon + 2);
+
+               var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
+               low_word = var & 0xffff;
+               var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
+               high_word = var / 65536;
+
+               /* Nbr of acquisition LOW */
+               outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+               outw(low_word, devpriv->i_IobaseAddon + 2);
+
+               /* Nbr of acquisition HIGH */
+               outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+               outw(high_word, devpriv->i_IobaseAddon + 2);
+
+               // To configure A2P FIFO
+               // ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+               // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+               outw(3, devpriv->i_IobaseAddon + 4);
+               //initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
+               outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+                               APCI3120_ENABLE_WRITE_TC_INT),
+                       devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+
+       }
+/*UPDATE-0.7.57->0.7.68
+       ptr=(sampl_t *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer];
+
+
+       // if there is not enough space left in the buffer to copy all data contained in the DMABufferVirtual
+       if(s->async->buf_int_ptr+samplesinbuf*sizeof(sampl_t)>=devpriv->ui_AiDataLength)
+       {
+               m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(sampl_t);
+               v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,m);
+               s->async->buf_int_count+=m*sizeof(sampl_t);
+               ptr+=m*sizeof(sampl_t);
+                samplesinbuf-=m;
+               s->async->buf_int_ptr=0;
+               comedi_eobuf(dev,s);
+       }
+
+       if (samplesinbuf)
+       {
+               v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,samplesinbuf);
+
+               s->async->buf_int_count+=samplesinbuf*sizeof(sampl_t);
+               s->async->buf_int_ptr+=samplesinbuf*sizeof(sampl_t);
+               if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS))
+               {
+                       comedi_bufcheck(dev,s);
+                }
+       }
+       if (!devpriv->b_AiContinuous)
+       if ( devpriv->ui_AiActualScan>=devpriv->ui_AiNbrofScans )
+       {
+           // all data sampled
+           i_APCI3120_StopCyclicAcquisition(dev,s);
+            devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE;
+           //DPRINTK("\n Single DMA completed..\n");
+               comedi_done(dev,s);
+               return;
+       }
+*/
+       if (samplesinbuf) {
+               v_APCI3120_InterruptDmaMoveBlock16bit(dev, s,
+                       devpriv->ul_DmaBufferVirtual[devpriv->
+                               ui_DmaActualBuffer], samplesinbuf);
+
+               if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) {
+                       s->async->events |= COMEDI_CB_EOS;
+                       comedi_event(dev, s);
+               }
+       }
+       if (!devpriv->b_AiContinuous)
+               if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) {
+                       // all data sampled
+                       i_APCI3120_StopCyclicAcquisition(dev, s);
+                       devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+                       s->async->events |= COMEDI_CB_EOA;
+                       comedi_event(dev, s);
+                       return;
+               }
+
+       if (devpriv->b_DmaDoubleBuffer) {       // switch dma buffers
+               devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
+       } else {
+               // restart DMA if is not used double buffering
+               //ADDED REINITIALISE THE DMA
+               ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+               outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
+
+               // changed  since 16 bit interface for add on
+               outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+               outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+                       devpriv->i_IobaseAddon + 2);
+               outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+               outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); //
+               // A2P FIFO MANAGEMENT
+               // A2P fifo reset  & transfer control enable
+               outl(APCI3120_A2P_FIFO_MANAGEMENT,
+                       devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+
+               var = devpriv->ul_DmaBufferHw[0];
+               low_word = var & 0xffff;
+               var = devpriv->ul_DmaBufferHw[0];
+               high_word = var / 65536;
+               outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+               outw(low_word, devpriv->i_IobaseAddon + 2);
+               outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+               outw(high_word, devpriv->i_IobaseAddon + 2);
+
+               var = devpriv->ui_DmaBufferUsesize[0];
+               low_word = var & 0xffff;        //changed
+               var = devpriv->ui_DmaBufferUsesize[0];
+               high_word = var / 65536;
+               outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+               outw(low_word, devpriv->i_IobaseAddon + 2);
+               outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+               outw(high_word, devpriv->i_IobaseAddon + 2);
+
+               // To configure A2P FIFO
+               //ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+               // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+               outw(3, devpriv->i_IobaseAddon + 4);
+               //initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
+               outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+                               APCI3120_ENABLE_WRITE_TC_INT),
+                       devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+       }
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device|
+|*dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n)                                 |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : This function copies the data from DMA buffer to the   |
+|                               Comedi buffer                                                                           |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     sampl_t *dma                                                                                      |
+|                     sampl_t *data,int n                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : void                                                                      |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+/*void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n)
+{
+       int i,j,m;
+
+       j=s->async->cur_chan;
+       m=devpriv->ui_AiActualScanPosition;
+        for(i=0;i<n;i++)
+       {
+               *data=*dma;
+               data++; dma++;
+               j++;
+               if(j>=devpriv->ui_AiNbrofChannels)
+               {
+                       m+=j;
+                       j=0;
+                       if(m>=devpriv->ui_AiScanLength)
+                       {
+                               m=0;
+                               devpriv->ui_AiActualScan++;
+                               if (devpriv->ui_AiFlags & TRIG_WAKE_EOS)
+;//UPDATE-0.7.57->0.7.68                                       comedi_eos(dev,s);
+                       }
+               }
+       }
+        devpriv->ui_AiActualScanPosition=m;
+       s->async->cur_chan=j;
+
+}
+*/
+void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+       comedi_subdevice * s, sampl_t * dma_buffer, unsigned int num_samples)
+{
+       devpriv->ui_AiActualScan +=
+               (s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
+       s->async->cur_chan += num_samples;
+       s->async->cur_chan %= devpriv->ui_AiScanLength;
+
+       cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(sampl_t));
+}
+
+/*
++----------------------------------------------------------------------------+
+|                           TIMER SUBDEVICE                                     |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnConfigTimer(comedi_device *dev,          |
+|      comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                        |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :Configure Timer 2                                                                      |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
+|                                                                                                                               |
+|                      data[0]= TIMER  configure as timer                    |
+|                                               = WATCHDOG configure as watchdog                                |
+|                                data[1] = Timer constant                                                       |
+|                                data[2] = Timer2 interrupt (1)enable or(0) disable |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ui_Timervalue2;
+       USHORT us_TmpValue;
+       BYTE b_Tmp;
+
+       if (!data[1])
+               comedi_error(dev, "config:No timer constant !");
+
+       devpriv->b_Timer2Interrupt = (BYTE) data[2];    // save info whether to enable or disable interrupt
+
+       ui_Timervalue2 = data[1] / 1000;        // convert nano seconds  to u seconds
+
+       //this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(BYTE)data[0]);
+       us_TmpValue = (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+       //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+       // and calculate the time value to set in the timer
+       if ((us_TmpValue & 0x00B0) == 0x00B0
+               || !strcmp(this_board->pc_DriverName, "apci3001")) {
+               //Calculate the time value to set in the timer
+               ui_Timervalue2 = ui_Timervalue2 / 50;
+       } else {
+               //Calculate the time value to set in the timer
+               ui_Timervalue2 = ui_Timervalue2 / 70;
+       }
+
+       //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0)
+       devpriv->us_OutputRegister =
+               devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2;
+       outw(devpriv->us_OutputRegister, devpriv->iobase + APCI3120_WR_ADDRESS);
+
+       // Disable TIMER Interrupt
+       devpriv->b_ModeSelectRegister =
+               devpriv->
+               b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF;
+
+       // Disable Eoc and Eos Interrupts
+       devpriv->b_ModeSelectRegister =
+               devpriv->
+               b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT &
+               APCI3120_DISABLE_EOS_INT;
+       outb(devpriv->b_ModeSelectRegister,
+               devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+       if (data[0] == APCI3120_TIMER)  //initialize timer
+       {
+
+               //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT ;
+               //outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT);
+
+               //Set the Timer 2 in mode 2(Timer)
+               devpriv->b_TimerSelectMode =
+                       (devpriv->
+                       b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2;
+               outb(devpriv->b_TimerSelectMode,
+                       devpriv->iobase + APCI3120_TIMER_CRT1);
+
+               //Configure the timer 2 for writing the LOW WORD of timer is Delay value
+               //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+               //you can set the digital output and configure the timer 2,and if you don't make this, digital output
+               //are erase (Set to 0)
+
+               //Writing LOW WORD
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_LOW_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+               outw(LOWORD(ui_Timervalue2),
+                       devpriv->iobase + APCI3120_TIMER_VALUE);
+
+               //Writing HIGH WORD
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_HIGH_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+               outw(HIWORD(ui_Timervalue2),
+                       devpriv->iobase + APCI3120_TIMER_VALUE);
+               // timer2 in Timer mode enabled
+               devpriv->b_Timer2Mode = APCI3120_TIMER;
+
+       } else                  // Initialize Watch dog
+       {
+
+               //Set the Timer 2 in mode 5(Watchdog)
+
+               devpriv->b_TimerSelectMode =
+                       (devpriv->
+                       b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_5;
+               outb(devpriv->b_TimerSelectMode,
+                       devpriv->iobase + APCI3120_TIMER_CRT1);
+
+               //Configure the timer 2 for writing the LOW WORD of timer is Delay value
+               //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+               //you can set the digital output and configure the timer 2,and if you don't make this, digital output
+               //are erase (Set to 0)
+
+               //Writing LOW WORD
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_LOW_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+               outw(LOWORD(ui_Timervalue2),
+                       devpriv->iobase + APCI3120_TIMER_VALUE);
+
+               //Writing HIGH WORD
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_HIGH_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+               outw(HIWORD(ui_Timervalue2),
+                       devpriv->iobase + APCI3120_TIMER_VALUE);
+               //watchdog enabled
+               devpriv->b_Timer2Mode = APCI3120_WATCHDOG;
+
+       }
+
+       return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnWriteTimer(comedi_device *dev,           |
+|                    comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)  |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :    To start and stop the timer                            |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                         |
+|                                                                            |
+|                              data[0] = 1 (start)                                  |
+|                              data[0] = 0 (stop )                                  |
+|                              data[0] = 2  (write new value)                       |
+|                              data[1]= new value                                   |
+|                                                                            |
+|                              devpriv->b_Timer2Mode =  0 DISABLE                   |
+|                                                               1 Timer                     |
+|                                                                               2 Watch dog                         |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ui_Timervalue2 = 0;
+       USHORT us_TmpValue;
+       BYTE b_Tmp;
+
+       if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+               && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
+               comedi_error(dev, "\nwrite:timer2  not configured ");
+               return -EINVAL;
+       }
+
+       if (data[0] == 2)       // write new value
+       {
+               if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
+                       comedi_error(dev,
+                               "write :timer2  not configured  in TIMER MODE");
+                       return -EINVAL;
+               }
+
+               if (data[1])
+                       ui_Timervalue2 = data[1];
+               else
+                       ui_Timervalue2 = 0;
+       }
+
+       //this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2);
+
+       switch (data[0]) {
+       case APCI3120_START:
+
+               // Reset FC_TIMER BIT
+               inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+               if (devpriv->b_Timer2Mode == APCI3120_TIMER)    //start timer
+               {
+                       //Enable Timer
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->b_ModeSelectRegister & 0x0B;
+               } else          //start watch dog
+               {
+                       //Enable WatchDog
+                       devpriv->b_ModeSelectRegister =
+                               (devpriv->
+                               b_ModeSelectRegister & 0x0B) |
+                               APCI3120_ENABLE_WATCHDOG;
+               }
+
+               //enable disable interrupt
+               if ((devpriv->b_Timer2Interrupt) == APCI3120_ENABLE) {
+
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister |
+                               APCI3120_ENABLE_TIMER_INT;
+                       // save the task structure to pass info to user
+                       devpriv->tsk_Current = current;
+               } else {
+
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister &
+                               APCI3120_DISABLE_TIMER_INT;
+               }
+               outb(devpriv->b_ModeSelectRegister,
+                       devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+               if (devpriv->b_Timer2Mode == APCI3120_TIMER)    //start timer
+               {
+                       //For Timer mode is  Gate2 must be activated   **timer started
+                       devpriv->us_OutputRegister =
+                               devpriv->
+                               us_OutputRegister | APCI3120_ENABLE_TIMER2;
+                       outw(devpriv->us_OutputRegister,
+                               devpriv->iobase + APCI3120_WR_ADDRESS);
+               }
+
+               break;
+
+       case APCI3120_STOP:
+               if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
+                       //Disable timer
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister &
+                               APCI3120_DISABLE_TIMER_COUNTER;
+               } else {
+                       //Disable WatchDog
+                       devpriv->b_ModeSelectRegister =
+                               devpriv->
+                               b_ModeSelectRegister &
+                               APCI3120_DISABLE_WATCHDOG;
+               }
+               // Disable timer interrupt
+               devpriv->b_ModeSelectRegister =
+                       devpriv->
+                       b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT;
+
+               // Write above states  to register
+               outb(devpriv->b_ModeSelectRegister,
+                       devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+               // Reset Gate 2
+               devpriv->us_OutputRegister =
+                       devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT;
+               outw(devpriv->us_OutputRegister,
+                       devpriv->iobase + APCI3120_WR_ADDRESS);
+
+               // Reset FC_TIMER BIT
+               inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+
+               // Disable timer
+               //devpriv->b_Timer2Mode=APCI3120_DISABLE;
+
+               break;
+
+       case 2:         //write new value to Timer
+               if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
+                       comedi_error(dev,
+                               "write :timer2  not configured  in TIMER MODE");
+                       return -EINVAL;
+               }
+               // ui_Timervalue2=data[1]; // passed as argument
+               us_TmpValue =
+                       (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+               //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+               // and calculate the time value to set in the timer
+               if ((us_TmpValue & 0x00B0) == 0x00B0
+                       || !strcmp(this_board->pc_DriverName, "apci3001")) {
+                       //Calculate the time value to set in the timer
+                       ui_Timervalue2 = ui_Timervalue2 / 50;
+               } else {
+                       //Calculate the time value to set in the timer
+                       ui_Timervalue2 = ui_Timervalue2 / 70;
+               }
+               //Writing LOW WORD
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_LOW_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+               outw(LOWORD(ui_Timervalue2),
+                       devpriv->iobase + APCI3120_TIMER_VALUE);
+
+               //Writing HIGH WORD
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_HIGH_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+               outw(HIWORD(ui_Timervalue2),
+                       devpriv->iobase + APCI3120_TIMER_VALUE);
+
+               break;
+       default:
+               return -EINVAL; // Not a valid input
+       }
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : int i_APCI3120_InsnReadTimer(comedi_device *dev,           |
+|              comedi_subdevice *s,comedi_insn *insn, lsampl_t *data)           |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : read the Timer value                                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  :  comedi_device *dev                                                                       |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
+|                                                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                                                           |
+|                      for Timer:      data[0]= Timer constant                                          |
+|                                                                                                                                       |
+|                      for watchdog: data[0]=0 (still running)                  |
+|                                        data[0]=1  (run down)                                  |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_Tmp;
+       USHORT us_TmpValue, us_TmpValue_2, us_StatusValue;
+
+       if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+               && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
+               comedi_error(dev, "\nread:timer2  not configured ");
+       }
+
+       //this_board->i_hwdrv_InsnReadTimer(dev,data);
+       if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
+
+               //Read the LOW WORD of Timer 2 register
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_LOW_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+               us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+
+               //Read the HIGH WORD of Timer 2 register
+               b_Tmp = ((devpriv->
+                               b_DigitalOutputRegister) & 0xF0) |
+                       APCI3120_SELECT_TIMER_2_HIGH_WORD;
+               outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+               us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+
+               // combining both words
+               data[0] = (UINT) ((us_TmpValue) | ((us_TmpValue_2) << 16));
+
+       } else                  // Read watch dog status
+       {
+
+               us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS);
+               us_StatusValue =
+                       ((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1;
+               if (us_StatusValue == 1) {
+                       // RESET FC_TIMER BIT
+                       inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+               }
+               data[0] = us_StatusValue;       // when data[0] = 1 then the watch dog has rundown
+       }
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+|                           DIGITAL INPUT SUBDEVICE                             |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnReadDigitalInput(comedi_device *dev,     |
+|                      comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)   |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Reads the value of the specified  Digital input channel|
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice
+       * s, comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Chan, ui_TmpValue;
+
+       ui_Chan = CR_CHAN(insn->chanspec);      // channel specified
+
+       //this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data);
+       if (ui_Chan >= 0 && ui_Chan <= 3) {
+               ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+               //      since only 1 channel reqd  to bring it to last bit it is rotated
+               //  8 +(chan - 1) times then ANDed with 1 for last bit.
+               *data = (ui_TmpValue >> (ui_Chan + 8)) & 1;
+               //return 0;
+       } else {
+               //      comedi_error(dev," chan spec wrong");
+               return -EINVAL; // "sorry channel spec wrong "
+       }
+       return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev, |
+|comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)                      |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Reads the value of the Digital input Port i.e.4channels|
+|   value is returned in data[0]                                                                                        |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_TmpValue;
+       ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+       /*****  state of 4 channels  in the 11, 10, 9, 8   bits of status reg
+                       rotated right 8 times to bring them to last four bits
+                       ANDed with oxf for  value.
+       *****/
+
+       *data = (ui_TmpValue >> 8) & 0xf;
+       //this_board->i_hwdrv_InsnBitsDigitalInput(dev,data);
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+|                           DIGITAL OUTPUT SUBDEVICE                                    |
++----------------------------------------------------------------------------+
+*/
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnConfigDigitalOutput(comedi_device    |
+| *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                            |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              :Configure the output memory ON or OFF                                  |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :comedi_device *dev                                                                                 |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Not a valid Data !!! ,Data should be 1 or 0\n");
+               return -EINVAL;
+       }
+       if (data[0]) {
+               devpriv->b_OutputMemoryStatus = APCI3120_ENABLE;
+
+       } else {
+               devpriv->b_OutputMemoryStatus = APCI3120_DISABLE;
+               devpriv->b_DigitalOutputRegister = 0;
+       }
+       if (!devpriv->b_OutputMemoryStatus) {
+               ui_Temp = 0;
+
+       }                       //if(!devpriv->b_OutputMemoryStatus )
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev,    |
+|              comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)           |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : write diatal output port                                                      |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
+                      data[0]     Value to be written
+                      data[1]    :1 Set digital o/p ON
+                      data[1]     2 Set digital o/p OFF with memory ON
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice
+       * s, comedi_insn * insn, lsampl_t * data)
+{
+       if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
+
+               comedi_error(dev, "Data is not valid !!! \n");
+               return -EINVAL;
+       }
+
+       switch (data[1]) {
+       case 1:
+               data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
+               break;
+
+       case 2:
+               data[0] = data[0];
+               break;
+       default:
+               printk("\nThe parameter passed is in error \n");
+               return -EINVAL;
+       }                       // switch(data[1])
+       outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+
+       devpriv->b_DigitalOutputRegister = data[0] & 0xF0;
+
+       return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev,|
+|comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                                      |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Write digiatl output                                                                  |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
+                      data[0]     Value to be written
+                      data[1]    :1 Set digital o/p ON
+                      data[1]     2 Set digital o/p OFF with memory ON
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice
+       * s, comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ui_Temp1;
+
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Not a valid Data !!! ,Data should be 1 or 0\n");
+               return -EINVAL;
+       }
+       if ((ui_NoOfChannel > (this_board->i_NbrDoChannel - 1))
+               || (ui_NoOfChannel < 0)) {
+               comedi_error(dev,
+                       "This board doesn't have specified channel !!! \n");
+               return -EINVAL;
+       }
+
+       switch (data[1]) {
+       case 1:
+               data[0] = (data[0] << ui_NoOfChannel);
+//ES05                   data[0]=(data[0]<<4)|ui_Temp;
+               data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
+               break;
+
+       case 2:
+               data[0] = ~data[0] & 0x1;
+               ui_Temp1 = 1;
+               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+               ui_Temp1 = ui_Temp1 << 4;
+//ES05                   ui_Temp=ui_Temp|ui_Temp1;
+               devpriv->b_DigitalOutputRegister =
+                       devpriv->b_DigitalOutputRegister | ui_Temp1;
+
+               data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
+               data[0] = data[0] << 4;
+//ES05                   data[0]=data[0]& ui_Temp;
+               data[0] = data[0] & devpriv->b_DigitalOutputRegister;
+               break;
+       default:
+               printk("\nThe parameter passed is in error \n");
+               return -EINVAL;
+       }                       // switch(data[1])
+       outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+
+//ES05        ui_Temp=data[0] & 0xf0;
+       devpriv->b_DigitalOutputRegister = data[0] & 0xf0;
+       return (insn->n);
+
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            ANALOG OUTPUT SUBDEVICE                         |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev,|
+|comedi_subdevice *s, comedi_insn *insn,lsampl_t *data)                                     |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Write  analog output                                                          |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                                                        |
+|                     comedi_subdevice *s                                                                       |
+|                     comedi_insn *insn                                      |
+|                     lsampl_t *data                                                                            |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnWriteAnalogOutput(comedi_device * dev, comedi_subdevice
+       * s, comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Range, ui_Channel;
+       USHORT us_TmpValue;
+
+       ui_Range = CR_RANGE(insn->chanspec);
+       ui_Channel = CR_CHAN(insn->chanspec);
+
+       //this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]);
+       if (ui_Range)           // if 1 then unipolar
+       {
+
+               if (data[0] != 0)
+                       data[0] =
+                               ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
+                                       13) | (data[0] + 8191));
+               else
+                       data[0] =
+                               ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
+                                       13) | 8192);
+
+       } else                  // if 0 then   bipolar
+       {
+               data[0] =
+                       ((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) |
+                       data[0]);
+
+       }
+
+       //out put n values at the given channel.
+       // rt_printk("\nwaiting for DA_READY BIT");
+       do                      //Waiting of DA_READY BIT
+       {
+               us_TmpValue =
+                       ((USHORT) inw(devpriv->iobase +
+                               APCI3120_RD_STATUS)) & 0x0001;
+       } while (us_TmpValue != 0x0001);
+
+       if (ui_Channel <= 3)
+               // for channel 0-3 out at  the register 1 (wrDac1-8)
+               // data[i] typecasted to ushort since  word write is to be done
+               outw((USHORT) data[0],
+                       devpriv->iobase + APCI3120_ANALOG_OUTPUT_1);
+       else
+               // for channel 4-7 out at the register 2 (wrDac5-8)
+               //data[i] typecasted to ushort since  word write is to be done
+               outw((USHORT) data[0],
+                       devpriv->iobase + APCI3120_ANALOG_OUTPUT_2);
+
+       return insn->n;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
new file mode 100644 (file)
index 0000000..5c5d2c1
--- /dev/null
@@ -0,0 +1,276 @@
+
+// hwdrv_apci3120.h
+
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project   : ADDI DATA         | Compiler : GCC                                   |
+  | Modulname : hwdrv_apci3120.h  | Version  : 2.96  Redhat Linux         |
+  |                               |                    kernel-2.4.2       |
+  +-------------------------------+---------------------------------------+
+  | Author    :                          | Date     :                                    |
+  +-----------------------------------------------------------------------+
+  | Description :Header file for apci3120 hardware abstraction layer      |
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |                          |                                                                                                |
+  |          |           |                                                                                               |
+  |          |           |                                                           |
+  |          |           |                                                                                               |
+  |          |           |                                                                   |
+  +----------+-----------+------------------------------------------------+
+  |         |                   |                                                                        |
+  |          |           |                                                                                               |
+  |          |           |                                                                               |
+  +----------+-----------+------------------------------------------------+
+*/
+
+// comedi related defines
+
+//ANALOG INPUT RANGE
+static const comedi_lrange range_apci3120_ai = { 8, {
+                       BIP_RANGE(10),
+                       BIP_RANGE(5),
+                       BIP_RANGE(2),
+                       BIP_RANGE(1),
+                       UNI_RANGE(10),
+                       UNI_RANGE(5),
+                       UNI_RANGE(2),
+                       UNI_RANGE(1)
+       }
+};
+
+// ANALOG OUTPUT RANGE
+static const comedi_lrange range_apci3120_ao = { 2, {
+                       BIP_RANGE(10),
+                       UNI_RANGE(10)
+       }
+};
+
+#define APCI3120_BIPOLAR_RANGES        4       // used for test on mixture of BIP/UNI ranges
+
+#define APCI3120_BOARD_VENDOR_ID                 0x10E8
+#define APCI3120_ADDRESS_RANGE                                 16
+
+#define APCI3120_DISABLE                         0
+#define APCI3120_ENABLE                          1
+
+#define APCI3120_START                           1
+#define APCI3120_STOP                            0
+
+#define     APCI3120_EOC_MODE         1
+#define     APCI3120_EOS_MODE         2
+#define     APCI3120_DMA_MODE         3
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI3120_DIGITAL_OUTPUT                        0x0D
+#define APCI3120_RD_STATUS                             0x02
+#define APCI3120_RD_FIFO                               0x00
+
+// digital output insn_write ON /OFF selection
+#define        APCI3120_SET4DIGITALOUTPUTON                            1
+#define APCI3120_SET4DIGITALOUTPUTOFF                          0
+
+// analog output SELECT BIT
+#define APCI3120_ANALOG_OP_CHANNEL_1   0x0000
+#define APCI3120_ANALOG_OP_CHANNEL_2   0x4000
+#define APCI3120_ANALOG_OP_CHANNEL_3   0x8000
+#define APCI3120_ANALOG_OP_CHANNEL_4   0xC000
+#define APCI3120_ANALOG_OP_CHANNEL_5   0x0000
+#define APCI3120_ANALOG_OP_CHANNEL_6   0x4000
+#define APCI3120_ANALOG_OP_CHANNEL_7   0x8000
+#define APCI3120_ANALOG_OP_CHANNEL_8   0xC000
+
+// Enable external trigger bit in nWrAddress
+#define APCI3120_ENABLE_EXT_TRIGGER    0x8000
+
+//ANALOG OUTPUT AND INPUT DEFINE
+#define APCI3120_UNIPOLAR 0x80 //$$ RAM sequence polarity BIT
+#define APCI3120_BIPOLAR  0x00 //$$ RAM sequence polarity BIT
+#define APCI3120_ANALOG_OUTPUT_1 0x08  // (ADDRESS )
+#define APCI3120_ANALOG_OUTPUT_2 0x0A  // (ADDRESS )
+#define APCI3120_1_GAIN              0x00      //$$ RAM sequence Gain Bits for gain 1
+#define APCI3120_2_GAIN              0x10      //$$ RAM sequence Gain Bits for gain 2
+#define APCI3120_5_GAIN              0x20      //$$ RAM sequence Gain Bits for gain 5
+#define APCI3120_10_GAIN             0x30      //$$ RAM sequence Gain Bits for gain 10
+#define APCI3120_SEQ_RAM_ADDRESS        0x06   //$$ EARLIER NAMED APCI3120_FIFO_ADDRESS
+#define APCI3120_RESET_FIFO          0x0C      //(ADDRESS)
+#define APCI3120_TIMER_0_MODE_2      0x01      //$$ Bits for timer mode
+#define APCI3120_TIMER_0_MODE_4       0x2
+#define APCI3120_SELECT_TIMER_0_WORD 0x00
+#define APCI3120_ENABLE_TIMER0     0x1000      //$$Gatebit 0 in nWrAddress
+#define APCI3120_CLEAR_PR          0xF0FF
+#define APCI3120_CLEAR_PA          0xFFF0
+#define APCI3120_CLEAR_PA_PR       (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA)
+
+// nWrMode_Select
+#define APCI3120_ENABLE_SCAN          0x8      //$$ bit in nWrMode_Select
+#define APCI3120_DISABLE_SCAN      (~APCI3120_ENABLE_SCAN)
+#define APCI3120_ENABLE_EOS_INT       0x2      //$$ bit in nWrMode_Select
+
+#define APCI3120_DISABLE_EOS_INT   (~APCI3120_ENABLE_EOS_INT)
+#define APCI3120_ENABLE_EOC_INT       0x1
+#define APCI3120_DISABLE_EOC_INT   (~APCI3120_ENABLE_EOC_INT)
+#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER   (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+#define APCI3120_DISABLE_ALL_INTERRUPT   (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+
+//status register bits
+#define APCI3120_EOC                     0x8000
+#define APCI3120_EOS                     0x2000
+
+// software trigger dummy register
+#define APCI3120_START_CONVERSION        0x02  //(ADDRESS)
+
+//TIMER DEFINE
+#define APCI3120_QUARTZ_A                                70
+#define APCI3120_QUARTZ_B                                50
+#define APCI3120_TIMER                            1
+#define APCI3120_WATCHDOG                         2
+#define APCI3120_TIMER_DISABLE                    0
+#define APCI3120_TIMER_ENABLE                     1
+#define APCI3120_ENABLE_TIMER2                    0x4000       //$$ gatebit 2 in nWrAddress
+#define APCI3120_DISABLE_TIMER2                   (~APCI3120_ENABLE_TIMER2)
+#define APCI3120_ENABLE_TIMER_INT                 0x04 //$$ ENAIRQ_FC_Bit in nWrModeSelect
+#define APCI3120_DISABLE_TIMER_INT                (~APCI3120_ENABLE_TIMER_INT)
+#define APCI3120_WRITE_MODE_SELECT                0x0E // (ADDRESS)
+#define APCI3120_SELECT_TIMER_0_WORD  0x00
+#define APCI3120_SELECT_TIMER_1_WORD  0x01
+#define APCI3120_TIMER_1_MODE_2       0x4
+
+//$$ BIT FOR MODE IN nCsTimerCtr1
+#define APCI3120_TIMER_2_MODE_0                   0x0
+#define APCI3120_TIMER_2_MODE_2                   0x10
+#define APCI3120_TIMER_2_MODE_5                   0x30
+
+//$$ BIT FOR MODE IN nCsTimerCtr0
+#define APCI3120_SELECT_TIMER_2_LOW_WORD          0x02
+#define APCI3120_SELECT_TIMER_2_HIGH_WORD         0x03
+
+#define APCI3120_TIMER_CRT0                       0x0D //(ADDRESS for cCsTimerCtr0)
+#define APCI3120_TIMER_CRT1                       0x0C //(ADDRESS for cCsTimerCtr1)
+
+#define APCI3120_TIMER_VALUE                      0x04 //ADDRESS for nCsTimerWert
+#define APCI3120_TIMER_STATUS_REGISTER            0x0D //ADDRESS for delete timer 2 interrupt
+#define APCI3120_RD_STATUS                        0x02 //ADDRESS
+#define APCI3120_WR_ADDRESS                       0x00 //ADDRESS
+#define APCI3120_ENABLE_WATCHDOG                  0x20 //$$BIT in nWrMode_Select
+#define APCI3120_DISABLE_WATCHDOG                 (~APCI3120_ENABLE_WATCHDOG)
+#define APCI3120_ENABLE_TIMER_COUNTER                    0x10  //$$BIT in nWrMode_Select
+#define APCI3120_DISABLE_TIMER_COUNTER            (~APCI3120_ENABLE_TIMER_COUNTER)
+#define APCI3120_FC_TIMER                         0x1000       //bit in  status register
+#define APCI3120_ENABLE_TIMER0                    0x1000
+#define APCI3120_ENABLE_TIMER1                    0x2000
+#define APCI3120_ENABLE_TIMER2                    0x4000
+#define APCI3120_DISABLE_TIMER0                                  (~APCI3120_ENABLE_TIMER0)
+#define APCI3120_DISABLE_TIMER1                              (~APCI3120_ENABLE_TIMER1)
+#define APCI3120_DISABLE_TIMER2                          (~APCI3120_ENABLE_TIMER2)
+
+#define APCI3120_TIMER2_SELECT_EOS                0xC0 // ADDED on 20-6
+#define APCI3120_COUNTER                          3    // on 20-6
+#define APCI3120_DISABLE_ALL_TIMER                ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 )      // on 20-6
+
+#define MAX_ANALOGINPUT_CHANNELS    32
+
+typedef struct {
+       BYTE b_Type;            /* EOC or EOS */
+       BYTE b_InterruptFlag;   /* Interrupt use or not                    */
+       UINT ui_ConvertTiming;  /* Selection of the convertion time        */
+       BYTE b_NbrOfChannel;    /* Number of channel to read               */
+       UINT ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];  /* Number of the channel to be read        */
+       UINT ui_RangeList[MAX_ANALOGINPUT_CHANNELS];    /* Gain of each channel                    */
+
+} str_AnalogReadInformation;
+
+// Function Declaration For APCI-3120
+
+// Internal functions
+int i_APCI3120_SetupChannelList(comedi_device * dev, comedi_subdevice * s,
+       int n_chan, unsigned int *chanlist, char check);
+int i_APCI3120_ExttrigEnable(comedi_device * dev);
+int i_APCI3120_ExttrigDisable(comedi_device * dev);
+int i_APCI3120_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s);
+int i_APCI3120_Reset(comedi_device * dev);
+int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,
+       comedi_subdevice * s);
+// Interrupt functions
+void v_APCI3120_Interrupt(int irq, void *d);
+//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n);
+void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device * dev,
+       comedi_subdevice * s, sampl_t * dma_buffer, unsigned int num_samples);
+int i_APCI3120_InterruptHandleEos(comedi_device * dev);
+void v_APCI3120_InterruptDma(int irq, void *d);
+
+// TIMER
+
+int i_APCI3120_InsnConfigTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI3120_InsnWriteTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI3120_InsnReadTimer(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//DI
+// for di read
+
+int i_APCI3120_InsnBitsDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI3120_InsnReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//DO
+//int i_APCI3120_WriteDigitalOutput(comedi_device *dev, BYTE data);
+int i_APCI3120_InsnConfigDigitalOutput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+int i_APCI3120_InsnBitsDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI3120_InsnWriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//AO
+//int i_APCI3120_Write1AnalogValue(comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
+int i_APCI3120_InsnWriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//AI HArdware layer
+
+int i_APCI3120_InsnConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI3120_InsnReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+int i_APCI3120_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_cmd * cmd);
+int i_APCI3120_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s);
+//int i_APCI3120_CancelAnalogInput(comedi_device * dev, comedi_subdevice * s);
+int i_APCI3120_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
new file mode 100644 (file)
index 0000000..8a507da
--- /dev/null
@@ -0,0 +1,3642 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-3200       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci3200.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-3200                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 02.07.04 | J. Krauth | Modification from the driver in order to       |
+  |          |           | correct some errors when using several boards. |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+  | 26.10.04 | J. Krauth | - Update for COMEDI 0.7.68                     |
+  |          |           | - Read eeprom value                            |
+  |          |           | - Append APCI-3300                             |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
+  +----------------------------------------------------------------------------+
+  |                               Included files                               |
+  +----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci3200.h"
+//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+#include "addi_amcc_S5920.h"
+//#define PRINT_INFO
+
+//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+//BEGIN JK 06.07.04: Management of sevrals boards
+/*
+  INT i_CJCAvailable=1;
+  INT i_CJCPolarity=0;
+  INT i_CJCGain=2;//changed from 0 to 2
+  INT i_InterruptFlag=0;
+  INT i_ADDIDATAPolarity;
+  INT i_ADDIDATAGain;
+  INT i_AutoCalibration=0;   //: auto calibration
+  INT i_ADDIDATAConversionTime;
+  INT i_ADDIDATAConversionTimeUnit;
+  INT i_ADDIDATAType;
+  INT i_ChannelNo;
+  INT i_ChannelCount=0;
+  INT i_ScanType;
+  INT i_FirstChannel;
+  INT i_LastChannel;
+  INT i_Sum=0;
+  INT i_Offset;
+  UINT ui_Channel_num=0;
+  static int i_Count=0;
+  INT i_Initialised=0;
+  UINT ui_InterruptChannelValue[96]; //Buffer
+*/
+str_BoardInfos s_BoardInfos[100];      // 100 will be the max number of boards to be used
+//END JK 06.07.04: Management of sevrals boards
+
+//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+/*+----------------------------------------------------------------------------+*/
+/*| Function   Name   : INT i_AddiHeaderRW_ReadEeprom                          |*/
+/*|                               (INT    i_NbOfWordsToRead,                   |*/
+/*|                                DWORD dw_PCIBoardEepromAddress,             |*/
+/*|                                WORD   w_EepromStartAddress,                |*/
+/*|                                PWORD pw_DataRead)                          |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Task              : Read word from the 5920 eeprom.                        |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Input Parameters  : INT    i_NbOfWordsToRead : Nbr. of word to read        |*/
+/*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+/*|                     WORD   w_EepromStartAddress : Eeprom strat address     |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Output Parameters : PWORD pw_DataRead : Read data                          |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Return Value      : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+
+INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+       DWORD dw_PCIBoardEepromAddress,
+       WORD w_EepromStartAddress, PWORD pw_DataRead)
+{
+       DWORD dw_eeprom_busy = 0;
+       INT i_Counter = 0;
+       INT i_WordCounter;
+       INT i;
+       BYTE pb_ReadByte[1];
+       BYTE b_ReadLowByte = 0;
+       BYTE b_ReadHighByte = 0;
+       BYTE b_SelectedAddressLow = 0;
+       BYTE b_SelectedAddressHigh = 0;
+       WORD w_ReadWord = 0;
+
+       for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+               i_WordCounter++) {
+               do {
+                       dw_eeprom_busy =
+                               inl(dw_PCIBoardEepromAddress +
+                               AMCC_OP_REG_MCSR);
+                       dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+               }
+               while (dw_eeprom_busy == EEPROM_BUSY);
+
+               for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+                       b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;        //Read the low 8 bit part
+                       b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256;       //Read the high 8 bit part
+
+                       //Select the load low address mode
+                       outb(NVCMD_LOAD_LOW,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Load the low address
+                       outb(b_SelectedAddressLow,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the load high address mode
+                       outb(NVCMD_LOAD_HIGH,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Load the high address
+                       outb(b_SelectedAddressHigh,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the READ mode
+                       outb(NVCMD_BEGIN_READ,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Read data into the EEPROM
+                       *pb_ReadByte =
+                               inb(dw_PCIBoardEepromAddress +
+                               AMCC_OP_REG_MCSR + 2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the upper address part
+                       if (i_Counter == 0) {
+                               b_ReadLowByte = pb_ReadByte[0];
+                       } else {
+                               b_ReadHighByte = pb_ReadByte[0];
+                       }
+
+                       //Sleep
+                       for (i = 0; i < 10000; i++) ;
+
+               }
+               w_ReadWord =
+                       (b_ReadLowByte | (((unsigned short)b_ReadHighByte) *
+                               256));
+
+               pw_DataRead[i_WordCounter] = w_ReadWord;
+
+               w_EepromStartAddress += 2;      // to read the next word
+
+       }                       // for (...) i_NbOfWordsToRead
+       return (0);
+}
+
+/*+----------------------------------------------------------------------------+*/
+/*| Function   Name   : VOID v_GetAPCI3200EepromCalibrationValue (VOID)        |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Task              : Read calibration value from the APCI-3200 eeprom.      |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Input Parameters  : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Output Parameters : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Return Value      : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+
+VOID v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
+       str_BoardInfos * BoardInformations)
+{
+       WORD w_AnalogInputMainHeaderAddress;
+       WORD w_AnalogInputComponentAddress;
+       WORD w_NumberOfModuls = 0;
+       WORD w_CurrentSources[2];
+       WORD w_ModulCounter = 0;
+       WORD w_FirstHeaderSize = 0;
+       WORD w_NumberOfInputs = 0;
+       WORD w_CJCFlag = 0;
+       WORD w_NumberOfGainValue = 0;
+       WORD w_SingleHeaderAddress = 0;
+       WORD w_SingleHeaderSize = 0;
+       WORD w_Input = 0;
+       WORD w_GainFactorAddress = 0;
+       WORD w_GainFactorValue[2];
+       WORD w_GainIndex = 0;
+       WORD w_GainValue = 0;
+
+  /*****************************************/
+  /** Get the Analog input header address **/
+  /*****************************************/
+       i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+               dw_PCIBoardEepromAddress, 0x116,        //w_EepromStartAddress: Analog input header address
+               &w_AnalogInputMainHeaderAddress);
+
+  /*******************************************/
+  /** Compute the real analog input address **/
+  /*******************************************/
+       w_AnalogInputMainHeaderAddress = w_AnalogInputMainHeaderAddress + 0x100;
+
+  /******************************/
+  /** Get the number of moduls **/
+  /******************************/
+       i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+               dw_PCIBoardEepromAddress, w_AnalogInputMainHeaderAddress + 0x02,        //w_EepromStartAddress: Number of conponment
+               &w_NumberOfModuls);
+
+       for (w_ModulCounter = 0; w_ModulCounter < w_NumberOfModuls;
+               w_ModulCounter++) {
+      /***********************************/
+      /** Compute the component address **/
+      /***********************************/
+               w_AnalogInputComponentAddress =
+                       w_AnalogInputMainHeaderAddress +
+                       (w_FirstHeaderSize * w_ModulCounter) + 0x04;
+
+      /****************************/
+      /** Read first header size **/
+      /****************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress,        // Address of the first header
+                       &w_FirstHeaderSize);
+
+               w_FirstHeaderSize = w_FirstHeaderSize >> 4;
+
+      /***************************/
+      /** Read number of inputs **/
+      /***************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x06, // Number of inputs for the first modul
+                       &w_NumberOfInputs);
+
+               w_NumberOfInputs = w_NumberOfInputs >> 4;
+
+      /***********************/
+      /** Read the CJC flag **/
+      /***********************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x08, // CJC flag
+                       &w_CJCFlag);
+
+               w_CJCFlag = (w_CJCFlag >> 3) & 0x1;     // Get only the CJC flag
+
+      /*******************************/
+      /** Read number of gain value **/
+      /*******************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x44, // Number of gain value
+                       &w_NumberOfGainValue);
+
+               w_NumberOfGainValue = w_NumberOfGainValue & 0xFF;
+
+      /***********************************/
+      /** Compute single header address **/
+      /***********************************/
+               w_SingleHeaderAddress =
+                       w_AnalogInputComponentAddress + 0x46 +
+                       (((w_NumberOfGainValue / 16) + 1) * 2) +
+                       (6 * w_NumberOfGainValue) +
+                       (4 * (((w_NumberOfGainValue / 16) + 1) * 2));
+
+      /********************************************/
+      /** Read current sources value for input 1 **/
+      /********************************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_SingleHeaderAddress,        //w_EepromStartAddress: Single header address
+                       &w_SingleHeaderSize);
+
+               w_SingleHeaderSize = w_SingleHeaderSize >> 4;
+
+      /*************************************/
+      /** Read gain factor for the module **/
+      /*************************************/
+               w_GainFactorAddress = w_AnalogInputComponentAddress;
+
+               for (w_GainIndex = 0; w_GainIndex < w_NumberOfGainValue;
+                       w_GainIndex++) {
+         /************************************/
+         /** Read gain value for the module **/
+         /************************************/
+                       i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                               dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + (2 * (1 + (w_NumberOfGainValue / 16))) + (0x02 * w_GainIndex),   // Gain value
+                               &w_GainValue);
+
+                       BoardInformations->s_Module[w_ModulCounter].
+                               w_GainValue[w_GainIndex] = w_GainValue;
+
+#             ifdef PRINT_INFO
+                       printk("\n Gain value = %d",
+                               BoardInformations->s_Module[w_ModulCounter].
+                               w_GainValue[w_GainIndex]);
+#             endif
+
+         /*************************************/
+         /** Read gain factor for the module **/
+         /*************************************/
+                       i_AddiHeaderRW_ReadEeprom(2,    //i_NbOfWordsToRead
+                               dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + ((2 * w_NumberOfGainValue) + (2 * (1 + (w_NumberOfGainValue / 16)))) + (0x04 * w_GainIndex),     // Gain factor
+                               w_GainFactorValue);
+
+                       BoardInformations->s_Module[w_ModulCounter].
+                               ul_GainFactor[w_GainIndex] =
+                               (w_GainFactorValue[1] << 16) +
+                               w_GainFactorValue[0];
+
+#             ifdef PRINT_INFO
+                       printk("\n w_GainFactorValue [%d] = %lu", w_GainIndex,
+                               BoardInformations->s_Module[w_ModulCounter].
+                               ul_GainFactor[w_GainIndex]);
+#             endif
+               }
+
+      /***************************************************************/
+      /** Read current source value for each channels of the module **/
+      /***************************************************************/
+               for (w_Input = 0; w_Input < w_NumberOfInputs; w_Input++) {
+         /********************************************/
+         /** Read current sources value for input 1 **/
+         /********************************************/
+                       i_AddiHeaderRW_ReadEeprom(2,    //i_NbOfWordsToRead
+                               dw_PCIBoardEepromAddress,
+                               (w_Input * w_SingleHeaderSize) +
+                               w_SingleHeaderAddress + 0x0C, w_CurrentSources);
+
+         /************************************/
+         /** Save the current sources value **/
+         /************************************/
+                       BoardInformations->s_Module[w_ModulCounter].
+                               ul_CurrentSource[w_Input] =
+                               (w_CurrentSources[0] +
+                               ((w_CurrentSources[1] & 0xFFF) << 16));
+
+#             ifdef PRINT_INFO
+                       printk("\n Current sources [%d] = %lu", w_Input,
+                               BoardInformations->s_Module[w_ModulCounter].
+                               ul_CurrentSource[w_Input]);
+#             endif
+               }
+
+      /***************************************/
+      /** Read the CJC current source value **/
+      /***************************************/
+               i_AddiHeaderRW_ReadEeprom(2,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress,
+                       (w_Input * w_SingleHeaderSize) + w_SingleHeaderAddress +
+                       0x0C, w_CurrentSources);
+
+      /************************************/
+      /** Save the current sources value **/
+      /************************************/
+               BoardInformations->s_Module[w_ModulCounter].
+                       ul_CurrentSourceCJC =
+                       (w_CurrentSources[0] +
+                       ((w_CurrentSources[1] & 0xFFF) << 16));
+
+#          ifdef PRINT_INFO
+               printk("\n Current sources CJC = %lu",
+                       BoardInformations->s_Module[w_ModulCounter].
+                       ul_CurrentSourceCJC);
+#          endif
+       }
+}
+
+INT i_APCI3200_GetChannelCalibrationValue(comedi_device * dev,
+       unsigned int ui_Channel_num, lsampl_t * CJCCurrentSource,
+       lsampl_t * ChannelCurrentSource, lsampl_t * ChannelGainFactor)
+{
+       int i_DiffChannel = 0;
+       int i_Module = 0;
+
+#ifdef PRINT_INFO
+       printk("\n Channel = %u", ui_Channel_num);
+#endif
+
+       //Test if single or differential mode
+       if (s_BoardInfos[dev->minor].i_ConnectionType == 1) {
+               //if diff
+
+               if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1))
+                       i_DiffChannel = ui_Channel_num, i_Module = 0;
+               else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3))
+                       i_DiffChannel = ui_Channel_num - 2, i_Module = 1;
+               else if ((ui_Channel_num >= 4) && (ui_Channel_num <= 5))
+                       i_DiffChannel = ui_Channel_num - 4, i_Module = 2;
+               else if ((ui_Channel_num >= 6) && (ui_Channel_num <= 7))
+                       i_DiffChannel = ui_Channel_num - 6, i_Module = 3;
+
+       } else {
+               // if single
+               if ((ui_Channel_num == 0) || (ui_Channel_num == 1))
+                       i_DiffChannel = 0, i_Module = 0;
+               else if ((ui_Channel_num == 2) || (ui_Channel_num == 3))
+                       i_DiffChannel = 1, i_Module = 0;
+               else if ((ui_Channel_num == 4) || (ui_Channel_num == 5))
+                       i_DiffChannel = 0, i_Module = 1;
+               else if ((ui_Channel_num == 6) || (ui_Channel_num == 7))
+                       i_DiffChannel = 1, i_Module = 1;
+               else if ((ui_Channel_num == 8) || (ui_Channel_num == 9))
+                       i_DiffChannel = 0, i_Module = 2;
+               else if ((ui_Channel_num == 10) || (ui_Channel_num == 11))
+                       i_DiffChannel = 1, i_Module = 2;
+               else if ((ui_Channel_num == 12) || (ui_Channel_num == 13))
+                       i_DiffChannel = 0, i_Module = 3;
+               else if ((ui_Channel_num == 14) || (ui_Channel_num == 15))
+                       i_DiffChannel = 1, i_Module = 3;
+       }
+
+       //Test if thermocouple or RTD mode
+       *CJCCurrentSource =
+               s_BoardInfos[dev->minor].s_Module[i_Module].ul_CurrentSourceCJC;
+#ifdef PRINT_INFO
+       printk("\n CJCCurrentSource = %lu", *CJCCurrentSource);
+#endif
+
+       *ChannelCurrentSource =
+               s_BoardInfos[dev->minor].s_Module[i_Module].
+               ul_CurrentSource[i_DiffChannel];
+#ifdef PRINT_INFO
+       printk("\n ChannelCurrentSource = %lu", *ChannelCurrentSource);
+#endif
+       //      }
+       //   }
+
+       //Channle gain factor
+       *ChannelGainFactor =
+               s_BoardInfos[dev->minor].s_Module[i_Module].
+               ul_GainFactor[s_BoardInfos[dev->minor].i_ADDIDATAGain];
+#ifdef PRINT_INFO
+       printk("\n ChannelGainFactor = %lu", *ChannelGainFactor);
+#endif
+       //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+       return (0);
+}
+
+//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadDigitalInput                       |
+  |                      (comedi_device *dev,comedi_subdevice *s,               |
+  |                      comedi_insn *insn,lsampl_t *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel or port           |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT ui_NoOfChannels    : No Of Channels To read  for Port
+  Channel Numberfor single channel
+  |                     UINT data[0]            : 0: Read single channel
+  1: Read port value
+  data[1]              Port number
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --      data[0] :Read status value
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+
+INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp = 0;
+       UINT ui_NoOfChannel = 0;
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       ui_Temp = data[0];
+       *data = inl(devpriv->i_IobaseReserved);
+
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       //if  (ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       if (data[1] < 0 || data[1] > 1) {
+                               printk("\nThe port number is in error\n");
+                               return -EINVAL;
+                       }       //if(data[1] < 0 || data[1] >1)
+                       switch (ui_NoOfChannel) {
+
+                       case 2:
+                               *data = (*data >> (2 * data[1])) & 0x3;
+                               break;
+                       case 3:
+                               *data = (*data & 15);
+                               break;
+                       default:
+                               comedi_error(dev, " chan spec wrong");
+                               return -EINVAL; // "sorry channel spec wrong "
+
+                       }       //switch(ui_NoOfChannels)
+               }               //if  (ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               //elseif  (ui_Temp==1)
+       }
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ConfigDigitalOutput                     |
+  |                      (comedi_device *dev,comedi_subdevice *s,                               |
+  |                      comedi_insn *insn,lsampl_t *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Configures The Digital Output Subdevice.               |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev : Driver handle                     |
+  |                      data[0]  :1  Memory enable
+  0  Memory Disable
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error                      |
+  |                                                                                                                                     |
+  +----------------------------------------------------------------------------+
+*/
+int i_APCI3200_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Not a valid Data !!! ,Data should be 1 or 0\n");
+               return -EINVAL;
+       }                       //if  ( (data[0]!=0) && (data[0]!=1) )
+       if (data[0]) {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+       }                       // if  (data[0])
+       else {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+       }                       //else if  (data[0])
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_WriteDigitalOutput                      |
+  |                      (comedi_device *dev,comedi_subdevice *s,                               |
+  |                      comedi_insn *insn,lsampl_t *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : writes To the digital Output Subdevice                 |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     comedi_subdevice *s     : Subdevice Pointer            |
+  |                     comedi_insn *insn       : Insn Structure Pointer       |
+  |                     lsampl_t *data          : Data Pointer contains        |
+  |                                          configuration parameters as below |
+  |                     data[0]             :Value to output
+  data[1]             : 0 o/p single channel
+  1 o/p port
+  data[2]             : port no
+  data[3]             :0 set the digital o/p on
+  1 set the digital o/p off
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error              |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+INT i_APCI3200_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp = 0, ui_Temp1 = 0;
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+       if (devpriv->b_OutputMemoryStatus) {
+               ui_Temp = inl(devpriv->i_IobaseAddon);
+
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       else {
+               ui_Temp = 0;
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outl(data[0], devpriv->i_IobaseAddon);
+               }               //if(data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               switch (ui_NoOfChannel) {
+
+                               case 2:
+                                       data[0] =
+                                               (data[0] << (2 *
+                                                       data[2])) | ui_Temp;
+                                       break;
+                               case 3:
+                                       data[0] = (data[0] | ui_Temp);
+                                       break;
+                               }       //switch(ui_NoOfChannels)
+
+                               outl(data[0], devpriv->i_IobaseAddon);
+                       }       // if(data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       //else if(data[1]==1)
+               }               //elseif(data[1]==0)
+       }                       //if(data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
+                               data[0] = data[0] & ui_Temp;
+                               outl(data[0], devpriv->i_IobaseAddon);
+                       }       //if(data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       switch (ui_NoOfChannel) {
+
+                                       case 2:
+                                               data[0] = ~data[0] & 0x3;
+                                               ui_Temp1 = 3;
+                                               ui_Temp1 =
+                                                       ui_Temp1 << 2 * data[2];
+                                               ui_Temp = ui_Temp | ui_Temp1;
+                                               data[0] =
+                                                       ((data[0] << (2 *
+                                                                       data
+                                                                       [2])) ^
+                                                       0xf) & ui_Temp;
+
+                                               break;
+                                       case 3:
+                                               break;
+
+                                       default:
+                                               comedi_error(dev,
+                                                       " chan spec wrong");
+                                               return -EINVAL; // "sorry channel spec wrong "
+                                       }       //switch(ui_NoOfChannels)
+
+                                       outl(data[0], devpriv->i_IobaseAddon);
+                               }       // if(data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       //else if(data[1]==1)
+                       }       //elseif(data[1]==0)
+               }               //if(data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               //if else data[3]==1)
+       }                       //if else data[3]==0)
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadDigitalOutput                       |
+  |                      (comedi_device *dev,comedi_subdevice *s,               |
+  |                      comedi_insn *insn,lsampl_t *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel or port           |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+  |                     UINT *data              : Data Pointer to read status  |
+  data[0]                 :0 read single channel
+  1 read port value
+  data[1]                  port no
+
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+INT i_APCI3200_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp;
+       UINT ui_NoOfChannel;
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       ui_Temp = data[0];
+       *data = inl(devpriv->i_IobaseAddon);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       // if  (ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       if (data[1] < 0 || data[1] > 1) {
+                               printk("\nThe port selection is in error\n");
+                               return -EINVAL;
+                       }       //if(data[1] <0 ||data[1] >1)
+                       switch (ui_NoOfChannel) {
+                       case 2:
+                               *data = (*data >> (2 * data[1])) & 3;
+                               break;
+
+                       case 3:
+                               break;
+
+                       default:
+                               comedi_error(dev, " chan spec wrong");
+                               return -EINVAL; // "sorry channel spec wrong "
+                               break;
+                       }       // switch(ui_NoOfChannels)
+               }               // if  (ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               // else if (ui_Temp==1)
+       }                       // else if  (ui_Temp==0)
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : INT i_APCI3200_ConfigAnalogInput                       |
+  |                      (comedi_device *dev,comedi_subdevice *s,               |
+  |                      comedi_insn *insn,lsampl_t *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Configures The Analog Input Subdevice                  |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     comedi_subdevice *s     : Subdevice Pointer            |
+  |                     comedi_insn *insn       : Insn Structure Pointer       |
+  |                     lsampl_t *data          : Data Pointer contains        |
+  |                                          configuration parameters as below |
+  |                                                                            |
+  |                                    data[0]
+  |                                               0:Normal AI                  |
+  |                                               1:RTD                        |
+  |                                               2:THERMOCOUPLE               |
+  |                                data[1]            : Gain To Use                 |
+  |                                                                            |
+  |                           data[2]            : Polarity
+  |                                                0:Bipolar                   |
+  |                                                1:Unipolar                  |
+  |                                                                                                                             |
+  |                           data[3]            : Offset Range
+  |                                                                            |
+  |                           data[4]            : Coupling
+  |                                                0:DC Coupling               |
+  |                                                1:AC Coupling               |
+  |                                                                            |
+  |                           data[5]            :Differential/Single
+  |                                                0:Single                    |
+  |                                                1:Differential              |
+  |                                                                            |
+  |                           data[6]            :TimerReloadValue
+  |                                                                            |
+  |                           data[7]            :ConvertingTimeUnit
+  |                                                                            |
+  |                           data[8]             :0 Analog voltage measurement
+  1 Resistance measurement
+  2 Temperature measurement
+  |                           data[9]            :Interrupt
+  |                                              0:Disable
+  |                                              1:Enable
+  data[10]           :Type of Thermocouple
+  |                          data[11]           : 0: single channel
+  Module Number
+  |
+  |                          data[12]
+  |                                             0:Single Read
+  |                                             1:Read more channel
+  2:Single scan
+  |                                             3:Continous Scan
+  data[13]          :Number of channels to read
+  |                          data[14]          :RTD connection type
+  :0:RTD not used
+  1:RTD 2 wire connection
+  2:RTD 3 wire connection
+  3:RTD 4 wire connection
+  |                                                                            |
+  |                                                                            |
+  |                                                                            |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       UINT ul_Config = 0, ul_Temp = 0;
+       UINT ui_ChannelNo = 0;
+       UINT ui_Dummy = 0;
+       INT i_err = 0;
+
+       //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+#ifdef PRINT_INFO
+       INT i = 0, i2 = 0;
+#endif
+       //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       // Initialize the structure
+       if (s_BoardInfos[dev->minor].b_StructInitialized != 1) {
+               s_BoardInfos[dev->minor].i_CJCAvailable = 1;
+               s_BoardInfos[dev->minor].i_CJCPolarity = 0;
+               s_BoardInfos[dev->minor].i_CJCGain = 2; //changed from 0 to 2
+               s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+               s_BoardInfos[dev->minor].i_AutoCalibration = 0; //: auto calibration
+               s_BoardInfos[dev->minor].i_ChannelCount = 0;
+               s_BoardInfos[dev->minor].i_Sum = 0;
+               s_BoardInfos[dev->minor].ui_Channel_num = 0;
+               s_BoardInfos[dev->minor].i_Count = 0;
+               s_BoardInfos[dev->minor].i_Initialised = 0;
+               s_BoardInfos[dev->minor].b_StructInitialized = 1;
+
+               //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               s_BoardInfos[dev->minor].i_ConnectionType = 0;
+               //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+               //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               memset(s_BoardInfos[dev->minor].s_Module, 0,
+                       sizeof(s_BoardInfos[dev->minor].s_Module[MAX_MODULE]));
+
+               v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc,
+                       &s_BoardInfos[dev->minor]);
+
+#ifdef PRINT_INFO
+               for (i = 0; i < MAX_MODULE; i++) {
+                       printk("\n s_Module[%i].ul_CurrentSourceCJC = %lu", i,
+                               s_BoardInfos[dev->minor].s_Module[i].
+                               ul_CurrentSourceCJC);
+
+                       for (i2 = 0; i2 < 5; i2++) {
+                               printk("\n s_Module[%i].ul_CurrentSource [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_CurrentSource[i2]);
+                       }
+
+                       for (i2 = 0; i2 < 8; i2++) {
+                               printk("\n s_Module[%i].ul_GainFactor [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_GainFactor[i2]);
+                       }
+
+                       for (i2 = 0; i2 < 8; i2++) {
+                               printk("\n s_Module[%i].w_GainValue [%i] = %u",
+                                       i, i2,
+                                       s_BoardInfos[dev->minor].s_Module[i].
+                                       w_GainValue[i2]);
+                       }
+               }
+#endif
+               //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+       }
+
+       if (data[0] != 0 && data[0] != 1 && data[0] != 2) {
+               printk("\nThe selection of acquisition type is in error\n");
+               i_err++;
+       }                       //if(data[0]!=0 && data[0]!=1 && data[0]!=2)
+       if (data[0] == 1) {
+               if (data[14] != 0 && data[14] != 1 && data[14] != 2
+                       && data[14] != 4) {
+                       printk("\n Error in selection of RTD connection type\n");
+                       i_err++;
+               }               //if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4)
+       }                       //if(data[0]==1 )
+       if (data[1] < 0 || data[1] > 7) {
+               printk("\nThe selection of gain is in error\n");
+               i_err++;
+       }                       // if(data[1]<0 || data[1]>7)
+       if (data[2] != 0 && data[2] != 1) {
+               printk("\nThe selection of polarity is in error\n");
+               i_err++;
+       }                       //if(data[2]!=0 &&  data[2]!=1)
+       if (data[3] != 0) {
+               printk("\nThe selection of offset range  is in error\n");
+               i_err++;
+       }                       // if(data[3]!=0)
+       if (data[4] != 0 && data[4] != 1) {
+               printk("\nThe selection of coupling is in error\n");
+               i_err++;
+       }                       //if(data[4]!=0 &&  data[4]!=1)
+       if (data[5] != 0 && data[5] != 1) {
+               printk("\nThe selection of single/differential mode is in error\n");
+               i_err++;
+       }                       //if(data[5]!=0 &&  data[5]!=1)
+       if (data[8] != 0 && data[8] != 1 && data[2] != 2) {
+               printk("\nError in selection of functionality\n");
+       }                       //if(data[8]!=0 && data[8]!=1 && data[2]!=2)
+       if (data[12] == 0 || data[12] == 1) {
+               if (data[6] != 20 && data[6] != 40 && data[6] != 80
+                       && data[6] != 160) {
+                       printk("\nThe selection of conversion time reload value is in error\n");
+                       i_err++;
+               }               // if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 )
+               if (data[7] != 2) {
+                       printk("\nThe selection of conversion time unit  is in error\n");
+                       i_err++;
+               }               // if(data[7]!=2)
+       }
+       if (data[9] != 0 && data[9] != 1) {
+               printk("\nThe selection of interrupt enable is in error\n");
+               i_err++;
+       }                       //if(data[9]!=0 &&  data[9]!=1)
+       if (data[11] < 0 || data[11] > 4) {
+               printk("\nThe selection of module is in error\n");
+               i_err++;
+       }                       //if(data[11] <0 ||  data[11]>1)
+       if (data[12] < 0 || data[12] > 3) {
+               printk("\nThe selection of singlechannel/scan selection is in error\n");
+               i_err++;
+       }                       //if(data[12] < 0 ||  data[12]> 3)
+       if (data[13] < 0 || data[13] > 16) {
+               printk("\nThe selection of number of channels is in error\n");
+               i_err++;
+       }                       // if(data[13] <0 ||data[13] >15)
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       /*
+          i_ChannelCount=data[13];
+          i_ScanType=data[12];
+          i_ADDIDATAPolarity = data[2];
+          i_ADDIDATAGain=data[1];
+          i_ADDIDATAConversionTime=data[6];
+          i_ADDIDATAConversionTimeUnit=data[7];
+          i_ADDIDATAType=data[0];
+        */
+
+       // Save acquisition configuration for the actual board
+       s_BoardInfos[dev->minor].i_ChannelCount = data[13];
+       s_BoardInfos[dev->minor].i_ScanType = data[12];
+       s_BoardInfos[dev->minor].i_ADDIDATAPolarity = data[2];
+       s_BoardInfos[dev->minor].i_ADDIDATAGain = data[1];
+       s_BoardInfos[dev->minor].i_ADDIDATAConversionTime = data[6];
+       s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit = data[7];
+       s_BoardInfos[dev->minor].i_ADDIDATAType = data[0];
+       //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       s_BoardInfos[dev->minor].i_ConnectionType = data[5];
+       //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       //END JK 06.07.04: Management of sevrals boards
+
+       //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(lsampl_t));     // 7 is the maximal number of channels
+       //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+       //BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards
+       //while(i_InterruptFlag==1)
+       while (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
+#ifndef MSXBOX
+               udelay(1);
+#else
+               // In the case where the driver is compiled for the MSX-Box
+               // we used a printk to have a little delay because udelay
+               // seems to be broken under the MSX-Box.
+               // This solution hat to be studied.
+               printk("");
+#endif
+       }
+       //END JK 02.07.04 : This while can't be do, it block the process when using severals boards
+
+       ui_ChannelNo = CR_CHAN(insn->chanspec); // get the channel
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //i_ChannelNo=ui_ChannelNo;
+       //ui_Channel_num =ui_ChannelNo;
+
+       s_BoardInfos[dev->minor].i_ChannelNo = ui_ChannelNo;
+       s_BoardInfos[dev->minor].ui_Channel_num = ui_ChannelNo;
+
+       //END JK 06.07.04: Management of sevrals boards
+
+       if (data[5] == 0) {
+               if (ui_ChannelNo < 0 || ui_ChannelNo > 15) {
+                       printk("\nThe Selection of the channel is in error\n");
+                       i_err++;
+               }               // if(ui_ChannelNo<0 || ui_ChannelNo>15)
+       }                       //if(data[5]==0)
+       else {
+               if (data[14] == 2) {
+                       if (ui_ChannelNo < 0 || ui_ChannelNo > 3) {
+                               printk("\nThe Selection of the channel is in error\n");
+                               i_err++;
+                       }       // if(ui_ChannelNo<0 || ui_ChannelNo>3)
+               }               //if(data[14]==2)
+               else {
+                       if (ui_ChannelNo < 0 || ui_ChannelNo > 7) {
+                               printk("\nThe Selection of the channel is in error\n");
+                               i_err++;
+                       }       // if(ui_ChannelNo<0 || ui_ChannelNo>7)
+               }               //elseif(data[14]==2)
+       }                       //elseif(data[5]==0)
+       if (data[12] == 0 || data[12] == 1) {
+               switch (data[5]) {
+               case 0:
+                       if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=0;
+                               s_BoardInfos[dev->minor].i_Offset = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=0 && ui_ChannelNo <=3)
+                       if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=64;
+                               s_BoardInfos[dev->minor].i_Offset = 64;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=4 && ui_ChannelNo <=7)
+                       if (ui_ChannelNo >= 8 && ui_ChannelNo <= 11) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=128;
+                               s_BoardInfos[dev->minor].i_Offset = 128;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=8 && ui_ChannelNo <=11)
+                       if (ui_ChannelNo >= 12 && ui_ChannelNo <= 15) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=192;
+                               s_BoardInfos[dev->minor].i_Offset = 192;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=12 && ui_ChannelNo <=15)
+                       break;
+               case 1:
+                       if (data[14] == 2) {
+                               if (ui_ChannelNo == 0) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=0;
+                                       s_BoardInfos[dev->minor].i_Offset = 0;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       //if(ui_ChannelNo ==0 )
+                               if (ui_ChannelNo == 1) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=0;
+                                       s_BoardInfos[dev->minor].i_Offset = 64;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       // if(ui_ChannelNo ==1)
+                               if (ui_ChannelNo == 2) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=128;
+                                       s_BoardInfos[dev->minor].i_Offset = 128;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       //if(ui_ChannelNo ==2 )
+                               if (ui_ChannelNo == 3) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=192;
+                                       s_BoardInfos[dev->minor].i_Offset = 192;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       //if(ui_ChannelNo ==3)
+
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=0;
+                               s_BoardInfos[dev->minor].i_ChannelNo = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = 0;
+                               break;
+                       }       //if(data[14]==2)
+                       if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=0;
+                               s_BoardInfos[dev->minor].i_Offset = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=0 && ui_ChannelNo <=1)
+                       if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=i_ChannelNo-2;
+                               //i_Offset=64;
+                               s_BoardInfos[dev->minor].i_ChannelNo =
+                                       s_BoardInfos[dev->minor].i_ChannelNo -
+                                       2;
+                               s_BoardInfos[dev->minor].i_Offset = 64;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = ui_ChannelNo - 2;
+                       }       //if(ui_ChannelNo >=2 && ui_ChannelNo <=3)
+                       if (ui_ChannelNo >= 4 && ui_ChannelNo <= 5) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=i_ChannelNo-4;
+                               //i_Offset=128;
+                               s_BoardInfos[dev->minor].i_ChannelNo =
+                                       s_BoardInfos[dev->minor].i_ChannelNo -
+                                       4;
+                               s_BoardInfos[dev->minor].i_Offset = 128;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = ui_ChannelNo - 4;
+                       }       //if(ui_ChannelNo >=4 && ui_ChannelNo <=5)
+                       if (ui_ChannelNo >= 6 && ui_ChannelNo <= 7) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=i_ChannelNo-6;
+                               //i_Offset=192;
+                               s_BoardInfos[dev->minor].i_ChannelNo =
+                                       s_BoardInfos[dev->minor].i_ChannelNo -
+                                       6;
+                               s_BoardInfos[dev->minor].i_Offset = 192;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = ui_ChannelNo - 6;
+                       }       //if(ui_ChannelNo >=6 && ui_ChannelNo <=7)
+                       break;
+
+               default:
+                       printk("\n This selection of polarity does not exist\n");
+                       i_err++;
+               }               //switch(data[2])
+       }                       //if(data[12]==0 || data[12]==1)
+       else {
+               switch (data[11]) {
+               case 1:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=0;
+                       s_BoardInfos[dev->minor].i_Offset = 0;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               case 2:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=64;
+                       s_BoardInfos[dev->minor].i_Offset = 64;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               case 3:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=128;
+                       s_BoardInfos[dev->minor].i_Offset = 128;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               case 4:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=192;
+                       s_BoardInfos[dev->minor].i_Offset = 192;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               default:
+                       printk("\nError in module selection\n");
+                       i_err++;
+               }               // switch(data[11])
+       }                       // elseif(data[12]==0 || data[12]==1)
+       if (i_err) {
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }
+       //if(i_ScanType!=1)
+       if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_Count=0;
+               //i_Sum=0;
+               s_BoardInfos[dev->minor].i_Count = 0;
+               s_BoardInfos[dev->minor].i_Sum = 0;
+               //END JK 06.07.04: Management of sevrals boards
+       }                       //if(i_ScanType!=1)
+
+       ul_Config =
+               data[1] | (data[2] << 6) | (data[5] << 7) | (data[3] << 8) |
+               (data[4] << 9);
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4);
+       outl(0 | ui_ChannelNo,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+  /**************************/
+       /* Reset the configuration */
+  /**************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl(0 , devpriv->iobase+i_Offset + 0x0);
+       outl(0, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+
+  /***************************/
+       /* Write the configuration */
+  /***************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl(ul_Config , devpriv->iobase+i_Offset + 0x0);
+       outl(ul_Config,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+       //END JK 06.07.04: Management of sevrals boards
+
+  /***************************/
+       /*Reset the calibration bit */
+  /***************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //ul_Temp = inl(devpriv->iobase+i_Offset + 12);
+       ul_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12);
+       outl((ul_Temp & 0xFFF9FFFF),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+       //END JK 06.07.04: Management of sevrals boards
+
+       if (data[9] == 1) {
+               devpriv->tsk_Current = current;
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_InterruptFlag=1;
+               s_BoardInfos[dev->minor].i_InterruptFlag = 1;
+               //END JK 06.07.04: Management of sevrals boards
+       }                       // if(data[9]==1)
+       else {
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_InterruptFlag=0;
+               s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+               //END JK 06.07.04: Management of sevrals boards
+       }                       //else  if(data[9]==1)
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //i_Initialised=1;
+       s_BoardInfos[dev->minor].i_Initialised = 1;
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //if(i_ScanType==1)
+       if (s_BoardInfos[dev->minor].i_ScanType == 1)
+               //END JK 06.07.04: Management of sevrals boards
+       {
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_Sum=i_Sum+1;
+               s_BoardInfos[dev->minor].i_Sum =
+                       s_BoardInfos[dev->minor].i_Sum + 1;
+               //END JK 06.07.04: Management of sevrals boards
+
+               insn->unused[0] = 0;
+               i_APCI3200_ReadAnalogInput(dev, s, insn, &ui_Dummy);
+       }
+
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadAnalogInput                         |
+  |                              (comedi_device *dev,comedi_subdevice *s,       |
+  |                     comedi_insn *insn,lsampl_t *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel                            |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                            data[0]  : Digital Value Of Input             |
+  |                            data[1]  : Calibration Offset Value           |
+  |                            data[2]  : Calibration Gain Value
+  |                            data[3]  : CJC value
+  |                            data[4]  : CJC offset value
+  |                            data[5]  : CJC gain value
+  | Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+  |                            data[6] : CJC current source from eeprom
+  |                            data[7] : Channel current source from eeprom
+  |                            data[8] : Channle gain factor from eeprom
+  | End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_DummyValue = 0;
+       int i_ConvertCJCCalibration;
+       int i = 0;
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //if(i_Initialised==0)
+       if (s_BoardInfos[dev->minor].i_Initialised == 0)
+               //END JK 06.07.04: Management of sevrals boards
+       {
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //if(i_Initialised==0);
+
+#ifdef PRINT_INFO
+       printk("\n insn->unused[0] = %i", insn->unused[0]);
+#endif
+
+       switch (insn->unused[0]) {
+       case 0:
+
+               i_APCI3200_Read1AnalogInputChannel(dev, s, insn,
+                       &ui_DummyValue);
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //ui_InterruptChannelValue[i_Count+0]=ui_DummyValue;
+               s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                       i_Count + 0] = ui_DummyValue;
+               //END JK 06.07.04: Management of sevrals boards
+
+               //Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               i_APCI3200_GetChannelCalibrationValue(dev,
+                       s_BoardInfos[dev->minor].ui_Channel_num,
+                       &s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                               i_Count + 6],
+                       &s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                               i_Count + 7],
+                       &s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                               i_Count + 8]);
+
+#ifdef PRINT_INFO
+               printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+6] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 6]);
+
+               printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+7] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 7]);
+
+               printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]);
+#endif
+
+               //End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))
+               if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+                       && (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+                       //END JK 06.07.04: Management of sevrals boards
+               {
+                       i_APCI3200_ReadCJCValue(dev, &ui_DummyValue);
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 3] = ui_DummyValue;
+                       //END JK 06.07.04: Management of sevrals boards
+               }               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE))
+               else {
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 3]=0;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 3] = 0;
+                       //END JK 06.07.04: Management of sevrals boards
+               }               //elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE))
+               if ((s_BoardInfos[dev->minor].i_AutoCalibration == FALSE)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE))
+                       //END JK 06.07.04: Management of sevrals boards
+               {
+                       i_APCI3200_ReadCalibrationOffsetValue(dev,
+                               &ui_DummyValue);
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 1] = ui_DummyValue;
+                       //END JK 06.07.04: Management of sevrals boards
+                       i_APCI3200_ReadCalibrationGainValue(dev,
+                               &ui_DummyValue);
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 2] = ui_DummyValue;
+                       //END JK 06.07.04: Management of sevrals boards
+               }               //if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE))
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1))
+               if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+                       && (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+                       //END JK 06.07.04: Management of sevrals boards
+               {
+         /**********************************************************/
+                       /*Test if the Calibration channel must be read for the CJC */
+         /**********************************************************/
+         /**********************************/
+                       /*Test if the polarity is the same */
+         /**********************************/
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                       if (s_BoardInfos[dev->minor].i_CJCPolarity !=
+                               s_BoardInfos[dev->minor].i_ADDIDATAPolarity)
+                               //END JK 06.07.04: Management of sevrals boards
+                       {
+                               i_ConvertCJCCalibration = 1;
+                       }       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                       else {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //if(i_CJCGain==i_ADDIDATAGain)
+                               if (s_BoardInfos[dev->minor].i_CJCGain ==
+                                       s_BoardInfos[dev->minor].i_ADDIDATAGain)
+                                       //END JK 06.07.04: Management of sevrals boards
+                               {
+                                       i_ConvertCJCCalibration = 0;
+                               }       //if(i_CJCGain==i_ADDIDATAGain)
+                               else {
+                                       i_ConvertCJCCalibration = 1;
+                               }       //elseif(i_CJCGain==i_ADDIDATAGain)
+                       }       //elseif(i_CJCPolarity!=i_ADDIDATAPolarity)
+                       if (i_ConvertCJCCalibration == 1) {
+                               i_APCI3200_ReadCJCCalOffset(dev,
+                                       &ui_DummyValue);
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //ui_InterruptChannelValue[i_Count+4]=ui_DummyValue;
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 4] =
+                                       ui_DummyValue;
+                               //END JK 06.07.04: Management of sevrals boards
+
+                               i_APCI3200_ReadCJCCalGain(dev, &ui_DummyValue);
+
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //ui_InterruptChannelValue[i_Count+5]=ui_DummyValue;
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 5] =
+                                       ui_DummyValue;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(i_ConvertCJCCalibration==1)
+                       else {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //ui_InterruptChannelValue[i_Count+4]=0;
+                               //ui_InterruptChannelValue[i_Count+5]=0;
+
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 4] = 0;
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 5] = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //elseif(i_ConvertCJCCalibration==1)
+               }               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE))
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if(i_ScanType!=1)
+               if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+                       //i_Count=0;
+                       s_BoardInfos[dev->minor].i_Count = 0;
+               }               //if(i_ScanType!=1)
+               else {
+                       //i_Count=i_Count +6;
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6;
+                       s_BoardInfos[dev->minor].i_Count =
+                               s_BoardInfos[dev->minor].i_Count + 9;
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               }               //else if(i_ScanType!=1)
+
+               //if((i_ScanType==1) &&(i_InterruptFlag==1))
+               if ((s_BoardInfos[dev->minor].i_ScanType == 1)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == 1)) {
+                       //i_Count=i_Count-6;
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6;
+                       s_BoardInfos[dev->minor].i_Count =
+                               s_BoardInfos[dev->minor].i_Count - 9;
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               }
+               //if(i_ScanType==0)
+               if (s_BoardInfos[dev->minor].i_ScanType == 0) {
+                       /*
+                          data[0]= ui_InterruptChannelValue[0];
+                          data[1]= ui_InterruptChannelValue[1];
+                          data[2]= ui_InterruptChannelValue[2];
+                          data[3]= ui_InterruptChannelValue[3];
+                          data[4]= ui_InterruptChannelValue[4];
+                          data[5]= ui_InterruptChannelValue[5];
+                        */
+#ifdef PRINT_INFO
+                       printk("\n data[0]= s_BoardInfos [dev->minor].ui_InterruptChannelValue[0];");
+#endif
+                       data[0] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[0];
+                       data[1] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[1];
+                       data[2] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[2];
+                       data[3] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[3];
+                       data[4] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[4];
+                       data[5] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[5];
+
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       //printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]);
+                       i_APCI3200_GetChannelCalibrationValue(dev,
+                               s_BoardInfos[dev->minor].ui_Channel_num,
+                               &data[6], &data[7], &data[8]);
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               }
+               break;
+       case 1:
+
+               for (i = 0; i < insn->n; i++) {
+                       //data[i]=ui_InterruptChannelValue[i];
+                       data[i] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[i];
+               }
+
+               //i_Count=0;
+               //i_Sum=0;
+               //if(i_ScanType==1)
+               s_BoardInfos[dev->minor].i_Count = 0;
+               s_BoardInfos[dev->minor].i_Sum = 0;
+               if (s_BoardInfos[dev->minor].i_ScanType == 1) {
+                       //i_Initialised=0;
+                       //i_InterruptFlag=0;
+                       s_BoardInfos[dev->minor].i_Initialised = 0;
+                       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+                       //END JK 06.07.04: Management of sevrals boards
+               }
+               break;
+       default:
+               printk("\nThe parameters passed are in error\n");
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //switch(insn->unused[0])
+
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_Read1AnalogInputChannel                 |
+  |                              (comedi_device *dev,comedi_subdevice *s,       |
+  |                     comedi_insn *insn,lsampl_t *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel                            |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT ui_NoOfChannel    : Channel No to read            |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                              data[0]  : Digital Value read                   |
+  |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+INT i_APCI3200_Read1AnalogInputChannel(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_EOC = 0;
+       UINT ui_ChannelNo = 0;
+       UINT ui_CommandRegister = 0;
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //ui_ChannelNo=i_ChannelNo;
+       ui_ChannelNo = s_BoardInfos[dev->minor].i_ChannelNo;
+
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //Begin JK 20.10.2004: Bad channel value is used when using differential mode
+       //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+       //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+       outl(0 | s_BoardInfos[dev->minor].i_ChannelNo,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+       //End JK 20.10.2004: Bad channel value is used when using differential mode
+
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+
+  /**************************************************************************/
+       /* Set the start end stop index to the selected channel and set the start */
+  /**************************************************************************/
+
+       ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000;
+
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /************************/
+               /* Enable the interrupt */
+      /************************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+       }                       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+
+  /******************************/
+       /* Write the command register */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+         /*************************/
+                       /*Read the EOC Status bit */
+         /*************************/
+
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /***************************************/
+               /* Read the digital value of the input */
+      /***************************************/
+
+               //data[0] = inl (devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+               //END JK 06.07.04: Management of sevrals boards
+
+       }                       // if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCalibrationOffsetValue              |
+  |                              (comedi_device *dev,comedi_subdevice *s,       |
+  |                     comedi_insn *insn,lsampl_t *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read calibration offset  value  of the selected channel|
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                              data[0]  : Calibration offset Value   |
+  |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+int i_APCI3200_ReadCalibrationOffsetValue(comedi_device * dev, UINT * data)
+{
+       UINT ui_Temp = 0, ui_EOC = 0;
+       UINT ui_CommandRegister = 0;
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //Begin JK 20.10.2004: This seems not necessary !
+       //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+       //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+       //End JK 20.10.2004: This seems not necessary !
+
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /*****************************/
+       /*Read the calibration offset */
+  /*****************************/
+       //ui_Temp = inl(devpriv->iobase+i_Offset + 12);
+       ui_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+
+  /*********************************/
+       /*Configure the Offset Conversion */
+  /*********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12);
+       outl((ui_Temp | 0x00020000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+  /*******************************/
+       /*Initialise ui_CommandRegister */
+  /*******************************/
+
+       ui_CommandRegister = 0;
+
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+
+       }                       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+
+               do {
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+
+                       //ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /**************************************************/
+               /*Read the digital value of the calibration Offset */
+      /**************************************************/
+
+               //data[0] = inl(devpriv->iobase+i_Offset+ 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCalibrationGainValue                |
+  |                              (comedi_device *dev,comedi_subdevice *s,       |
+  |                     comedi_insn *insn,lsampl_t *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read calibration gain  value  of the selected channel  |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                              data[0]  : Calibration gain Value Of Input     |
+  |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+int i_APCI3200_ReadCalibrationGainValue(comedi_device * dev, UINT * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //Begin JK 20.10.2004: This seems not necessary !
+       //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+       //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+       //End JK 20.10.2004: This seems not necessary !
+
+  /***************************/
+       /*Read the calibration gain */
+  /***************************/
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /*******************************/
+       /*Configure the Gain Conversion */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00040000 , devpriv->iobase+i_Offset + 12);
+       outl(0x00040000,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+
+  /*******************************/
+       /*Initialise ui_CommandRegister */
+  /*******************************/
+
+       ui_CommandRegister = 0;
+
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+
+       }                       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+
+               do {
+
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /************************************************/
+               /*Read the digital value of the calibration Gain */
+      /************************************************/
+
+               //data[0] = inl(devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCJCValue                            |
+  |                              (comedi_device *dev,comedi_subdevice *s,       |
+  |                     comedi_insn *insn,lsampl_t *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read CJC  value  of the selected channel               |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                              data[0]  : CJC Value                           |
+  |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_ReadCJCValue(comedi_device * dev, lsampl_t * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+
+  /******************************/
+       /*Set the converting time unit */
+  /******************************/
+
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+
+  /******************************/
+       /*Configure the CJC Conversion */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl( 0x00000400 , devpriv->iobase+i_Offset + 4);
+       outl(0x00000400,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************************/
+       /*Initialise dw_CommandRegister */
+  /*******************************/
+       ui_CommandRegister = 0;
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+       }
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /***********************************/
+               /*Read the digital value of the CJC */
+      /***********************************/
+
+               //data[0] = inl(devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCJCCalOffset                        |
+  |                              (comedi_device *dev,comedi_subdevice *s,       |
+  |                     comedi_insn *insn,lsampl_t *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read CJC calibration offset  value  of the selected channel
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                              data[0]  : CJC calibration offset Value
+  |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, lsampl_t * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+  /*******************************************/
+       /*Read calibration offset value for the CJC */
+  /*******************************************/
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /******************************/
+       /*Configure the CJC Conversion */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00000400 , devpriv->iobase+i_Offset + 4);
+       outl(0x00000400,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*********************************/
+       /*Configure the Offset Conversion */
+  /*********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00020000, devpriv->iobase+i_Offset + 12);
+       outl(0x00020000,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+  /*******************************/
+       /*Initialise ui_CommandRegister */
+  /*******************************/
+       ui_CommandRegister = 0;
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+
+       }
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+               } while (ui_EOC != 1);
+
+      /**************************************************/
+               /*Read the digital value of the calibration Offset */
+      /**************************************************/
+               //data[0] = inl(devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCJCGainValue                        |
+  |                              (comedi_device *dev,comedi_subdevice *s,       |
+  |                     comedi_insn *insn,lsampl_t *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read CJC calibration gain value
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                              data[0]  : CJC calibration gain value
+  |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+int i_APCI3200_ReadCJCCalGain(comedi_device * dev, lsampl_t * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /******************************/
+       /*Configure the CJC Conversion */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00000400,devpriv->iobase+i_Offset + 4);
+       outl(0x00000400,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************************/
+       /*Configure the Gain Conversion */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00040000,devpriv->iobase+i_Offset + 12);
+       outl(0x00040000,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+
+  /*******************************/
+       /*Initialise dw_CommandRegister */
+  /*******************************/
+       ui_CommandRegister = 0;
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+       }
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+               } while (ui_EOC != 1);
+      /************************************************/
+               /*Read the digital value of the calibration Gain */
+      /************************************************/
+               //data[0] = inl (devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_InsnBits_AnalogInput_Test               |
+  |                      (comedi_device *dev,comedi_subdevice *s,               |
+  |                      comedi_insn *insn,lsampl_t *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Tests the Selected Anlog Input Channel                 |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     comedi_subdevice *s     : Subdevice Pointer            |
+  |                     comedi_insn *insn       : Insn Structure Pointer       |
+  |                     lsampl_t *data          : Data Pointer contains        |
+  |                                          configuration parameters as below |
+  |
+  |
+  |                           data[0]            : 0 TestAnalogInputShortCircuit
+  |                                                                         1 TestAnalogInputConnection                                                                                                                                                                                                |
+
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                            data[0]            : Digital value obtained      |
+  |                           data[1]            : calibration offset          |
+  |                           data[2]            : calibration gain            |
+  |                                                                             |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+
+INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Configuration = 0;
+       INT i_Temp;             //,i_TimeUnit;
+       //if(i_Initialised==0)
+
+       if (s_BoardInfos[dev->minor].i_Initialised == 0) {
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //if(i_Initialised==0);
+       if (data[0] != 0 && data[0] != 1) {
+               printk("\nError in selection of functionality\n");
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //if(data[0]!=0 && data[0]!=1)
+
+       if (data[0] == 1)       //Perform Short Circuit TEST
+       {
+      /**************************/
+               /*Set the short-cicuit bit */
+      /**************************/
+               //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+               while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                               i_Offset + 12) >> 19) & 1) !=
+                       1) ;
+               //outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+               outl((0x00001000 | s_BoardInfos[dev->minor].i_ChannelNo),
+                       devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                       4);
+      /*************************/
+               /*Set the time unit to ns */
+      /*************************/
+               /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+                  i_ADDIDATAConversionTimeUnit= 1; */
+               //i_Temp= i_InterruptFlag ;
+               i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
+               //i_InterruptFlag = ADDIDATA_DISABLE;
+               s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+               i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
+               //if(i_AutoCalibration == FALSE)
+               if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
+                       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+                       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                                       i_Offset +
+                                                       12) >> 19) & 1) != 1) ;
+
+                       //outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+                       outl((0x00001000 | s_BoardInfos[dev->minor].
+                                       i_ChannelNo),
+                               devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 4);
+                       data++;
+                       i_APCI3200_ReadCalibrationOffsetValue(dev, data);
+                       data++;
+                       i_APCI3200_ReadCalibrationGainValue(dev, data);
+               }
+       } else {
+               //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+               while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                               i_Offset + 12) >> 19) & 1) !=
+                       1) ;
+               //outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+               outl((0x00000800 | s_BoardInfos[dev->minor].i_ChannelNo),
+                       devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                       4);
+               //ui_Configuration = inl(devpriv->iobase+i_Offset + 0);
+               ui_Configuration =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 0);
+      /*************************/
+               /*Set the time unit to ns */
+      /*************************/
+               /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+                  i_ADDIDATAConversionTimeUnit= 1; */
+               //i_Temp= i_InterruptFlag ;
+               i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
+               //i_InterruptFlag = ADDIDATA_DISABLE;
+               s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+               i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
+               //if(i_AutoCalibration == FALSE)
+               if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
+                       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+                       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                                       i_Offset +
+                                                       12) >> 19) & 1) != 1) ;
+                       //outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+                       outl((0x00000800 | s_BoardInfos[dev->minor].
+                                       i_ChannelNo),
+                               devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 4);
+                       data++;
+                       i_APCI3200_ReadCalibrationOffsetValue(dev, data);
+                       data++;
+                       i_APCI3200_ReadCalibrationGainValue(dev, data);
+               }
+       }
+       //i_InterruptFlag=i_Temp ;
+       s_BoardInfos[dev->minor].i_InterruptFlag = i_Temp;
+       //printk("\ni_InterruptFlag=%d\n",i_InterruptFlag);
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_InsnWriteReleaseAnalogInput             |
+  |                      (comedi_device *dev,comedi_subdevice *s,               |
+  |                      comedi_insn *insn,lsampl_t *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              :  Resets the channels                                                      |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev      : Driver handle                |
+  |                     comedi_subdevice *s     : Subdevice Pointer            |
+  |                     comedi_insn *insn       : Insn Structure Pointer       |
+  |                     lsampl_t *data          : Data Pointer
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+
+INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       i_APCI3200_Reset(dev);
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     :int i_APCI3200_CommandTestAnalogInput(comedi_device *dev|
+  |                    ,comedi_subdevice *s,comedi_cmd *cmd)                            |
+  |                                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              : Test validity for a command for cyclic anlog input     |
+  |                       acquisition                                                                           |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev                                                                      |
+  |                     comedi_subdevice *s                                                                     |
+  |                     comedi_cmd *cmd                                                         |
+  |                                                                                                                     |
+  |
+  |                                                                                                                     |
+  |                                                                                                                     |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Return Value      :0                                                                    |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_cmd * cmd)
+{
+
+       int err = 0;
+       int tmp;                // divisor1,divisor2;
+       UINT ui_ConvertTime = 0;
+       UINT ui_ConvertTimeBase = 0;
+       UINT ui_DelayTime = 0;
+       UINT ui_DelayTimeBase = 0;
+       INT i_Triggermode = 0;
+       INT i_TriggerEdge = 0;
+       INT i_NbrOfChannel = 0;
+       INT i_Cpt = 0;
+       double d_ConversionTimeForAllChannels = 0.0;
+       double d_SCANTimeNewUnit = 0.0;
+       // step 1: make sure trigger sources are trivially valid
+
+       tmp = cmd->start_src;
+       cmd->start_src &= TRIG_NOW | TRIG_EXT;
+       if (!cmd->start_src || tmp != cmd->start_src)
+               err++;
+       tmp = cmd->scan_begin_src;
+       cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
+       if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+               err++;
+       tmp = cmd->convert_src;
+       cmd->convert_src &= TRIG_TIMER;
+       if (!cmd->convert_src || tmp != cmd->convert_src)
+               err++;
+       tmp = cmd->scan_end_src;
+       cmd->scan_end_src &= TRIG_COUNT;
+       if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+               err++;
+       tmp = cmd->stop_src;
+       cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+       if (!cmd->stop_src || tmp != cmd->stop_src)
+               err++;
+       //if(i_InterruptFlag==0)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
+               err++;
+               //          printk("\nThe interrupt should be enabled\n");
+       }
+       if (err) {
+               i_APCI3200_Reset(dev);
+               return 1;
+       }
+
+       if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
+               err++;
+       }
+       if (cmd->start_src == TRIG_EXT) {
+               i_TriggerEdge = cmd->start_arg & 0xFFFF;
+               i_Triggermode = cmd->start_arg >> 16;
+               if (i_TriggerEdge < 1 || i_TriggerEdge > 3) {
+                       err++;
+                       printk("\nThe trigger edge selection is in error\n");
+               }
+               if (i_Triggermode != 2) {
+                       err++;
+                       printk("\nThe trigger mode selection is in error\n");
+               }
+       }
+
+       if (cmd->scan_begin_src != TRIG_TIMER &&
+               cmd->scan_begin_src != TRIG_FOLLOW)
+               err++;
+
+       if (cmd->convert_src != TRIG_TIMER)
+               err++;
+
+       if (cmd->scan_end_src != TRIG_COUNT) {
+               cmd->scan_end_src = TRIG_COUNT;
+               err++;
+       }
+
+       if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
+               err++;
+
+       if (err) {
+               i_APCI3200_Reset(dev);
+               return 2;
+       }
+       //i_FirstChannel=cmd->chanlist[0];
+       s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
+       //i_LastChannel=cmd->chanlist[1];
+       s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
+
+       if (cmd->convert_src == TRIG_TIMER) {
+               ui_ConvertTime = cmd->convert_arg & 0xFFFF;
+               ui_ConvertTimeBase = cmd->convert_arg >> 16;
+               if (ui_ConvertTime != 20 && ui_ConvertTime != 40
+                       && ui_ConvertTime != 80 && ui_ConvertTime != 160)
+               {
+                       printk("\nThe selection of conversion time reload value is in error\n");
+                       err++;
+               }               // if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 )
+               if (ui_ConvertTimeBase != 2) {
+                       printk("\nThe selection of conversion time unit  is in error\n");
+                       err++;
+               }               //if(ui_ConvertTimeBase!=2)
+       } else {
+               ui_ConvertTime = 0;
+               ui_ConvertTimeBase = 0;
+       }
+       if (cmd->scan_begin_src == TRIG_FOLLOW) {
+               ui_DelayTime = 0;
+               ui_DelayTimeBase = 0;
+       }                       //if(cmd->scan_begin_src==TRIG_FOLLOW)
+       else {
+               ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
+               ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
+               if (ui_DelayTimeBase != 2 && ui_DelayTimeBase != 3) {
+                       err++;
+                       printk("\nThe Delay time base selection is in error\n");
+               }
+               if (ui_DelayTime < 1 && ui_DelayTime > 1023) {
+                       err++;
+                       printk("\nThe Delay time value is in error\n");
+               }
+               if (err) {
+                       i_APCI3200_Reset(dev);
+                       return 3;
+               }
+               fpu_begin();
+               d_SCANTimeNewUnit = (double)ui_DelayTime;
+               //i_NbrOfChannel= i_LastChannel-i_FirstChannel + 4;
+               i_NbrOfChannel =
+                       s_BoardInfos[dev->minor].i_LastChannel -
+                       s_BoardInfos[dev->minor].i_FirstChannel + 4;
+      /**********************************************************/
+               /*calculate the total conversion time for all the channels */
+      /**********************************************************/
+               d_ConversionTimeForAllChannels =
+                       (double)((double)ui_ConvertTime /
+                       (double)i_NbrOfChannel);
+
+      /*******************************/
+               /*Convert the frequence in time */
+      /*******************************/
+               d_ConversionTimeForAllChannels =
+                       (double)1.0 / d_ConversionTimeForAllChannels;
+               ui_ConvertTimeBase = 3;
+      /***********************************/
+               /*Test if the time unit is the same */
+      /***********************************/
+
+               if (ui_DelayTimeBase <= ui_ConvertTimeBase) {
+
+                       for (i_Cpt = 0;
+                               i_Cpt < (ui_ConvertTimeBase - ui_DelayTimeBase);
+                               i_Cpt++) {
+
+                               d_ConversionTimeForAllChannels =
+                                       d_ConversionTimeForAllChannels * 1000;
+                               d_ConversionTimeForAllChannels =
+                                       d_ConversionTimeForAllChannels + 1;
+                       }
+               } else {
+                       for (i_Cpt = 0;
+                               i_Cpt < (ui_DelayTimeBase - ui_ConvertTimeBase);
+                               i_Cpt++) {
+                               d_SCANTimeNewUnit = d_SCANTimeNewUnit * 1000;
+
+                       }
+               }
+
+               if (d_ConversionTimeForAllChannels >= d_SCANTimeNewUnit) {
+
+                       printk("\nSCAN Delay value cannot be used\n");
+         /*********************************/
+                       /*SCAN Delay value cannot be used */
+         /*********************************/
+                       err++;
+               }
+               fpu_end();
+       }                       //else if(cmd->scan_begin_src==TRIG_FOLLOW)
+
+       if (err) {
+               i_APCI3200_Reset(dev);
+               return 4;
+       }
+
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     :int i_APCI3200_StopCyclicAcquisition(comedi_device *dev,|
+  |                                                                                         comedi_subdevice *s)|
+  |                                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              : Stop the  acquisition                                                       |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev                                                                      |
+  |                     comedi_subdevice *s                                                                     |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Return Value      :0                                                                    |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s)
+{
+       UINT ui_Configuration = 0;
+       //i_InterruptFlag=0;
+       //i_Initialised=0;
+       //i_Count=0;
+       //i_Sum=0;
+       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+       s_BoardInfos[dev->minor].i_Initialised = 0;
+       s_BoardInfos[dev->minor].i_Count = 0;
+       s_BoardInfos[dev->minor].i_Sum = 0;
+
+  /*******************/
+       /*Read the register */
+  /*******************/
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 8);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+  /*****************************/
+       /*Reset the START and IRQ bit */
+  /*****************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+i_Offset + 8);
+       outl((ui_Configuration & 0xFFE7FFFF),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     : int i_APCI3200_CommandAnalogInput(comedi_device *dev,  |
+  |                                                                                            comedi_subdevice *s) |
+  |                                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              : Does asynchronous acquisition                          |
+  |                     Determines the mode 1 or 2.                                                 |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev                                                                      |
+  |                     comedi_subdevice *s                                                                     |
+  |                                                                                                                                     |
+  |                                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Return Value      :                                                                         |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s)
+{
+       comedi_cmd *cmd = &s->async->cmd;
+       UINT ui_Configuration = 0;
+       //INT  i_CurrentSource = 0;
+       UINT ui_Trigger = 0;
+       UINT ui_TriggerEdge = 0;
+       UINT ui_Triggermode = 0;
+       UINT ui_ScanMode = 0;
+       UINT ui_ConvertTime = 0;
+       UINT ui_ConvertTimeBase = 0;
+       UINT ui_DelayTime = 0;
+       UINT ui_DelayTimeBase = 0;
+       UINT ui_DelayMode = 0;
+       //i_FirstChannel=cmd->chanlist[0];
+       //i_LastChannel=cmd->chanlist[1];
+       s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
+       s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
+       if (cmd->start_src == TRIG_EXT) {
+               ui_Trigger = 1;
+               ui_TriggerEdge = cmd->start_arg & 0xFFFF;
+               ui_Triggermode = cmd->start_arg >> 16;
+       }                       //if(cmd->start_src==TRIG_EXT)
+       else {
+               ui_Trigger = 0;
+       }                       //elseif(cmd->start_src==TRIG_EXT)
+
+       if (cmd->stop_src == TRIG_COUNT) {
+               ui_ScanMode = 0;
+       }                       // if (cmd->stop_src==TRIG_COUNT)
+       else {
+               ui_ScanMode = 2;
+       }                       //else if (cmd->stop_src==TRIG_COUNT)
+
+       if (cmd->scan_begin_src == TRIG_FOLLOW) {
+               ui_DelayTime = 0;
+               ui_DelayTimeBase = 0;
+               ui_DelayMode = 0;
+       }                       //if(cmd->scan_begin_src==TRIG_FOLLOW)
+       else {
+               ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
+               ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
+               ui_DelayMode = 1;
+       }                       //else if(cmd->scan_begin_src==TRIG_FOLLOW)
+       //        printk("\nui_DelayTime=%u\n",ui_DelayTime);
+       //        printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase);
+       if (cmd->convert_src == TRIG_TIMER) {
+               ui_ConvertTime = cmd->convert_arg & 0xFFFF;
+               ui_ConvertTimeBase = cmd->convert_arg >> 16;
+       } else {
+               ui_ConvertTime = 0;
+               ui_ConvertTimeBase = 0;
+       }
+
+       // if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2)))
+       //   {
+  /**************************************************/
+       /*Read the old configuration of the current source */
+  /**************************************************/
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 12);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+  /***********************************************/
+       /*Write the configuration of the current source */
+  /***********************************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+i_Offset +12);
+       outl((ui_Configuration & 0xFFC00000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+       // }
+       ui_Configuration = 0;
+       //     printk("\nfirstchannel=%u\n",i_FirstChannel);
+       //     printk("\nlastchannel=%u\n",i_LastChannel);
+       //     printk("\nui_Trigger=%u\n",ui_Trigger);
+       //     printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge);
+       //     printk("\nui_Triggermode=%u\n",ui_Triggermode);
+       //      printk("\nui_DelayMode=%u\n",ui_DelayMode);
+       //     printk("\nui_ScanMode=%u\n",ui_ScanMode);
+
+       //ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 |
+       ui_Configuration =
+               s_BoardInfos[dev->minor].i_FirstChannel | (s_BoardInfos[dev->
+                       minor].
+               i_LastChannel << 8) | 0x00100000 | (ui_Trigger << 24) |
+               (ui_TriggerEdge << 25) | (ui_Triggermode << 27) | (ui_DelayMode
+               << 18) | (ui_ScanMode << 16);
+
+  /*************************/
+       /*Write the Configuration */
+  /*************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8);
+       outl(ui_Configuration,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x8);
+  /***********************/
+       /*Write the Delay Value */
+  /***********************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_DelayTime,devpriv->iobase+i_Offset + 40);
+       outl(ui_DelayTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 40);
+  /***************************/
+       /*Write the Delay time base */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44);
+       outl(ui_DelayTimeBase,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 44);
+  /*********************************/
+       /*Write the conversion time value */
+  /*********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32);
+       outl(ui_ConvertTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+
+  /********************************/
+       /*Write the conversion time base */
+  /********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36);
+       outl(ui_ConvertTimeBase,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /*******************/
+       /*Read the register */
+  /*******************/
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 4);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /******************/
+       /*Set the SCAN bit */
+  /******************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4);
+       outl(((ui_Configuration & 0x1E0FF) | 0x00002000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************/
+       /*Read the register */
+  /*******************/
+       ui_Configuration = 0;
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 8);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*******************/
+       /*Set the START bit */
+  /*******************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8);
+       outl((ui_Configuration | 0x00080000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   :  int i_APCI3200_Reset(comedi_device *dev)                           |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              :Resets the registers of the card                        |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  :                                                        |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      :                                                        |
+  |                                                                                     |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_Reset(comedi_device * dev)
+{
+       INT i_Temp;
+       DWORD dw_Dummy;
+       //i_InterruptFlag=0;
+       //i_Initialised==0;
+       //i_Count=0;
+       //i_Sum=0;
+
+       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+       s_BoardInfos[dev->minor].i_Initialised = 0;
+       s_BoardInfos[dev->minor].i_Count = 0;
+       s_BoardInfos[dev->minor].i_Sum = 0;
+       s_BoardInfos[dev->minor].b_StructInitialized = 0;
+
+       outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
+
+       // Enable the interrupt for the controler
+       dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
+       outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
+       outl(0, devpriv->i_IobaseAddon);        //Resets the output
+  /***************/
+       /*Empty the buffer */
+  /**************/
+       for (i_Temp = 0; i_Temp <= 95; i_Temp++) {
+               //ui_InterruptChannelValue[i_Temp]=0;
+               s_BoardInfos[dev->minor].ui_InterruptChannelValue[i_Temp] = 0;
+       }                       //for(i_Temp=0;i_Temp<=95;i_Temp++)
+  /*****************************/
+       /*Reset the START and IRQ bit */
+  /*****************************/
+       for (i_Temp = 0; i_Temp <= 192;) {
+               while (((inl(devpriv->iobase + i_Temp + 12) >> 19) & 1) != 1) ;
+               outl(0, devpriv->iobase + i_Temp + 8);
+               i_Temp = i_Temp + 64;
+       }                       //for(i_Temp=0;i_Temp<=192;i_Temp+64)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : static void v_APCI3200_Interrupt                                            |
+  |                                      (int irq , void *d)                            |
+  +----------------------------------------------------------------------------+
+  | Task              : Interrupt processing Routine                           |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : int irq                 : irq number                   |
+  |                     void *d                 : void pointer                 |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error                                      |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+void v_APCI3200_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+       UINT ui_StatusRegister = 0;
+       UINT ui_ChannelNumber = 0;
+       INT i_CalibrationFlag = 0;
+       INT i_CJCFlag = 0;
+       UINT ui_DummyValue = 0;
+       UINT ui_DigitalTemperature = 0;
+       UINT ui_DigitalInput = 0;
+       int i_ConvertCJCCalibration;
+
+       //BEGIN JK TEST
+       int i_ReturnValue = 0;
+       //END JK TEST
+
+       //printk ("\n i_ScanType = %i i_ADDIDATAType = %i", s_BoardInfos [dev->minor].i_ScanType, s_BoardInfos [dev->minor].i_ADDIDATAType);
+
+       //switch(i_ScanType)
+       switch (s_BoardInfos[dev->minor].i_ScanType) {
+       case 0:
+       case 1:
+               //switch(i_ADDIDATAType)
+               switch (s_BoardInfos[dev->minor].i_ADDIDATAType) {
+               case 0:
+               case 1:
+
+         /************************************/
+                       /*Read the interrupt status register */
+         /************************************/
+                       //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+                       ui_StatusRegister =
+                               inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 16);
+                       if ((ui_StatusRegister & 0x2) == 0x2) {
+                               //i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17);
+                               i_CalibrationFlag =
+                                       ((inl(devpriv->iobase +
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_Offset +
+                                                       12) & 0x00060000) >>
+                                       17);
+             /*************************/
+                               /*Read the channel number */
+             /*************************/
+                               //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+
+             /*************************************/
+                               /*Read the digital analog input value */
+             /*************************************/
+                               //ui_DigitalInput = inl(devpriv->iobase+i_Offset + 28);
+                               ui_DigitalInput =
+                                       inl(devpriv->iobase +
+                                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+             /***********************************************/
+                               /* Test if the value read is the channel value */
+             /***********************************************/
+                               if (i_CalibrationFlag == 0) {
+                                       //ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 0] = ui_DigitalInput;
+
+                                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                       /*
+                                          printk("\n 1 - i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos %i", ui_ChannelNumber);
+                                          i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos [dev->minor].ui_Channel_num,
+                                          &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 6],
+                                          &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 7],
+                                          &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 8]);
+                                        */
+                                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+                 /******************************************************/
+                                       /*Start the conversion of the calibration offset value */
+                 /******************************************************/
+                                       i_APCI3200_ReadCalibrationOffsetValue
+                                               (dev, &ui_DummyValue);
+                               }       //if (i_CalibrationFlag == 0)
+             /**********************************************************/
+                               /* Test if the value read is the calibration offset value */
+             /**********************************************************/
+
+                               if (i_CalibrationFlag == 1) {
+
+                 /******************/
+                                       /* Save the value */
+                 /******************/
+
+                                       //ui_InterruptChannelValue[i_Count + 1] = ui_DigitalInput;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 1] = ui_DigitalInput;
+
+                 /******************************************************/
+                                       /* Start the conversion of the calibration gain value */
+                 /******************************************************/
+                                       i_APCI3200_ReadCalibrationGainValue(dev,
+                                               &ui_DummyValue);
+                               }       //if (i_CalibrationFlag == 1)
+             /******************************************************/
+                               /*Test if the value read is the calibration gain value */
+             /******************************************************/
+
+                               if (i_CalibrationFlag == 2) {
+
+                 /****************/
+                                       /*Save the value */
+                 /****************/
+                                       //ui_InterruptChannelValue[i_Count + 2] = ui_DigitalInput;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 2] = ui_DigitalInput;
+                                       //if(i_ScanType==1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType == 1) {
+
+                                               //i_InterruptFlag=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_InterruptFlag = 0;
+                                               //i_Count=i_Count + 6;
+                                               //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                               //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count =
+                                                       s_BoardInfos[dev->
+                                                       minor].i_Count + 9;
+                                               //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                       }       //if(i_ScanType==1)
+                                       else {
+                                               //i_Count=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count = 0;
+                                       }       //elseif(i_ScanType==1)
+                                       //if(i_ScanType!=1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType != 1) {
+                                               i_ReturnValue = send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+                                       }       //if(i_ScanType!=1)
+                                       else {
+                                               //if(i_ChannelCount==i_Sum)
+                                               if (s_BoardInfos[dev->minor].
+                                                       i_ChannelCount ==
+                                                       s_BoardInfos[dev->
+                                                               minor].i_Sum) {
+                                                       send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+                                               }
+                                       }       //if(i_ScanType!=1)
+                               }       //if (i_CalibrationFlag == 2)
+                       }       // if ((ui_StatusRegister & 0x2) == 0x2)
+
+                       break;
+
+               case 2:
+         /************************************/
+                       /*Read the interrupt status register */
+         /************************************/
+
+                       //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+                       ui_StatusRegister =
+                               inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 16);
+         /*************************/
+                       /*Test if interrupt occur */
+         /*************************/
+
+                       if ((ui_StatusRegister & 0x2) == 0x2) {
+
+                               //i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10);
+                               i_CJCFlag =
+                                       ((inl(devpriv->iobase +
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_Offset +
+                                                       4) & 0x00000400) >> 10);
+
+                               //i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17);
+                               i_CalibrationFlag =
+                                       ((inl(devpriv->iobase +
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_Offset +
+                                                       12) & 0x00060000) >>
+                                       17);
+
+             /*************************/
+                               /*Read the channel number */
+             /*************************/
+
+                               //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+                               ui_ChannelNumber =
+                                       inl(devpriv->iobase +
+                                       s_BoardInfos[dev->minor].i_Offset + 24);
+                               //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                               s_BoardInfos[dev->minor].ui_Channel_num =
+                                       ui_ChannelNumber;
+                               //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+             /************************************/
+                               /*Read the digital temperature value */
+             /************************************/
+                               //ui_DigitalTemperature = inl(devpriv->iobase+i_Offset + 28);
+                               ui_DigitalTemperature =
+                                       inl(devpriv->iobase +
+                                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+             /*********************************************/
+                               /*Test if the value read is the channel value */
+             /*********************************************/
+
+                               if ((i_CalibrationFlag == 0)
+                                       && (i_CJCFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 0]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 0] =
+                                               ui_DigitalTemperature;
+
+                 /*********************************/
+                                       /*Start the conversion of the CJC */
+                 /*********************************/
+                                       i_APCI3200_ReadCJCValue(dev,
+                                               &ui_DummyValue);
+
+                               }       //if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0))
+
+                /*****************************************/
+                               /*Test if the value read is the CJC value */
+                /*****************************************/
+
+                               if ((i_CJCFlag == 1)
+                                       && (i_CalibrationFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 3]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 3] =
+                                               ui_DigitalTemperature;
+
+                 /******************************************************/
+                                       /*Start the conversion of the calibration offset value */
+                 /******************************************************/
+                                       i_APCI3200_ReadCalibrationOffsetValue
+                                               (dev, &ui_DummyValue);
+                               }       // if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0))
+
+                /********************************************************/
+                               /*Test if the value read is the calibration offset value */
+                /********************************************************/
+
+                               if ((i_CalibrationFlag == 1)
+                                       && (i_CJCFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 1]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 1] =
+                                               ui_DigitalTemperature;
+
+                 /****************************************************/
+                                       /*Start the conversion of the calibration gain value */
+                 /****************************************************/
+                                       i_APCI3200_ReadCalibrationGainValue(dev,
+                                               &ui_DummyValue);
+
+                               }       //if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0))
+
+             /******************************************************/
+                               /*Test if the value read is the calibration gain value */
+             /******************************************************/
+
+                               if ((i_CalibrationFlag == 2)
+                                       && (i_CJCFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 2]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 2] =
+                                               ui_DigitalTemperature;
+
+                 /**********************************************************/
+                                       /*Test if the Calibration channel must be read for the CJC */
+                 /**********************************************************/
+
+                                       /*Test if the polarity is the same */
+                 /**********************************/
+                                       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_CJCPolarity !=
+                                               s_BoardInfos[dev->minor].
+                                               i_ADDIDATAPolarity) {
+                                               i_ConvertCJCCalibration = 1;
+                                       }       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                                       else {
+                                               //if(i_CJCGain==i_ADDIDATAGain)
+                                               if (s_BoardInfos[dev->minor].
+                                                       i_CJCGain ==
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_ADDIDATAGain) {
+                                                       i_ConvertCJCCalibration
+                                                               = 0;
+                                               }       //if(i_CJCGain==i_ADDIDATAGain)
+                                               else {
+                                                       i_ConvertCJCCalibration
+                                                               = 1;
+                                               }       //elseif(i_CJCGain==i_ADDIDATAGain)
+                                       }       //elseif(i_CJCPolarity!=i_ADDIDATAPolarity)
+                                       if (i_ConvertCJCCalibration == 1) {
+                     /****************************************************************/
+                                               /*Start the conversion of the calibration gain value for the CJC */
+                     /****************************************************************/
+                                               i_APCI3200_ReadCJCCalOffset(dev,
+                                                       &ui_DummyValue);
+
+                                       }       //if(i_ConvertCJCCalibration==1)
+                                       else {
+                                               //ui_InterruptChannelValue[i_Count + 4]=0;
+                                               //ui_InterruptChannelValue[i_Count + 5]=0;
+                                               s_BoardInfos[dev->minor].
+                                                       ui_InterruptChannelValue
+                                                       [s_BoardInfos[dev->
+                                                               minor].i_Count +
+                                                       4] = 0;
+                                               s_BoardInfos[dev->minor].
+                                                       ui_InterruptChannelValue
+                                                       [s_BoardInfos[dev->
+                                                               minor].i_Count +
+                                                       5] = 0;
+                                       }       //elseif(i_ConvertCJCCalibration==1)
+                               }       //else if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0))
+
+                /********************************************************************/
+                               /*Test if the value read is the calibration offset value for the CJC */
+                /********************************************************************/
+
+                               if ((i_CalibrationFlag == 1)
+                                       && (i_CJCFlag == 1)) {
+                                       //ui_InterruptChannelValue[i_Count + 4]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 4] =
+                                               ui_DigitalTemperature;
+
+                 /****************************************************************/
+                                       /*Start the conversion of the calibration gain value for the CJC */
+                 /****************************************************************/
+                                       i_APCI3200_ReadCJCCalGain(dev,
+                                               &ui_DummyValue);
+
+                               }       //if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1))
+
+             /******************************************************************/
+                               /*Test if the value read is the calibration gain value for the CJC */
+             /******************************************************************/
+
+                               if ((i_CalibrationFlag == 2)
+                                       && (i_CJCFlag == 1)) {
+                                       //ui_InterruptChannelValue[i_Count + 5]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 5] =
+                                               ui_DigitalTemperature;
+
+                                       //if(i_ScanType==1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType == 1) {
+
+                                               //i_InterruptFlag=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_InterruptFlag = 0;
+                                               //i_Count=i_Count + 6;
+                                               //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                               //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count =
+                                                       s_BoardInfos[dev->
+                                                       minor].i_Count + 9;
+                                               //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                       }       //if(i_ScanType==1)
+                                       else {
+                                               //i_Count=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count = 0;
+                                       }       //elseif(i_ScanType==1)
+
+                                       //if(i_ScanType!=1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType != 1) {
+                                               send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+                                       }       //if(i_ScanType!=1)
+                                       else {
+                                               //if(i_ChannelCount==i_Sum)
+                                               if (s_BoardInfos[dev->minor].
+                                                       i_ChannelCount ==
+                                                       s_BoardInfos[dev->
+                                                               minor].i_Sum) {
+                                                       send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+
+                                               }       //if(i_ChannelCount==i_Sum)
+                                       }       //else if(i_ScanType!=1)
+                               }       //if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1))
+
+                       }       //else if ((ui_StatusRegister & 0x2) == 0x2)
+                       break;
+               }               //switch(i_ADDIDATAType)
+               break;
+       case 2:
+       case 3:
+               i_APCI3200_InterruptHandleEos(dev);
+               break;
+       }                       //switch(i_ScanType)
+       return;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     :int i_APCI3200_InterruptHandleEos(comedi_device *dev)   |
+  |                                                                                                             |
+  |                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Task              : .                   |
+  |                     This function copies the acquired data(from FIFO)      |
+  |                            to Comedi buffer.                                                                        |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : comedi_device *dev                                                                      |
+  |                                                                                                                                     |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Return Value      : 0                                                                       |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+int i_APCI3200_InterruptHandleEos(comedi_device * dev)
+{
+       UINT ui_StatusRegister = 0;
+       comedi_subdevice *s = dev->subdevices + 0;
+
+       //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       //comedi_async *async = s->async;
+       //UINT *data;
+       //data=async->data+async->buf_int_ptr;//new samples added from here onwards
+       int n = 0, i = 0;
+       //END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+  /************************************/
+       /*Read the interrupt status register */
+  /************************************/
+       //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+       ui_StatusRegister =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 16);
+
+  /*************************/
+       /*Test if interrupt occur */
+  /*************************/
+
+       if ((ui_StatusRegister & 0x2) == 0x2) {
+      /*************************/
+               /*Read the channel number */
+      /*************************/
+               //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+               //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+               //This value is not used
+               //ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24);
+               s->async->events = 0;
+               //END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+      /*************************************/
+               /*Read the digital Analog Input value */
+      /*************************************/
+
+               //data[i_Count] = inl(devpriv->iobase+i_Offset + 28);
+               //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+               //data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28);
+               s_BoardInfos[dev->minor].ui_ScanValueArray[s_BoardInfos[dev->
+                               minor].i_Count] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+               //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+               //if((i_Count == (i_LastChannel-i_FirstChannel+3)))
+               if ((s_BoardInfos[dev->minor].i_Count ==
+                               (s_BoardInfos[dev->minor].i_LastChannel -
+                                       s_BoardInfos[dev->minor].
+                                       i_FirstChannel + 3))) {
+
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       s_BoardInfos[dev->minor].i_Count++;
+
+                       for (i = s_BoardInfos[dev->minor].i_FirstChannel;
+                               i <= s_BoardInfos[dev->minor].i_LastChannel;
+                               i++) {
+                               i_APCI3200_GetChannelCalibrationValue(dev, i,
+                                       &s_BoardInfos[dev->minor].
+                                       ui_ScanValueArray[s_BoardInfos[dev->
+                                                       minor].i_Count + ((i -
+                                                               s_BoardInfos
+                                                               [dev->minor].
+                                                               i_FirstChannel)
+                                                       * 3)],
+                                       &s_BoardInfos[dev->minor].
+                                       ui_ScanValueArray[s_BoardInfos[dev->
+                                                       minor].i_Count + ((i -
+                                                               s_BoardInfos
+                                                               [dev->minor].
+                                                               i_FirstChannel)
+                                                       * 3) + 1],
+                                       &s_BoardInfos[dev->minor].
+                                       ui_ScanValueArray[s_BoardInfos[dev->
+                                                       minor].i_Count + ((i -
+                                                               s_BoardInfos
+                                                               [dev->minor].
+                                                               i_FirstChannel)
+                                                       * 3) + 2]);
+                       }
+
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+                       //i_Count=-1;
+
+                       s_BoardInfos[dev->minor].i_Count = -1;
+
+                       //async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
+                       //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT);
+                       //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
+                       //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT);
+                       //comedi_eos(dev,s);
+
+                       // Set the event type (Comedi Buffer End Of Scan)
+                       s->async->events |= COMEDI_CB_EOS;
+
+                       // Test if enougth memory is available and allocate it for 7 values
+                       //n = comedi_buf_write_alloc(s->async, 7*sizeof(lsampl_t));
+                       n = comedi_buf_write_alloc(s->async,
+                               (7 + 12) * sizeof(lsampl_t));
+
+                       // If not enougth memory available, event is set to Comedi Buffer Errror
+                       if (n > ((7 + 12) * sizeof(lsampl_t))) {
+                               printk("\ncomedi_buf_write_alloc n = %i", n);
+                               s->async->events |= COMEDI_CB_ERROR;
+                       }
+                       // Write all 7 scan values in the comedi buffer
+                       comedi_buf_memcpy_to(s->async, 0,
+                               (lsampl_t *) s_BoardInfos[dev->minor].
+                               ui_ScanValueArray, (7 + 12) * sizeof(lsampl_t));
+
+                       // Update comedi buffer pinters indexes
+                       comedi_buf_write_free(s->async,
+                               (7 + 12) * sizeof(lsampl_t));
+
+                       // Send events
+                       comedi_event(dev, s);
+                       //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+                       //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //
+                       //if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over
+                       //  {
+                       //    /* buffer rollover */
+                       //    s->async->buf_int_ptr=0;
+                       //    comedi_eobuf(dev,s);
+                       //  }
+                       //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+               }
+               //i_Count++;
+               s_BoardInfos[dev->minor].i_Count++;
+       }
+       //i_InterruptFlag=0;
+       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
new file mode 100644 (file)
index 0000000..d718509
--- /dev/null
@@ -0,0 +1,191 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+// Card Specific information
+#define APCI3200_BOARD_VENDOR_ID                 0x15B8
+//#define APCI3200_ADDRESS_RANGE                   264
+
+int MODULE_NO;
+struct {
+       INT i_Gain;
+       INT i_Polarity;
+       INT i_OffsetRange;
+       INT i_Coupling;
+       INT i_SingleDiff;
+       INT i_AutoCalibration;
+       UINT ui_ReloadValue;
+       UINT ui_TimeUnitReloadVal;
+       INT i_Interrupt;
+       INT i_ModuleSelection;
+} Config_Parameters_Module1, Config_Parameters_Module2,
+       Config_Parameters_Module3, Config_Parameters_Module4;
+
+//ANALOG INPUT RANGE
+static const comedi_lrange range_apci3200_ai = { 8, {
+                       BIP_RANGE(10),
+                       BIP_RANGE(5),
+                       BIP_RANGE(2),
+                       BIP_RANGE(1),
+                       UNI_RANGE(10),
+                       UNI_RANGE(5),
+                       UNI_RANGE(2),
+                       UNI_RANGE(1)
+       }
+};
+
+static const comedi_lrange range_apci3300_ai = { 4, {
+                       UNI_RANGE(10),
+                       UNI_RANGE(5),
+                       UNI_RANGE(2),
+                       UNI_RANGE(1)
+       }
+};
+
+//Analog Input related Defines
+#define APCI3200_AI_OFFSET_GAIN                  0
+#define APCI3200_AI_SC_TEST                      4
+#define APCI3200_AI_IRQ                          8
+#define APCI3200_AI_AUTOCAL                      12
+#define APCI3200_RELOAD_CONV_TIME_VAL            32
+#define APCI3200_CONV_TIME_TIME_BASE             36
+#define APCI3200_RELOAD_DELAY_TIME_VAL           40
+#define APCI3200_DELAY_TIME_TIME_BASE            44
+#define APCI3200_AI_MODULE1                      0
+#define APCI3200_AI_MODULE2                      64
+#define APCI3200_AI_MODULE3                      128
+#define APCI3200_AI_MODULE4                      192
+#define TRUE                                     1
+#define FALSE                                    0
+#define APCI3200_AI_EOSIRQ                       16
+#define APCI3200_AI_EOS                          20
+#define APCI3200_AI_CHAN_ID                      24
+#define APCI3200_AI_CHAN_VAL                     28
+#define ANALOG_INPUT                             0
+#define TEMPERATURE                              1
+#define RESISTANCE                               2
+
+#define ENABLE_EXT_TRIG                          1
+#define ENABLE_EXT_GATE                          2
+#define ENABLE_EXT_TRIG_GATE                     3
+
+#define APCI3200_MAXVOLT                         2.5
+#define ADDIDATA_GREATER_THAN_TEST               0
+#define ADDIDATA_LESS_THAN_TEST                  1
+
+#define ADDIDATA_UNIPOLAR                        1
+#define ADDIDATA_BIPOLAR                         2
+
+//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+#define MAX_MODULE                             4
+//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+typedef struct {
+       ULONG ul_NumberOfValue;
+       ULONG *pul_ResistanceValue;
+       ULONG *pul_TemperatureValue;
+} str_ADDIDATA_RTDStruct, *pstr_ADDIDATA_RTDStruct;
+
+//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+typedef struct {
+       // Begin JK 05/08/2003 change for Linux
+       unsigned long ul_CurrentSourceCJC;
+       unsigned long ul_CurrentSource[5];
+       // End JK 05/08/2003 change for Linux
+
+       // Begin CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
+       unsigned long ul_GainFactor[8]; // Gain Factor
+       unsigned int w_GainValue[10];
+       // End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
+} str_Module;
+//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+//BEGIN JK 06.07.04: Management of sevrals boards
+typedef struct {
+       INT i_CJCAvailable;
+       INT i_CJCPolarity;
+       INT i_CJCGain;
+       INT i_InterruptFlag;
+       INT i_ADDIDATAPolarity;
+       INT i_ADDIDATAGain;
+       INT i_AutoCalibration;
+       INT i_ADDIDATAConversionTime;
+       INT i_ADDIDATAConversionTimeUnit;
+       INT i_ADDIDATAType;
+       INT i_ChannelNo;
+       INT i_ChannelCount;
+       INT i_ScanType;
+       INT i_FirstChannel;
+       INT i_LastChannel;
+       INT i_Sum;
+       INT i_Offset;
+       UINT ui_Channel_num;
+       INT i_Count;
+       INT i_Initialised;
+       //UINT ui_InterruptChannelValue[96]; //Buffer
+       UINT ui_InterruptChannelValue[144];     //Buffer
+       BYTE b_StructInitialized;
+       //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       lsampl_t ui_ScanValueArray[7 + 12];     // 7 is the maximal number of channels
+       //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+       //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+       INT i_ConnectionType;
+       INT i_NbrOfModule;
+       str_Module s_Module[MAX_MODULE];
+       //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+} str_BoardInfos;
+//END JK 06.07.04: Management of sevrals boards
+
+// Hardware Layer  functions for Apci3200
+
+//AI
+
+INT i_APCI3200_ConfigAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI3200_ReadAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+INT i_APCI3200_StopCyclicAcquisition(comedi_device * dev, comedi_subdevice * s);
+INT i_APCI3200_InterruptHandleEos(comedi_device * dev);
+INT i_APCI3200_CommandTestAnalogInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_cmd * cmd);
+INT i_APCI3200_CommandAnalogInput(comedi_device * dev, comedi_subdevice * s);
+INT i_APCI3200_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+//Interrupt
+void v_APCI3200_Interrupt(int irq, void *d);
+int i_APCI3200_InterruptHandleEos(comedi_device * dev);
+//Reset functions
+INT i_APCI3200_Reset(comedi_device * dev);
+
+int i_APCI3200_ReadCJCCalOffset(comedi_device * dev, lsampl_t * data);
+int i_APCI3200_ReadCJCValue(comedi_device * dev, lsampl_t * data);
+int i_APCI3200_ReadCalibrationGainValue(comedi_device * dev, UINT * data);
+int i_APCI3200_ReadCalibrationOffsetValue(comedi_device * dev, UINT * data);
+int i_APCI3200_Read1AnalogInputChannel(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+int i_APCI3200_ReadCJCCalGain(comedi_device * dev, lsampl_t * data);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
new file mode 100644 (file)
index 0000000..9ecd9ba
--- /dev/null
@@ -0,0 +1,742 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*.
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-3501       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci3501.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-3501                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci3501.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_ReadDigitalInput                    |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel or port           |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp;
+       UINT ui_NoOfChannel;
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       ui_Temp = data[0];
+       *data = inl(devpriv->iobase + APCI3501_DIGITAL_IP);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       //if  (ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+
+                       *data = *data & 0x3;
+               }               //if  (ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               //elseif  (ui_Temp==1)
+       }                       //elseif  (ui_Temp==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_ConfigDigitalOutput                     |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Digital Output Subdevice.               |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[1]            : 1 Enable  VCC  Interrupt  |
+|                                                                                 0 Disable VCC  Interrupt  |
+|                                        data[2]            : 1 Enable  CC  Interrupt   |
+|                                                                                 0 Disable CC  Interrupt   |
+|                                                                                                                                       |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+
+       if ((data[0] != 0) && (data[0] != 1)) {
+               comedi_error(dev,
+                       "Not a valid Data !!! ,Data should be 1 or 0\n");
+               return -EINVAL;
+       }                       //if  ( (data[0]!=0) && (data[0]!=1) )
+       if (data[0]) {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+       }                       // if  (data[0])
+       else {
+               devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+       }                       //else if  (data[0])
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_WriteDigitalOutput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : writes To the digital Output Subdevice                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s     : Subdevice Pointer            |
+|                     comedi_insn *insn       : Insn Structure Pointer       |
+|                     lsampl_t *data          : Data Pointer contains        |
+|                                          configuration parameters as below |
+|                                                                            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp, ui_Temp1;
+       UINT ui_NoOfChannel = CR_CHAN(insn->chanspec);  // get the channel
+       if (devpriv->b_OutputMemoryStatus) {
+               ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       else {
+               ui_Temp = 0;
+       }                       //if(devpriv->b_OutputMemoryStatus )
+       if (data[3] == 0) {
+               if (data[1] == 0) {
+                       data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+                       outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP);
+               }               //if(data[1]==0)
+               else {
+                       if (data[1] == 1) {
+                               data[0] = (data[0] << (2 * data[2])) | ui_Temp;
+                               outl(data[0],
+                                       devpriv->iobase + APCI3501_DIGITAL_OP);
+                       }       // if(data[1]==1)
+                       else {
+                               printk("\nSpecified channel not supported\n");
+                       }       //else if(data[1]==1)
+               }               //elseif(data[1]==0)
+       }                       //if(data[3]==0)
+       else {
+               if (data[3] == 1) {
+                       if (data[1] == 0) {
+                               data[0] = ~data[0] & 0x1;
+                               ui_Temp1 = 1;
+                               ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+                               ui_Temp = ui_Temp | ui_Temp1;
+                               data[0] =
+                                       (data[0] << ui_NoOfChannel) ^
+                                       0xffffffff;
+                               data[0] = data[0] & ui_Temp;
+                               outl(data[0],
+                                       devpriv->iobase + APCI3501_DIGITAL_OP);
+                       }       //if(data[1]==0)
+                       else {
+                               if (data[1] == 1) {
+                                       data[0] = ~data[0] & 0x3;
+                                       ui_Temp1 = 3;
+                                       ui_Temp1 = ui_Temp1 << 2 * data[2];
+                                       ui_Temp = ui_Temp | ui_Temp1;
+                                       data[0] =
+                                               ((data[0] << (2 *
+                                                               data[2])) ^
+                                               0xffffffff) & ui_Temp;
+                                       outl(data[0],
+                                               devpriv->iobase +
+                                               APCI3501_DIGITAL_OP);
+                               }       // if(data[1]==1)
+                               else {
+                                       printk("\nSpecified channel not supported\n");
+                               }       //else if(data[1]==1)
+                       }       //elseif(data[1]==0)
+               }               //if(data[3]==1);
+               else {
+                       printk("\nSpecified functionality does not exist\n");
+                       return -EINVAL;
+               }               //if else data[3]==1)
+       }                       //if else data[3]==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_ReadDigitalOutput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read  value  of the selected channel or port           |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     UINT ui_NoOfChannels    : No Of Channels To read       |
+|                     UINT *data              : Data Pointer to read status  |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       UINT ui_Temp;
+       UINT ui_NoOfChannel;
+
+       ui_NoOfChannel = CR_CHAN(insn->chanspec);
+       ui_Temp = data[0];
+       *data = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
+       if (ui_Temp == 0) {
+               *data = (*data >> ui_NoOfChannel) & 0x1;
+       }                       // if  (ui_Temp==0)
+       else {
+               if (ui_Temp == 1) {
+                       *data = *data & 0x3;
+
+               }               // if  (ui_Temp==1)
+               else {
+                       printk("\nSpecified channel not supported \n");
+               }               // else if (ui_Temp==1)
+       }                       // else if  (ui_Temp==0)
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_ConfigAnalogOutput                      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Analog Output Subdevice                 |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s     : Subdevice Pointer            |
+|                     comedi_insn *insn       : Insn Structure Pointer       |
+|                     lsampl_t *data          : Data Pointer contains        |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                      data[0]            : Voltage Mode                |
+|                                                0:Mode 0                    |
+|                                                1:Mode 1                    |
+|                                                                            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       outl(data[0],
+               devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+               APCI3501_AO_VOLT_MODE);
+
+       if (data[0]) {
+               devpriv->b_InterruptMode = MODE1;
+       } else {
+               devpriv->b_InterruptMode = MODE0;
+       }
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_WriteAnalogOutput                       |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Writes To the Selected Anlog Output Channel            |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev      : Driver handle                |
+|                     comedi_subdevice *s     : Subdevice Pointer            |
+|                     comedi_insn *insn       : Insn Structure Pointer       |
+|                     lsampl_t *data          : Data Pointer contains        |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                                                            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+
+       ul_Channel_no = CR_CHAN(insn->chanspec);
+
+       if (devpriv->b_InterruptMode == MODE1) {
+               ul_Polarity = 0x80000000;
+               if ((*data < 0) || (*data > 16384)) {
+                       printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
+               }
+
+       }                       // end if(devpriv->b_InterruptMode==MODE1)
+       else {
+               ul_Polarity = 0;
+               if ((*data < 0) || (*data > 8192)) {
+                       printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
+               }
+
+       }                       // end else
+
+       if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) {
+               printk("\nIn WriteAnalogOutput :: Not Valid Channel\n");
+       }                       // end if((ul_Channel_no<0)||(ul_Channel_no>7))
+
+       ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+
+       while (ul_DAC_Ready == 0) {
+               ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+               ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
+       }
+
+       if (ul_DAC_Ready) {
+// Output the Value on the output channels.
+               ul_Command1 =
+                       (ULONG) ((ULONG) (ul_Channel_no & 0xFF) |
+                       (ULONG) ((*data << 0x8) & 0x7FFFFF00L) |
+                       (ULONG) (ul_Polarity));
+               outl(ul_Command1,
+                       devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+                       APCI3501_AO_PROG);
+       }
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_ConfigTimerCounterWatchdog              |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Configures The Timer , Counter or Watchdog             |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[0]            : 0 Configure As Timer      |
+|                                                                                 1 Configure As Counter    |
+|                                                                                 2 Configure As Watchdog   |
+|                                        data[1]            : 1 Enable  Interrupt       |
+|                                                                                 0 Disable Interrupt       |
+|                                        data[2]            : Time Unit                 |
+|                                        data[3]                        : Reload Value                      |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command1 = 0;
+       devpriv->tsk_Current = current;
+       if (data[0] == ADDIDATA_WATCHDOG) {
+
+               devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+               //Disable the watchdog
+               outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     //disable Wa
+
+               if (data[1] == 1) {
+                       //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
+                       outl(0x02,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               } else {
+                       outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     //disable Timer interrupt
+               }
+
+               //Loading the Timebase value
+               outl(data[2],
+                       devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_TIMEBASE);
+
+               //Loading the Reload value
+               outl(data[3],
+                       devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_RELOAD_VALUE);
+               //Set the mode
+               ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL;      //e2->e0
+               outl(ul_Command1,
+                       devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_PROG);
+       }                       //end if(data[0]==ADDIDATA_WATCHDOG)
+
+       else if (data[0] == ADDIDATA_TIMER) {
+               //First Stop The Timer
+               ul_Command1 =
+                       inl(devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_PROG);
+               ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+               outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     //Stop The Timer
+               devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+               if (data[1] == 1) {
+                       //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
+                       outl(0x02,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               } else {
+                       outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     //disable Timer interrupt
+               }
+
+               // Loading Timebase
+               outl(data[2],
+                       devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_TIMEBASE);
+
+               //Loading the Reload value
+               outl(data[3],
+                       devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_RELOAD_VALUE);
+
+               // printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG));
+               ul_Command1 =
+                       inl(devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_PROG);
+               ul_Command1 =
+                       (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
+               outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);     //mode 2
+
+       }                       //end if(data[0]==ADDIDATA_TIMER)
+
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_StartStopWriteTimerCounterWatchdog      |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Start / Stop The Selected Timer , Counter or Watchdog  |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[0]            : 0 Timer                   |
+|                                                                                 1 Counter                 |
+|                                                                                 2 Watchdog                    |                             |                                         data[1]            : 1 Start                   |
+|                                                                                 0 Stop                                |                                                                                                                    2 Trigger                 |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       ULONG ul_Command1 = 0;
+       int i_Temp;
+       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+
+               if (data[1] == 1) {
+                       ul_Command1 =
+                               inl(devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+                       //Enable the Watchdog
+                       outl(ul_Command1,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               }
+
+               else if (data[1] == 0)  //Stop The Watchdog
+               {
+                       //Stop The Watchdog
+                       ul_Command1 =
+                               inl(devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+                       ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+                       outl(0x0,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               } else if (data[1] == 2) {
+                       ul_Command1 =
+                               inl(devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
+                       outl(ul_Command1,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               }               //if(data[1]==2)
+       }                       // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+
+       if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+               if (data[1] == 1) {
+
+                       ul_Command1 =
+                               inl(devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+                       //Enable the Timer
+                       outl(ul_Command1,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               } else if (data[1] == 0) {
+                       //Stop The Timer
+                       ul_Command1 =
+                               inl(devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+                       ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+                       outl(ul_Command1,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               }
+
+               else if (data[1] == 2) {
+                       //Trigger the Timer
+                       ul_Command1 =
+                               inl(devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
+                       outl(ul_Command1,
+                               devpriv->iobase + APCI3501_WATCHDOG +
+                               APCI3501_TCW_PROG);
+               }
+
+       }                       // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+       i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
+               APCI3501_TCW_TRIG_STATUS) & 0x1;
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3501_ReadTimerCounterWatchdog                |
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+
+| Task              : Read The Selected Timer , Counter or Watchdog          |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev : Driver handle                     |
+|                     UINT *data         : Data Pointer contains             |
+|                                          configuration parameters as below |
+|                                                                            |
+|                                        data[0]            : 0 Timer                   |
+|                                                                                 1 Counter                 |
+|                                                                                 2 Watchdog                |                             |                                      data[1]             : Timer Counter Watchdog Number   |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3501_ReadTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+               data[0] =
+                       inl(devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_TRIG_STATUS) & 0x1;
+               data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
+       }                       // end if  (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+
+       else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+               data[0] =
+                       inl(devpriv->iobase + APCI3501_WATCHDOG +
+                       APCI3501_TCW_TRIG_STATUS) & 0x1;
+               data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
+       }                       // end if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+
+       else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+               && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
+               printk("\nIn ReadTimerCounterWatchdog :: Invalid Subdevice \n");
+       }
+       return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   :  int i_APCI3501_Reset(comedi_device *dev)                             |
+|                                                                                       |
++----------------------------------------------------------------------------+
+| Task              :Resets the registers of the card                        |
++----------------------------------------------------------------------------+
+| Input Parameters  :                                                        |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      :                                                        |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3501_Reset(comedi_device * dev)
+{
+       int i_Count = 0, i_temp = 0;
+       ULONG ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
+       outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
+       outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+               APCI3501_AO_VOLT_MODE);
+
+       ul_Polarity = 0x80000000;
+
+       for (i_Count = 0; i_Count <= 7; i_Count++) {
+               ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+
+               while (ul_DAC_Ready == 0) {
+                       ul_DAC_Ready =
+                               inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+                       ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
+               }
+
+               if (ul_DAC_Ready) {
+                       // Output the Value on the output channels.
+                       ul_Command1 =
+                               (ULONG) ((ULONG) (i_Count & 0xFF) |
+                               (ULONG) ((i_temp << 0x8) & 0x7FFFFF00L) |
+                               (ULONG) (ul_Polarity));
+                       outl(ul_Command1,
+                               devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+                               APCI3501_AO_PROG);
+               }
+       }
+
+       return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : static void v_APCI3501_Interrupt                                      |
+|                                        (int irq , void *d)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt processing Routine                           |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+void v_APCI3501_Interrupt(int irq, void *d)
+{
+       int i_temp;
+       comedi_device *dev = d;
+       unsigned int ui_Timer_AOWatchdog;
+       unsigned long ul_Command1;
+       // Disable Interrupt
+       ul_Command1 =
+               inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+
+       ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
+       outl(ul_Command1,
+               devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+
+       ui_Timer_AOWatchdog =
+               inl(devpriv->iobase + APCI3501_WATCHDOG +
+               APCI3501_TCW_IRQ) & 0x1;
+
+       if ((!ui_Timer_AOWatchdog)) {
+               comedi_error(dev, "IRQ from unknow source");
+               return;
+       }
+
+       // Enable Interrupt
+       //Send a signal to from kernel to user space
+       send_sig(SIGIO, devpriv->tsk_Current, 0);
+       ul_Command1 =
+               inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+       ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1);
+       outl(ul_Command1,
+               devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+       i_temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
+               APCI3501_TCW_TRIG_STATUS) & 0x1;
+       return;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
new file mode 100644 (file)
index 0000000..5188672
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+// Card Specific information
+#define APCI3501_BOARD_VENDOR_ID                 0x15B8
+#define APCI3501_ADDRESS_RANGE                   255
+
+#define APCI3501_DIGITAL_IP                       0x50
+#define APCI3501_DIGITAL_OP                       0x40
+#define APCI3501_ANALOG_OUTPUT                    0x00
+
+//Analog Output related Defines
+#define APCI3501_AO_VOLT_MODE                     0
+#define APCI3501_AO_PROG                          4
+#define APCI3501_AO_TRIG_SCS                      8
+#define UNIPOLAR                                  0
+#define BIPOLAR                                   1
+#define MODE0                                     0
+#define MODE1                                     1
+// ANALOG OUTPUT RANGE
+comedi_lrange range_apci3501_ao = { 2, {
+                       BIP_RANGE(10),
+                       UNI_RANGE(10)
+       }
+};
+
+//Watchdog Related Defines
+
+#define APCI3501_WATCHDOG                         0x20
+#define APCI3501_TCW_SYNC_ENABLEDISABLE           0
+#define APCI3501_TCW_RELOAD_VALUE                 4
+#define APCI3501_TCW_TIMEBASE                     8
+#define APCI3501_TCW_PROG                         12
+#define APCI3501_TCW_TRIG_STATUS                  16
+#define APCI3501_TCW_IRQ                          20
+#define APCI3501_TCW_WARN_TIMEVAL                 24
+#define APCI3501_TCW_WARN_TIMEBASE                28
+#define ADDIDATA_TIMER                            0
+#define ADDIDATA_WATCHDOG                         2
+
+// Hardware Layer  functions for Apci3501
+
+//AO
+INT i_APCI3501_ConfigAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI3501_WriteAnalogOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//DI
+// for di read
+//INT i_APCI3501_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
+
+INT i_APCI3501_ReadDigitalInput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+//DO
+int i_APCI3501_ConfigDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI3501_WriteDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+INT i_APCI3501_ReadDigitalOutput(comedi_device * dev, comedi_subdevice * s,
+       comedi_insn * insn, lsampl_t * data);
+
+// TIMER
+// timer value is passed as u seconds
+INT i_APCI3501_ConfigTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+int i_APCI3501_ReadTimerCounterWatchdog(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+//Interrupt
+void v_APCI3501_Interrupt(int irq, void *d);
+
+//Reset functions
+int i_APCI3501_Reset(comedi_device * dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
new file mode 100644 (file)
index 0000000..a4f411d
--- /dev/null
@@ -0,0 +1,1691 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-----------------------------------------------------------------------+
+  | Project     : APCI-3XXX       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci3xxx.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: S. Weber     | Date       :  15/09/2005              |
+  +-----------------------------------------------------------------------+
+  | Description :APCI3XXX Module.  Hardware abstraction Layer for APCI3XXX|
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |                  |                                                |
+  |          |           |                                               |
+  +----------+-----------+------------------------------------------------+
+*/
+
+#include "hwdrv_apci3xxx.h"
+
+/*
++----------------------------------------------------------------------------+
+|                         ANALOG INPUT FUNCTIONS                             |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT   i_APCI3XXX_TestConversionStarted                 |
+|                          (comedi_device    *dev)                           |
++----------------------------------------------------------------------------+
+| Task                Test if any conversion started                         |
++----------------------------------------------------------------------------+
+| Input Parameters  : -                                                      |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0 : Conversion not started                             |
+|                     1 : Conversion started                                 |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_TestConversionStarted(comedi_device * dev)
+{
+       if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL) {
+               return (1);
+       } else {
+               return (0);
+       }
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT   i_APCI3XXX_AnalogInputConfigOperatingMode        |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task           Converting mode and convert time selection                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_SingleDiff  = (BYTE)  data[1];                       |
+|                     b_TimeBase    = (BYTE)  data[2]; (0: ns, 1:micros 2:ms)|
+|                    dw_ReloadValue = (DWORD) data[3];                       |
+|                     ........                                               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :>0 : No error                                           |
+|                    -1 : Single/Diff selection error                        |
+|                    -2 : Convert time base unity selection error            |
+|                    -3 : Convert time value selection error                 |
+|                    -10: Any conversion started                             |
+|                    ....                                                    |
+|                    -100 : Config command error                             |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_AnalogInputConfigOperatingMode(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_TimeBase = 0;
+       BYTE b_SingleDiff = 0;
+       DWORD dw_ReloadValue = 0;
+       DWORD dw_TestReloadValue = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n == 4) {
+          /****************************/
+               /* Get the Singel/Diff flag */
+          /****************************/
+
+               b_SingleDiff = (BYTE) data[1];
+
+          /****************************/
+               /* Get the time base unitiy */
+          /****************************/
+
+               b_TimeBase = (BYTE) data[2];
+
+          /*************************************/
+               /* Get the convert time reload value */
+          /*************************************/
+
+               dw_ReloadValue = (DWORD) data[3];
+
+          /**********************/
+               /* Test the time base */
+          /**********************/
+
+               if ((devpriv->ps_BoardInfo->
+                               b_AvailableConvertUnit & (1 << b_TimeBase)) !=
+                       0) {
+             /*******************************/
+                       /* Test the convert time value */
+             /*******************************/
+
+                       if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) {
+                               dw_TestReloadValue = dw_ReloadValue;
+
+                               if (b_TimeBase == 1) {
+                                       dw_TestReloadValue =
+                                               dw_TestReloadValue * 1000UL;
+                               }
+                               if (b_TimeBase == 2) {
+                                       dw_TestReloadValue =
+                                               dw_TestReloadValue * 1000000UL;
+                               }
+
+                /*******************************/
+                               /* Test the convert time value */
+                /*******************************/
+
+                               if (dw_TestReloadValue >=
+                                       devpriv->ps_BoardInfo->
+                                       ui_MinAcquisitiontimeNs) {
+                                       if ((b_SingleDiff == APCI3XXX_SINGLE)
+                                               || (b_SingleDiff ==
+                                                       APCI3XXX_DIFF)) {
+                                               if (((b_SingleDiff == APCI3XXX_SINGLE) && (devpriv->ps_BoardInfo->i_NbrAiChannel == 0)) || ((b_SingleDiff == APCI3XXX_DIFF) && (devpriv->ps_BoardInfo->i_NbrAiChannelDiff == 0))) {
+                          /*******************************/
+                                                       /* Single/Diff selection error */
+                          /*******************************/
+
+                                                       printk("Single/Diff selection error\n");
+                                                       i_ReturnValue = -1;
+                                               } else {
+                          /**********************************/
+                                                       /* Test if conversion not started */
+                          /**********************************/
+
+                                                       if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
+                                                               devpriv->
+                                                                       ui_EocEosConversionTime
+                                                                       =
+                                                                       (UINT)
+                                                                       dw_ReloadValue;
+                                                               devpriv->
+                                                                       b_EocEosConversionTimeBase
+                                                                       =
+                                                                       b_TimeBase;
+                                                               devpriv->
+                                                                       b_SingelDiff
+                                                                       =
+                                                                       b_SingleDiff;
+                                                               devpriv->
+                                                                       b_AiInitialisation
+                                                                       = 1;
+
+                             /*******************************/
+                                                               /* Set the convert timing unit */
+                             /*******************************/
+
+                                                               writel((DWORD)
+                                                                       b_TimeBase,
+                                                                       (void *)
+                                                                       (devpriv->
+                                                                               dw_AiBase
+                                                                               +
+                                                                               36));
+
+                             /**************************/
+                                                               /* Set the convert timing */
+                             /*************************/
+
+                                                               writel(dw_ReloadValue, (void *)(devpriv->dw_AiBase + 32));
+                                                       } else {
+                             /**************************/
+                                                               /* Any conversion started */
+                             /**************************/
+
+                                                               printk("Any conversion started\n");
+                                                               i_ReturnValue =
+                                                                       -10;
+                                                       }
+                                               }
+                                       } else {
+                      /*******************************/
+                                               /* Single/Diff selection error */
+                      /*******************************/
+
+                                               printk("Single/Diff selection error\n");
+                                               i_ReturnValue = -1;
+                                       }
+                               } else {
+                   /************************/
+                                       /* Time selection error */
+                   /************************/
+
+                                       printk("Convert time value selection error\n");
+                                       i_ReturnValue = -3;
+                               }
+                       } else {
+                /************************/
+                               /* Time selection error */
+                /************************/
+
+                               printk("Convert time value selection error\n");
+                               i_ReturnValue = -3;
+                       }
+               } else {
+             /*****************************/
+                       /* Time base selection error */
+             /*****************************/
+
+                       printk("Convert time base unity selection error\n");
+                       i_ReturnValue = -2;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT   i_APCI3XXX_InsnConfigAnalogInput                 |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task           Converting mode and convert time selection                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_ConvertMode = (BYTE)  data[0];                       |
+|                     b_TimeBase    = (BYTE)  data[1]; (0: ns, 1:micros 2:ms)|
+|                    dw_ReloadValue = (DWORD) data[2];                       |
+|                     ........                                               |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :>0: No error                                            |
+|                    ....                                                    |
+|                    -100 : Config command error                             |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnConfigAnalogInput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+               switch ((BYTE) data[0]) {
+               case APCI3XXX_CONFIGURATION:
+                       i_ReturnValue =
+                               i_APCI3XXX_AnalogInputConfigOperatingMode(dev,
+                               s, insn, data);
+                       break;
+
+               default:
+                       i_ReturnValue = -100;
+                       printk("Config command error %d\n", data[0]);
+                       break;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT   i_APCI3XXX_InsnReadAnalogInput                   |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task                Read 1 analog input                                    |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_Range             = CR_RANGE(insn->chanspec);        |
+|                     b_Channel           = CR_CHAN(insn->chanspec);         |
+|                     dw_NbrOfAcquisition = insn->n;                         |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :>0: No error                                            |
+|                    -3 : Channel selection error                            |
+|                    -4 : Configuration selelection error                    |
+|                    -10: Any conversion started                             |
+|                    ....                                                    |
+|                    -100 : Config command error                             |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadAnalogInput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec);
+       BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+       DWORD dw_Temp = 0;
+       DWORD dw_Configuration = 0;
+       DWORD dw_AcquisitionCpt = 0;
+       BYTE b_Interrupt = 0;
+
+       /*************************************/
+       /* Test if operating mode configured */
+       /*************************************/
+
+       if (devpriv->b_AiInitialisation) {
+          /***************************/
+               /* Test the channel number */
+          /***************************/
+
+               if (((b_Channel < devpriv->ps_BoardInfo->i_NbrAiChannel)
+                               && (devpriv->b_SingelDiff == APCI3XXX_SINGLE))
+                       || ((b_Channel < devpriv->ps_BoardInfo->
+                                       i_NbrAiChannelDiff)
+                               && (devpriv->b_SingelDiff == APCI3XXX_DIFF))) {
+             /**********************************/
+                       /* Test the channel configuration */
+             /**********************************/
+
+                       if (b_Configuration > 7) {
+                /***************************/
+                               /* Channel not initialised */
+                /***************************/
+
+                               i_ReturnValue = -4;
+                               printk("Channel %d range %d selection error\n",
+                                       b_Channel, b_Configuration);
+                       }
+               } else {
+             /***************************/
+                       /* Channel selection error */
+             /***************************/
+
+                       i_ReturnValue = -3;
+                       printk("Channel %d selection error\n", b_Channel);
+               }
+
+          /**************************/
+               /* Test if no error occur */
+          /**************************/
+
+               if (i_ReturnValue >= 0) {
+             /************************/
+                       /* Test the buffer size */
+             /************************/
+
+                       if ((b_Interrupt != 0) || ((b_Interrupt == 0)
+                                       && (insn->n >= 1))) {
+                /**********************************/
+                               /* Test if conversion not started */
+                /**********************************/
+
+                               if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
+                   /******************/
+                                       /* Clear the FIFO */
+                   /******************/
+
+                                       writel(0x10000UL,
+                                               (void *)(devpriv->dw_AiBase +
+                                                       12));
+
+                   /*******************************/
+                                       /* Get and save the delay mode */
+                   /*******************************/
+
+                                       dw_Temp =
+                                               readl((void *)(devpriv->
+                                                       dw_AiBase + 4));
+                                       dw_Temp = dw_Temp & 0xFFFFFEF0UL;
+
+                   /***********************************/
+                                       /* Channel configuration selection */
+                   /***********************************/
+
+                                       writel(dw_Temp,
+                                               (void *)(devpriv->dw_AiBase +
+                                                       4));
+
+                   /**************************/
+                                       /* Make the configuration */
+                   /**************************/
+
+                                       dw_Configuration =
+                                               (b_Configuration & 3) |
+                                               ((DWORD) (b_Configuration >> 2)
+                                               << 6) | ((DWORD) devpriv->
+                                               b_SingelDiff << 7);
+
+                   /***************************/
+                                       /* Write the configuration */
+                   /***************************/
+
+                                       writel(dw_Configuration,
+                                               (void *)(devpriv->dw_AiBase +
+                                                       0));
+
+                   /*********************/
+                                       /* Channel selection */
+                   /*********************/
+
+                                       writel(dw_Temp | 0x100UL,
+                                               (void *)(devpriv->dw_AiBase +
+                                                       4));
+                                       writel((DWORD) b_Channel,
+                                               (void *)(devpriv->dw_AiBase +
+                                                       0));
+
+                   /***********************/
+                                       /* Restaure delay mode */
+                   /***********************/
+
+                                       writel(dw_Temp,
+                                               (void *)(devpriv->dw_AiBase +
+                                                       4));
+
+                   /***********************************/
+                                       /* Set the number of sequence to 1 */
+                   /***********************************/
+
+                                       writel(1,
+                                               (void *)(devpriv->dw_AiBase +
+                                                       48));
+
+                   /***************************/
+                                       /* Save the interrupt flag */
+                   /***************************/
+
+                                       devpriv->b_EocEosInterrupt =
+                                               b_Interrupt;
+
+                   /*******************************/
+                                       /* Save the number of channels */
+                   /*******************************/
+
+                                       devpriv->ui_AiNbrofChannels = 1;
+
+                   /******************************/
+                                       /* Test if interrupt not used */
+                   /******************************/
+
+                                       if (b_Interrupt == 0) {
+                                               for (dw_AcquisitionCpt = 0;
+                                                       dw_AcquisitionCpt <
+                                                       insn->n;
+                                                       dw_AcquisitionCpt++) {
+                         /************************/
+                                                       /* Start the conversion */
+                         /************************/
+
+                                                       writel(0x80000UL,
+                                                               (void *)
+                                                               (devpriv->
+                                                                       dw_AiBase
+                                                                       + 8));
+
+                         /****************/
+                                                       /* Wait the EOS */
+                         /****************/
+
+                                                       do {
+                                                               dw_Temp =
+                                                                       readl(
+                                                                       (void *)
+                                                                       (devpriv->
+                                                                               dw_AiBase
+                                                                               +
+                                                                               20));
+                                                               dw_Temp =
+                                                                       dw_Temp
+                                                                       & 1;
+                                                       }
+                                                       while (dw_Temp != 1);
+
+                         /*************************/
+                                                       /* Read the analog value */
+                         /*************************/
+
+                                                       data[dw_AcquisitionCpt]
+                                                               =
+                                                               (lsampl_t)
+                                                               readl((void
+                                                                       *)
+                                                               (devpriv->
+                                                                       dw_AiBase
+                                                                       + 28));
+                                               }
+                                       } else {
+                      /************************/
+                                               /* Start the conversion */
+                      /************************/
+
+                                               writel(0x180000UL,
+                                                       (void *)(devpriv->
+                                                               dw_AiBase + 8));
+                                       }
+                               } else {
+                   /**************************/
+                                       /* Any conversion started */
+                   /**************************/
+
+                                       printk("Any conversion started\n");
+                                       i_ReturnValue = -10;
+                               }
+                       } else {
+                /*******************/
+                               /* Data size error */
+                /*******************/
+
+                               printk("Buffer size error\n");
+                               i_ReturnValue = -101;
+                       }
+               }
+       } else {
+          /***************************/
+               /* Channel selection error */
+          /***************************/
+
+               printk("Operating mode not configured\n");
+               i_ReturnValue = -1;
+       }
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : void v_APCI3XXX_Interrupt (int            irq,         |
+|                                                void           *d)       |
++----------------------------------------------------------------------------+
+| Task              :Interrupt handler for APCI3XXX                          |
+|                    When interrupt occurs this gets called.                 |
+|                    First it finds which interrupt has been generated and   |
+|                    handles  corresponding interrupt                        |
++----------------------------------------------------------------------------+
+| Input Parameters  : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : -                                                      |
++----------------------------------------------------------------------------+
+*/
+
+void v_APCI3XXX_Interrupt(int irq, void *d)
+{
+       comedi_device *dev = d;
+       BYTE b_CopyCpt = 0;
+       DWORD dw_Status = 0;
+
+       /***************************/
+       /* Test if interrupt occur */
+       /***************************/
+
+       if (((dw_Status = readl((void *)(devpriv->dw_AiBase + 16))) & 0x2UL) ==
+               0x2UL) {
+          /***********************/
+               /* Reset the interrupt */
+          /***********************/
+
+               writel(dw_Status, (void *)(devpriv->dw_AiBase + 16));
+
+          /*****************************/
+               /* Test if interrupt enabled */
+          /*****************************/
+
+               if (devpriv->b_EocEosInterrupt == 1) {
+             /********************************/
+                       /* Read all analog inputs value */
+             /********************************/
+
+                       for (b_CopyCpt = 0;
+                               b_CopyCpt < devpriv->ui_AiNbrofChannels;
+                               b_CopyCpt++) {
+                               devpriv->ui_AiReadData[b_CopyCpt] =
+                                       (UINT) readl((void *)(devpriv->
+                                               dw_AiBase + 28));
+                       }
+
+             /**************************/
+                       /* Set the interrupt flag */
+             /**************************/
+
+                       devpriv->b_EocEosInterrupt = 2;
+
+             /**********************************************/
+                       /* Send a signal to from kernel to user space */
+             /**********************************************/
+
+                       send_sig(SIGIO, devpriv->tsk_Current, 0);
+               }
+       }
+}
+
+/*
++----------------------------------------------------------------------------+
+|                            ANALOG OUTPUT SUBDEVICE                         |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT   i_APCI3XXX_InsnWriteAnalogOutput                 |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task                Read 1 analog input                                    |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_Range    = CR_RANGE(insn->chanspec);                 |
+|                     b_Channel  = CR_CHAN(insn->chanspec);                  |
+|                     data[0]    = analog value;                             |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :>0: No error                                            |
+|                    -3 : Channel selection error                            |
+|                    -4 : Configuration selelection error                    |
+|                    ....                                                    |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnWriteAnalogOutput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
+       BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+       DWORD dw_Status = 0;
+       INT i_ReturnValue = insn->n;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /***************************/
+               /* Test the channel number */
+          /***************************/
+
+               if (b_Channel < devpriv->ps_BoardInfo->i_NbrAoChannel) {
+             /**********************************/
+                       /* Test the channel configuration */
+             /**********************************/
+
+                       if (b_Range < 2) {
+                /***************************/
+                               /* Set the range selection */
+                /***************************/
+
+                               writel(b_Range,
+                                       (void *)(devpriv->dw_AiBase + 96));
+
+                /**************************************************/
+                               /* Write the analog value to the selected channel */
+                /**************************************************/
+
+                               writel((data[0] << 8) | b_Channel,
+                                       (void *)(devpriv->dw_AiBase + 100));
+
+                /****************************/
+                               /* Wait the end of transfer */
+                /****************************/
+
+                               do {
+                                       dw_Status =
+                                               readl((void *)(devpriv->
+                                                       dw_AiBase + 96));
+                               }
+                               while ((dw_Status & 0x100) != 0x100);
+                       } else {
+                /***************************/
+                               /* Channel not initialised */
+                /***************************/
+
+                               i_ReturnValue = -4;
+                               printk("Channel %d range %d selection error\n",
+                                       b_Channel, b_Range);
+                       }
+               } else {
+             /***************************/
+                       /* Channel selection error */
+             /***************************/
+
+                       i_ReturnValue = -3;
+                       printk("Channel %d selection error\n", b_Channel);
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                              TTL FUNCTIONS                                 |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT   i_APCI3XXX_InsnConfigInitTTLIO                   |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task           You must calling this function be                           |
+|                for you call any other function witch access of TTL.        |
+|                APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
++----------------------------------------------------------------------------+
+| Input Parameters  : b_InitType    = (BYTE) data[0];                        |
+|                     b_Port2Mode   = (BYTE) data[1];                        |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :>0: No error                                            |
+|                    -1: Port 2 mode selection is wrong                      |
+|                    ....                                                    |
+|                    -100 : Config command error                             |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnConfigInitTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Command = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /*******************/
+               /* Get the command */
+               /* **************** */
+
+               b_Command = (BYTE) data[0];
+
+          /********************/
+               /* Test the command */
+          /********************/
+
+               if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
+             /***************************************/
+                       /* Test the initialisation buffer size */
+             /***************************************/
+
+                       if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)
+                               && (insn->n != 2)) {
+                /*******************/
+                               /* Data size error */
+                /*******************/
+
+                               printk("Buffer size error\n");
+                               i_ReturnValue = -101;
+                       }
+               } else {
+             /************************/
+                       /* Config command error */
+             /************************/
+
+                       printk("Command selection error\n");
+                       i_ReturnValue = -100;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       /*********************************************************************************/
+       /* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */
+       /*********************************************************************************/
+
+       if ((i_ReturnValue >= 0)
+               && (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) {
+          /**********************/
+               /* Test the direction */
+          /**********************/
+
+               if ((data[1] == 0) || (data[1] == 0xFF)) {
+             /**************************/
+                       /* Save the configuration */
+             /**************************/
+
+                       devpriv->ul_TTLPortConfiguration[0] =
+                               devpriv->ul_TTLPortConfiguration[0] | data[1];
+               } else {
+             /************************/
+                       /* Port direction error */
+             /************************/
+
+                       printk("Port 2 direction selection error\n");
+                       i_ReturnValue = -1;
+               }
+       }
+
+       /**************************/
+       /* Test if no error occur */
+       /**************************/
+
+       if (i_ReturnValue >= 0) {
+          /***********************************/
+               /* Test if TTL port initilaisation */
+          /***********************************/
+
+               if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
+             /*************************/
+                       /* Set the configuration */
+             /*************************/
+
+                       outl(data[1], devpriv->iobase + 224);
+               }
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                        TTL INPUT FUNCTIONS                                 |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT     i_APCI3XXX_InsnBitsTTLIO                       |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task              : Write the selected output mask and read the status from|
+|                     all TTL channles                                       |
++----------------------------------------------------------------------------+
+| Input Parameters  : dw_ChannelMask = data [0];                             |
+|                     dw_BitMask     = data [1];                             |
++----------------------------------------------------------------------------+
+| Output Parameters : data[1] : All TTL channles states                      |
++----------------------------------------------------------------------------+
+| Return Value      : >0  : No error                                         |
+|                    -4   : Channel mask error                               |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnBitsTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_ChannelCpt = 0;
+       DWORD dw_ChannelMask = 0;
+       DWORD dw_BitMask = 0;
+       DWORD dw_Status = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 2) {
+          /*******************************/
+               /* Get the channe and bit mask */
+          /*******************************/
+
+               dw_ChannelMask = data[0];
+               dw_BitMask = data[1];
+
+          /*************************/
+               /* Test the channel mask */
+          /*************************/
+
+               if (((dw_ChannelMask & 0XFF00FF00) == 0) &&
+                       (((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF)
+                               || (((devpriv->ul_TTLPortConfiguration[0] &
+                                                       0xFF) == 0)
+                                       && ((dw_ChannelMask & 0XFF0000) ==
+                                               0)))) {
+             /*********************************/
+                       /* Test if set/reset any channel */
+             /*********************************/
+
+                       if (dw_ChannelMask) {
+                /****************************************/
+                               /* Test if set/rest any port 0 channels */
+                /****************************************/
+
+                               if (dw_ChannelMask & 0xFF) {
+                   /*******************************************/
+                                       /* Read port 0 (first digital output port) */
+                   /*******************************************/
+
+                                       dw_Status = inl(devpriv->iobase + 80);
+
+                                       for (b_ChannelCpt = 0; b_ChannelCpt < 8;
+                                               b_ChannelCpt++) {
+                                               if ((dw_ChannelMask >>
+                                                               b_ChannelCpt) &
+                                                       1) {
+                                                       dw_Status =
+                                                               (dw_Status &
+                                                               (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
+                                               }
+                                       }
+
+                                       outl(dw_Status, devpriv->iobase + 80);
+                               }
+
+                /****************************************/
+                               /* Test if set/rest any port 2 channels */
+                /****************************************/
+
+                               if (dw_ChannelMask & 0xFF0000) {
+                                       dw_BitMask = dw_BitMask >> 16;
+                                       dw_ChannelMask = dw_ChannelMask >> 16;
+
+                   /********************************************/
+                                       /* Read port 2 (second digital output port) */
+                   /********************************************/
+
+                                       dw_Status = inl(devpriv->iobase + 112);
+
+                                       for (b_ChannelCpt = 0; b_ChannelCpt < 8;
+                                               b_ChannelCpt++) {
+                                               if ((dw_ChannelMask >>
+                                                               b_ChannelCpt) &
+                                                       1) {
+                                                       dw_Status =
+                                                               (dw_Status &
+                                                               (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
+                                               }
+                                       }
+
+                                       outl(dw_Status, devpriv->iobase + 112);
+                               }
+                       }
+
+             /*******************************************/
+                       /* Read port 0 (first digital output port) */
+             /*******************************************/
+
+                       data[1] = inl(devpriv->iobase + 80);
+
+             /******************************************/
+                       /* Read port 1 (first digital input port) */
+             /******************************************/
+
+                       data[1] = data[1] | (inl(devpriv->iobase + 64) << 8);
+
+             /************************/
+                       /* Test if port 2 input */
+             /************************/
+
+                       if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) {
+                               data[1] =
+                                       data[1] | (inl(devpriv->iobase +
+                                               96) << 16);
+                       } else {
+                               data[1] =
+                                       data[1] | (inl(devpriv->iobase +
+                                               112) << 16);
+                       }
+               } else {
+             /************************/
+                       /* Config command error */
+             /************************/
+
+                       printk("Channel mask error\n");
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT i_APCI3XXX_InsnReadTTLIO                           |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task              : Read the status from selected channel                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Selected TTL channel state                   |
++----------------------------------------------------------------------------+
+| Return Value      : 0   : No error                                         |
+|                    -3   : Channel selection error                          |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+       INT i_ReturnValue = insn->n;
+       lsampl_t *pls_ReadData = data;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /***********************/
+               /* Test if read port 0 */
+          /***********************/
+
+               if (b_Channel < 8) {
+             /*******************************************/
+                       /* Read port 0 (first digital output port) */
+             /*******************************************/
+
+                       pls_ReadData[0] = inl(devpriv->iobase + 80);
+                       pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1;
+               } else {
+             /***********************/
+                       /* Test if read port 1 */
+             /***********************/
+
+                       if ((b_Channel > 7) && (b_Channel < 16)) {
+                /******************************************/
+                               /* Read port 1 (first digital input port) */
+                /******************************************/
+
+                               pls_ReadData[0] = inl(devpriv->iobase + 64);
+                               pls_ReadData[0] =
+                                       (pls_ReadData[0] >> (b_Channel -
+                                               8)) & 1;
+                       } else {
+                /***********************/
+                               /* Test if read port 2 */
+                /***********************/
+
+                               if ((b_Channel > 15) && (b_Channel < 24)) {
+                   /************************/
+                                       /* Test if port 2 input */
+                   /************************/
+
+                                       if ((devpriv->ul_TTLPortConfiguration[0]
+                                                       & 0xFF) == 0) {
+                                               pls_ReadData[0] =
+                                                       inl(devpriv->iobase +
+                                                       96);
+                                               pls_ReadData[0] =
+                                                       (pls_ReadData[0] >>
+                                                       (b_Channel - 16)) & 1;
+                                       } else {
+                                               pls_ReadData[0] =
+                                                       inl(devpriv->iobase +
+                                                       112);
+                                               pls_ReadData[0] =
+                                                       (pls_ReadData[0] >>
+                                                       (b_Channel - 16)) & 1;
+                                       }
+                               } else {
+                   /***************************/
+                                       /* Channel selection error */
+                   /***************************/
+
+                                       i_ReturnValue = -3;
+                                       printk("Channel %d selection error\n",
+                                               b_Channel);
+                               }
+                       }
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                        TTL OUTPUT FUNCTIONS                                |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     : INT     i_APCI3XXX_InsnWriteTTLIO                      |
+|                          (comedi_device    *dev,                           |
+|                           comedi_subdevice *s,                             |
+|                           comedi_insn      *insn,                          |
+|                           lsampl_t         *data)                          |
++----------------------------------------------------------------------------+
+| Task              : Set the state from TTL output channel                  |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
+|                     b_State   = data [0]                                   |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : 0   : No error                                         |
+|                    -3   : Channel selection error                          |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnWriteTTLIO(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+       BYTE b_State = 0;
+       DWORD dw_Status = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+               b_State = (BYTE) data[0];
+
+          /***********************/
+               /* Test if read port 0 */
+          /***********************/
+
+               if (b_Channel < 8) {
+             /*****************************************************************************/
+                       /* Read port 0 (first digital output port) and set/reset the selcted channel */
+             /*****************************************************************************/
+
+                       dw_Status = inl(devpriv->iobase + 80);
+                       dw_Status =
+                               (dw_Status & (0xFF -
+                                       (1 << b_Channel))) | ((b_State & 1) <<
+                               b_Channel);
+                       outl(dw_Status, devpriv->iobase + 80);
+               } else {
+             /***********************/
+                       /* Test if read port 2 */
+             /***********************/
+
+                       if ((b_Channel > 15) && (b_Channel < 24)) {
+                /*************************/
+                               /* Test if port 2 output */
+                /*************************/
+
+                               if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
+                                       == 0xFF) {
+                   /*****************************************************************************/
+                                       /* Read port 2 (first digital output port) and set/reset the selcted channel */
+                   /*****************************************************************************/
+
+                                       dw_Status = inl(devpriv->iobase + 112);
+                                       dw_Status =
+                                               (dw_Status & (0xFF -
+                                                       (1 << (b_Channel -
+                                                                       16)))) |
+                                               ((b_State & 1) << (b_Channel -
+                                                       16));
+                                       outl(dw_Status, devpriv->iobase + 112);
+                               } else {
+                   /***************************/
+                                       /* Channel selection error */
+                   /***************************/
+
+                                       i_ReturnValue = -3;
+                                       printk("Channel %d selection error\n",
+                                               b_Channel);
+                               }
+                       } else {
+                /***************************/
+                               /* Channel selection error */
+                /***************************/
+
+                               i_ReturnValue = -3;
+                               printk("Channel %d selection error\n",
+                                       b_Channel);
+                       }
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                           DIGITAL INPUT SUBDEVICE                          |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3XXX_InsnReadDigitalInput                     |
+|                                          (comedi_device *dev,              |
+|                                           comedi_subdevice *s,             |
+|                                           comedi_insn *insn,               |
+|                                           lsampl_t *data)                  |
++----------------------------------------------------------------------------+
+| Task              : Reads the value of the specified Digital input channel |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec) (0 to 3)           |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Channel value                                |
++----------------------------------------------------------------------------+
+| Return Value      : 0   : No error                                         |
+|                    -3   : Channel selection error                          |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadDigitalInput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+       DWORD dw_Temp = 0;
+
+       /***************************/
+       /* Test the channel number */
+       /***************************/
+
+       if (b_Channel <= devpriv->ps_BoardInfo->i_NbrDiChannel) {
+          /************************/
+               /* Test the buffer size */
+          /************************/
+
+               if (insn->n >= 1) {
+                       dw_Temp = inl(devpriv->iobase + 32);
+                       *data = (dw_Temp >> b_Channel) & 1;
+               } else {
+             /*******************/
+                       /* Data size error */
+             /*******************/
+
+                       printk("Buffer size error\n");
+                       i_ReturnValue = -101;
+               }
+       } else {
+          /***************************/
+               /* Channel selection error */
+          /***************************/
+
+               printk("Channel selection error\n");
+               i_ReturnValue = -3;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3XXX_InsnBitsDigitalInput                     |
+|                                          (comedi_device *dev,              |
+|                                           comedi_subdevice *s,             |
+|                                           comedi_insn *insn,               |
+|                                           lsampl_t *data)                  |
++----------------------------------------------------------------------------+
+| Task              : Reads the value of the Digital input Port i.e.4channels|
++----------------------------------------------------------------------------+
+| Input Parameters  : -                                                      |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Port value                                   |
++----------------------------------------------------------------------------+
+| Return Value      :>0: No error                                            |
+|                    ....                                                    |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3XXX_InsnBitsDigitalInput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       DWORD dw_Temp = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+               dw_Temp = inl(devpriv->iobase + 32);
+               *data = dw_Temp & 0xf;
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+|                           DIGITAL OUTPUT SUBDEVICE                         |
++----------------------------------------------------------------------------+
+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3XXX_InsnBitsDigitalOutput                    |
+|                                          (comedi_device *dev,              |
+|                                           comedi_subdevice *s,             |
+|                                           comedi_insn *insn,               |
+|                                           lsampl_t *data)                  |
++----------------------------------------------------------------------------+
+| Task              : Write the selected output mask and read the status from|
+|                     all digital output channles                            |
++----------------------------------------------------------------------------+
+| Input Parameters  : dw_ChannelMask = data [0];                             |
+|                     dw_BitMask     = data [1];                             |
++----------------------------------------------------------------------------+
+| Output Parameters : data[1] : All digital output channles states           |
++----------------------------------------------------------------------------+
+| Return Value      : >0  : No error                                         |
+|                    -4   : Channel mask error                               |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3XXX_InsnBitsDigitalOutput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_ChannelCpt = 0;
+       DWORD dw_ChannelMask = 0;
+       DWORD dw_BitMask = 0;
+       DWORD dw_Status = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 2) {
+          /*******************************/
+               /* Get the channe and bit mask */
+          /*******************************/
+
+               dw_ChannelMask = data[0];
+               dw_BitMask = data[1];
+
+          /*************************/
+               /* Test the channel mask */
+          /*************************/
+
+               if ((dw_ChannelMask & 0XFFFFFFF0) == 0) {
+             /*********************************/
+                       /* Test if set/reset any channel */
+             /*********************************/
+
+                       if (dw_ChannelMask & 0xF) {
+                /********************************/
+                               /* Read the digital output port */
+                /********************************/
+
+                               dw_Status = inl(devpriv->iobase + 48);
+
+                               for (b_ChannelCpt = 0; b_ChannelCpt < 4;
+                                       b_ChannelCpt++) {
+                                       if ((dw_ChannelMask >> b_ChannelCpt) &
+                                               1) {
+                                               dw_Status =
+                                                       (dw_Status & (0xF -
+                                                               (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
+                                       }
+                               }
+
+                               outl(dw_Status, devpriv->iobase + 48);
+                       }
+
+             /********************************/
+                       /* Read the digital output port */
+             /********************************/
+
+                       data[1] = inl(devpriv->iobase + 48);
+               } else {
+             /************************/
+                       /* Config command error */
+             /************************/
+
+                       printk("Channel mask error\n");
+                       i_ReturnValue = -4;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3XXX_InsnWriteDigitalOutput                   |
+|                                          (comedi_device *dev,              |
+|                                           comedi_subdevice *s,             |
+|                                           comedi_insn *insn,               |
+|                                           lsampl_t *data)                  |
++----------------------------------------------------------------------------+
+| Task              : Set the state from digital output channel              |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
+|                     b_State   = data [0]                                   |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : >0  : No error                                         |
+|                    -3   : Channel selection error                          |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnWriteDigitalOutput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Channel = CR_CHAN(insn->chanspec);
+       BYTE b_State = 0;
+       DWORD dw_Status = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /***************************/
+               /* Test the channel number */
+          /***************************/
+
+               if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
+             /*******************/
+                       /* Get the command */
+             /*******************/
+
+                       b_State = (BYTE) data[0];
+
+             /********************************/
+                       /* Read the digital output port */
+             /********************************/
+
+                       dw_Status = inl(devpriv->iobase + 48);
+
+                       dw_Status =
+                               (dw_Status & (0xF -
+                                       (1 << b_Channel))) | ((b_State & 1) <<
+                               b_Channel);
+                       outl(dw_Status, devpriv->iobase + 48);
+               } else {
+             /***************************/
+                       /* Channel selection error */
+             /***************************/
+
+                       printk("Channel selection error\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name     :int i_APCI3XXX_InsnReadDigitalOutput                    |
+|                                          (comedi_device *dev,              |
+|                                           comedi_subdevice *s,             |
+|                                           comedi_insn *insn,               |
+|                                           lsampl_t *data)                  |
++----------------------------------------------------------------------------+
+| Task              : Read the state from digital output channel             |
++----------------------------------------------------------------------------+
+| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
++----------------------------------------------------------------------------+
+| Output Parameters : b_State   = data [0]                                   |
++----------------------------------------------------------------------------+
+| Return Value      : >0  : No error                                         |
+|                    -3   : Channel selection error                          |
+|                    -101 : Data size error                                  |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadDigitalOutput(comedi_device * dev,
+       comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+       INT i_ReturnValue = insn->n;
+       BYTE b_Channel = CR_CHAN(insn->chanspec);
+       DWORD dw_Status = 0;
+
+       /************************/
+       /* Test the buffer size */
+       /************************/
+
+       if (insn->n >= 1) {
+          /***************************/
+               /* Test the channel number */
+          /***************************/
+
+               if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
+             /********************************/
+                       /* Read the digital output port */
+             /********************************/
+
+                       dw_Status = inl(devpriv->iobase + 48);
+
+                       dw_Status = (dw_Status >> b_Channel) & 1;
+                       *data = dw_Status;
+               } else {
+             /***************************/
+                       /* Channel selection error */
+             /***************************/
+
+                       printk("Channel selection error\n");
+                       i_ReturnValue = -3;
+               }
+       } else {
+          /*******************/
+               /* Data size error */
+          /*******************/
+
+               printk("Buffer size error\n");
+               i_ReturnValue = -101;
+       }
+
+       return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function   Name   : int i_APCI3XXX_Reset(comedi_device *dev)               |                                                         +----------------------------------------------------------------------------+
+| Task              :resets all the registers                                |
++----------------------------------------------------------------------------+
+| Input Parameters  : comedi_device *dev                                     |
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      : -                                                      |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_Reset(comedi_device * dev)
+{
+       unsigned char b_Cpt = 0;
+
+       /*************************/
+       /* Disable the interrupt */
+       /*************************/
+
+       disable_irq(dev->irq);
+
+       /****************************/
+       /* Reset the interrupt flag */
+       /****************************/
+
+       devpriv->b_EocEosInterrupt = 0;
+
+       /***************************/
+       /* Clear the start command */
+       /***************************/
+
+       writel(0, (void *)(devpriv->dw_AiBase + 8));
+
+       /*****************************/
+       /* Reset the interrupt flags */
+       /*****************************/
+
+       writel(readl((void *)(devpriv->dw_AiBase + 16)),
+               (void *)(devpriv->dw_AiBase + 16));
+
+       /*****************/
+       /* clear the EOS */
+       /*****************/
+
+       readl((void *)(devpriv->dw_AiBase + 20));
+
+       /******************/
+       /* Clear the FIFO */
+       /******************/
+
+       for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
+               readl((void *)(devpriv->dw_AiBase + 28));
+       }
+
+       /************************/
+       /* Enable the interrupt */
+       /************************/
+
+       enable_irq(dev->irq);
+
+       return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
new file mode 100644 (file)
index 0000000..bf0f540
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+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.
+
+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.
+
+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
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO   11 /* Digital Input Output But TTL */
+#endif
+
+#ifndef ADDIDATA_ENABLE
+#define ADDIDATA_ENABLE  1
+#define ADDIDATA_DISABLE 0
+#endif
+
+#define APCI3XXX_SINGLE                              0
+#define APCI3XXX_DIFF                                1
+#define APCI3XXX_CONFIGURATION                       0
+
+#define APCI3XXX_TTL_INIT_DIRECTION_PORT2   0
+
+#ifdef __KERNEL__
+
+static const comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10),
+                       BIP_RANGE(5),
+                       BIP_RANGE(2),
+                       BIP_RANGE(1),
+                       UNI_RANGE(10),
+                       UNI_RANGE(5),
+                       UNI_RANGE(2),
+       UNI_RANGE(1)}
+};
+
+static const comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+                       BIP_RANGE(1),
+       BIP_RANGE(1)}
+};
+
+static const comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10),
+       UNI_RANGE(10)}
+};
+#endif
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
new file mode 100644 (file)
index 0000000..bac0182
--- /dev/null
@@ -0,0 +1,5 @@
+#define CONFIG_APCI_035 1
+
+#define ADDIDATA_WATCHDOG 2    // Or shold it be something else
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
new file mode 100644 (file)
index 0000000..fa2056e
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_1032 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
new file mode 100644 (file)
index 0000000..7a5cae5
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_1500 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
new file mode 100644 (file)
index 0000000..8d41484
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_1516 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
new file mode 100644 (file)
index 0000000..0351cdd
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_1564 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
new file mode 100644 (file)
index 0000000..5067990
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_16XX 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
new file mode 100644 (file)
index 0000000..c433445
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_1710 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2016.c b/drivers/staging/comedi/drivers/addi_apci_2016.c
new file mode 100644 (file)
index 0000000..271c47c
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_2016 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
new file mode 100644 (file)
index 0000000..5108ea2
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_2032 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
new file mode 100644 (file)
index 0000000..e439f83
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_2200 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3001.c b/drivers/staging/comedi/drivers/addi_apci_3001.c
new file mode 100644 (file)
index 0000000..df97c30
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_3001 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
new file mode 100644 (file)
index 0000000..9183125
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_3120 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
new file mode 100644 (file)
index 0000000..f25a70b
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_3200 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3300.c b/drivers/staging/comedi/drivers/addi_apci_3300.c
new file mode 100644 (file)
index 0000000..1ee4778
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_3300 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
new file mode 100644 (file)
index 0000000..1049e20
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_3501 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
new file mode 100644 (file)
index 0000000..fb9deb7
--- /dev/null
@@ -0,0 +1,3 @@
+#define CONFIG_APCI_3XXX 1
+
+#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_all.c b/drivers/staging/comedi/drivers/addi_apci_all.c
new file mode 100644 (file)
index 0000000..aeb1b26
--- /dev/null
@@ -0,0 +1,18 @@
+#define CONFIG_APCI_035  1
+#define CONFIG_APCI_1032 1
+#define CONFIG_APCI_1500 1
+#define CONFIG_APCI_1516 1
+#define CONFIG_APCI_1564 1
+#define CONFIG_APCI_16XX 1
+#define CONFIG_APCI_1710 1
+#define CONFIG_APCI_2016 1
+#define CONFIG_APCI_2032 1
+#define CONFIG_APCI_2200 1
+#define CONFIG_APCI_3001 1
+#define CONFIG_APCI_3120 1
+#define CONFIG_APCI_3200 1
+#define CONFIG_APCI_3300 1
+#define CONFIG_APCI_3501 1
+#define CONFIG_APCI_3XXX 1
+
+#include "addi-data/addi_common.c"