driver(s) from ADDI-DATA
authorDavid Schleef <ds@schleef.org>
Mon, 11 Aug 2003 18:32:00 +0000 (18:32 +0000)
committerDavid Schleef <ds@schleef.org>
Mon, 11 Aug 2003 18:32:00 +0000 (18:32 +0000)
48 files changed:
comedi/drivers/addi-data/APCI1710_82x54.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_82x54.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Chrono.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Chrono.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Dig_io.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Dig_io.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_INCCPT.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_INCCPT.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Inp_cpt.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Inp_cpt.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Pwm.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Pwm.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Ssi.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Ssi.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Tor.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Tor.h [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Ttl.c [new file with mode: 0644]
comedi/drivers/addi-data/APCI1710_Ttl.h [new file with mode: 0644]
comedi/drivers/addi-data/Makefile.am [new file with mode: 0644]
comedi/drivers/addi-data/addi_amcc_s5933.h [new file with mode: 0644]
comedi/drivers/addi-data/addi_common.c [new file with mode: 0644]
comedi/drivers/addi-data/addi_common.h [new file with mode: 0644]
comedi/drivers/addi-data/addi_eeprom.c [new file with mode: 0644]
comedi/drivers/addi-data/amcc_s5933_58.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_APCI1710.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_APCI1710.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci035.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci035.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1032.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1032.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1500.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1500.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1516.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1516.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1564.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci1564.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci2016.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci2016.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci2032.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci2032.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci2200.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci2200.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci3120.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci3120.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci3200.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci3200.h [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci3501.c [new file with mode: 0644]
comedi/drivers/addi-data/hwdrv_apci3501.h [new file with mode: 0644]

diff --git a/comedi/drivers/addi-data/APCI1710_82x54.c b/comedi/drivers/addi-data/APCI1710_82x54.c
new file mode 100644 (file)
index 0000000..6cbe9ef
--- /dev/null
@@ -0,0 +1,1521 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : 82X54.C         |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 29.06.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 82X54 timer module                          |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  | 29/06/98 | S. Weber  | Digital input / output implementation          |\r
+  |----------|-----------|------------------------------------------------|\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+#include "APCI1710_82x54.h"\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_     i_APCI1710_InitTimer                         |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                BYTE_   b_TimerNbr,                         |\r
+|                                BYTE_   b_TimerMode,                        |\r
+|                                ULONG_ ul_ReloadValue,                      |\r
+|                                BYTE_   b_InputClockSelection,              |\r
+|                                BYTE_   b_InputClockLevel,                  |\r
+|                                BYTE_   b_OutputLevel,                      |\r
+|                                BYTE_   b_HardwareGateLevel)\r
+INT i_InsnConfig_InitTimer(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+|      \r
++----------------------------------------------------------------------------+\r
+| Task              : Configure the Timer (b_TimerNbr) operating mode        |\r
+|                     (b_TimerMode) from selected module (b_ModulNbr).       |\r
+|                     You must calling this function be for you call any     |\r
+|                     other function witch access of the timer.              |\r
+|                                                                            |\r
+|                                                                            |\r
+|                       Timer mode description table                         |\r
+|                                                                            |\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+||Selected+      Mode description       +u_ReloadValue | Hardware gate input||\r
+||  mode  |                             |  description |      action        ||\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+||        |Mode 0 is typically used     |              |                    ||\r
+||        |for event counting. After    |              |                    ||\r
+||        |the initialisation, OUT      |              |                    ||\r
+||        |is initially low, and        |              |                    ||\r
+||   0    |will remain low until the    |Start counting|   Hardware gate    ||\r
+||        |counter reaches zero.        |   value      |                    ||\r
+||        |OUT then goes high and       |              |                    ||\r
+||        |remains high until a new     |              |                    ||\r
+||        |count is written. See        |              |                    ||\r
+||        |"i_APCI1710_WriteTimerValue" |              |                    ||\r
+||        |function.                    |              |                    ||\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+||        |Mode 1 is similar to mode 0  |              |                    ||\r
+||        |except for the gate input    |              |                    ||\r
+||   1    |action. The gate input is not|Start counting|  Hardware trigger  ||\r
+||        |used for enabled or disabled |   value      |                    ||\r
+||        |the timer.                   |              |                    ||\r
+||        |The gate input is used for   |              |                    ||\r
+||        |triggered the timer.         |              |                    ||\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+||        |This mode functions like a   |              |                    ||\r
+||        |divide-by-ul_ReloadValue     |              |                    ||\r
+||        |counter. It is typically used|              |                    ||\r
+||        |to generate a real time clock|              |                    ||\r
+||        |interrupt. OUT will initially|              |                    ||\r
+||   2    |be high after the            |   Division   |  Hardware gate     ||\r
+||        |initialisation. When the     |    factor    |                    ||\r
+||        |initial count has decremented|              |                    ||\r
+||        |to 1, OUT goes low for one   |              |                    ||\r
+||        |CLK pule. OUT then goes high |              |                    ||\r
+||        |again, the counter reloads   |              |                    ||\r
+||        |the initial count            |              |                    ||\r
+||        |(ul_ReloadValue) and the     |              |                    ||\r
+||        |process is repeated.         |              |                    ||\r
+||        |This action can generated a  |              |                    ||\r
+||        |interrupt. See function      |              |                    ||\r
+||        |"i_APCI1710_SetBoardInt-     |              |                    ||\r
+||        |RoutineX"                    |              |                    ||\r
+||        |and "i_APCI1710_EnableTimer" |              |                    ||\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+||        |Mode 3 is typically used for |              |                    ||\r
+||        |baud rate generation. This   |              |                    ||\r
+||        |mode is similar to mode 2    |              |                    ||\r
+||        |except for the duty cycle of |              |                    ||\r
+||   3    |OUT. OUT will initially be   |  Division    |   Hardware gate    ||\r
+||        |high after the initialisation|   factor     |                    ||\r
+||        |When half the initial count  |              |                    ||\r
+||        |(ul_ReloadValue) has expired,|              |                    ||\r
+||        |OUT goes low for the         |              |                    ||\r
+||        |remainder of the count. The  |              |                    ||\r
+||        |mode is periodic; the        |              |                    ||\r
+||        |sequence above is repeated   |              |                    ||\r
+||        |indefinitely.                |              |                    ||\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+||        |OUT will be initially high   |              |                    ||\r
+||        |after the initialisation.    |              |                    ||\r
+||        |When the initial count       |              |                    ||\r
+||   4    |expires OUT will go low for  |Start counting|  Hardware gate     ||\r
+||        |one CLK pulse and then go    |    value     |                    ||\r
+||        |high again.                  |              |                    ||\r
+||        |The counting sequences is    |              |                    ||\r
+||        |triggered by writing a new   |              |                    ||\r
+||        |value. See                   |              |                    ||\r
+||        |"i_APCI1710_WriteTimerValue" |              |                    ||\r
+||        |function. If a new count is  |              |                    ||\r
+||        |written during counting,     |              |                    ||\r
+||        |it will be loaded on the     |              |                    ||\r
+||        |next CLK pulse               |              |                    ||\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+||        |Mode 5 is similar to mode 4  |              |                    ||\r
+||        |except for the gate input    |              |                    ||\r
+||        |action. The gate input is not|              |                    ||\r
+||   5    |used for enabled or disabled |Start counting|  Hardware trigger  ||\r
+||        |the timer. The gate input is |    value     |                    ||\r
+||        |used for triggered the timer.|              |                    ||\r
+|+--------+-----------------------------+--------------+--------------------+|\r
+|                                                                            |\r
+|                                                                            |\r
+|                                                                            |\r
+|                      Input clock selection table                           |\r
+|                                                                            |\r
+|  +--------------------------------+------------------------------------+   |\r
+|  |       b_InputClockSelection    |           Description              |   |\r
+|  |           parameter            |                                    |   |\r
+|  +--------------------------------+------------------------------------+   |\r
+|  |    APCI1710_PCI_BUS_CLOCK      | For the timer input clock, the PCI |   |\r
+|  |                                | bus clock / 4 is used. This PCI bus|   |\r
+|  |                                | clock can be 30MHz or 33MHz. For   |   |\r
+|  |                                | Timer 0 only this selection are    |   |\r
+|  |                                | available.                         |   |\r
+|  +--------------------------------+------------------------------------+   |\r
+|  | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the|   |\r
+|  |                                | possibility to inject a input clock|   |\r
+|  |                                | for Timer 1 or Timer 2. The source |   |\r
+|  |                                | from this clock can eat the output |   |\r
+|  |                                | clock from Timer 0 or any other    |   |\r
+|  |                                | clock source.                      |   |\r
+|  +--------------------------------+------------------------------------+   |\r
+|                                                                            |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_   b_BoardHandle        : Handle of board         |\r
+|                                                    APCI-1710               |\r
+|                     BYTE_   b_ModulNbr           : Module number to        |\r
+|                                                    configure (0 to 3)      |\r
+|                     BYTE_   b_TimerNbr           : Timer number to         |\r
+|                                                    configure (0 to 2)      |\r
+|                     BYTE_   b_TimerMode          : Timer mode selection    |\r
+|                                                    (0 to 5)                |\r
+|                                                    0: Interrupt on terminal|\r
+|                                                       count                |\r
+|                                                    1: Hardware             |\r
+|                                                       retriggerable one-   |\r
+|                                                       shot                 |\r
+|                                                    2: Rate generator       |\r
+|                                                    3: Square wave mode     |\r
+|                                                    4: Software triggered   |\r
+|                                                       strobe               |\r
+|                                                    5: Hardware triggered   |\r
+|                                                       strobe               |\r
+|                                                       See timer mode       |\r
+|                                                       description table.   |\r
+|                     ULONG_ ul_ReloadValue         : Start counting value   |\r
+|                                                     or division factor     |\r
+|                                                     See timer mode         |\r
+|                                                     description table.     |\r
+|                     BYTE_   b_InputClockSelection : Selection from input   |\r
+|                                                     timer clock.           |\r
+|                                                     See input clock        |\r
+|                                                     selection table.       |\r
+|                     BYTE_   b_InputClockLevel     : Selection from input   |\r
+|                                                     clock level.           |\r
+|                                                     0 : Low active         |\r
+|                                                         (Input inverted)   |\r
+|                                                     1 : High active        |\r
+|                     BYTE_   b_OutputLevel,        : Selection from output  |\r
+|                                                     clock level.           |\r
+|                                                     0 : Low active         |\r
+|                                                     1 : High active        |\r
+|                                                         (Output inverted)  |\r
+|                     BYTE_   b_HardwareGateLevel   : Selection from         |\r
+|                                                     hardware gate level.   |\r
+|                                                     0 : Low active         |\r
+|                                                         (Input inverted)   |\r
+|                                                     1 : High active        |\r
+|                                                     If you will not used   |\r
+|                                                     the hardware gate set  |\r
+|                                                     this value to 0.       \r
+|b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);\r
+       b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);\r
+       b_TimerMode               = (BYTE) data[0];\r
+       ul_ReloadValue    = (ULONG) data[1];\r
+       b_InputClockSelection   =(BYTE) data[2];\r
+       b_InputClockLevel               =(BYTE) data[3];\r
+       b_OutputLevel                   =(BYTE) data[4];\r
+       b_HardwareGateLevel             =(BYTE) data[5];\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: Module selection wrong                              |\r
+|                    -3: Timer selection wrong                               |\r
+|                    -4: The module is not a TIMER module                    |\r
+|                    -5: Timer mode selection is wrong                       |\r
+|                    -6: Input timer clock selection is wrong                |\r
+|                    -7: Selection from input clock level is wrong           |\r
+|                    -8: Selection from output clock level is wrong          |\r
+|                    -9: Selection from hardware gate level is wrong         |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+
+INT i_APCI1710_InsnConfigInitTimer(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+\r
+       INT i_ReturnValue = 0;  \r
+       BYTE   b_ModulNbr;\r
+       BYTE   b_TimerNbr;\r
+       BYTE   b_TimerMode;\r
+       ULONG  ul_ReloadValue;\r
+       BYTE   b_InputClockSelection;\r
+       BYTE   b_InputClockLevel;\r
+       BYTE   b_OutputLevel;\r
+       BYTE   b_HardwareGateLevel;\r
+\r
+       i_ReturnValue=insn->n;\r
+       b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);\r
+       b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);\r
+       b_TimerMode               = (BYTE) data[0];\r
+       ul_ReloadValue    = (ULONG) data[1];\r
+       b_InputClockSelection   =(BYTE) data[2];\r
+       b_InputClockLevel               =(BYTE) data[3];\r
+       b_OutputLevel                   =(BYTE) data[4];\r
+       b_HardwareGateLevel             =(BYTE) data[5];\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r       
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if 82X54 timer */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER)\r
+             {\r
+             /*************************/\r
+             /* Test the timer number */\r
+             /*************************/\r
+\r
+             if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))\r
+                {\r
+                /***********************/\r
+                /* Test the timer mode */\r
+                /***********************/\r
+\r
+                if ((b_TimerMode >= 0) && (b_TimerMode <= 5))\r
+                   {\r
+                   /*********************************/\r
+                   /* Test te imput clock selection */\r
+                   /*********************************/\r
+\r
+                   if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||\r
+                       ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1))))\r
+                      {\r
+                      /****************************************/\r
+                      /* Test the input clock level selection */\r
+                      /****************************************/\r
+\r
+                      if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))\r
+                         {\r
+                         /*****************************************/\r
+                         /* Test the output clock level selection */\r
+                         /*****************************************/\r
+\r
+                         if ((b_OutputLevel == 0) || (b_OutputLevel == 1))\r
+                            {\r
+                            /******************************************/\r
+                            /* Test the hardware gate level selection */\r
+                            /******************************************/\r
+\r
+                            if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))\r
+                               {\r
+                               /*********************/\r
+                               /* Initialisation OK */\r
+                               /*********************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_82X54ModuleInfo.\r
+                               s_82X54TimerInfo  [b_TimerNbr].\r
+                               b_82X54Init = 1;\r
+\r
+                               /**********************************/\r
+                               /* Save the input clock selection */\r
+                               /**********************************/\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_82X54ModuleInfo.\r
+                               s_82X54TimerInfo  [b_TimerNbr].\r
+                               b_InputClockSelection = b_InputClockSelection;\r
+\r
+                               /******************************/\r
+                               /* Save the input clock level */\r
+                               /******************************/\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_82X54ModuleInfo.\r
+                               s_82X54TimerInfo  [b_TimerNbr].\r
+                               b_InputClockLevel = ~b_InputClockLevel & 1;\r
+\r
+                               /*************************/\r
+                               /* Save the output level */\r
+                               /*************************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_82X54ModuleInfo.\r
+                               s_82X54TimerInfo  [b_TimerNbr].\r
+                               b_OutputLevel = ~b_OutputLevel & 1;\r
+\r
+                               /***********************/\r
+                               /* Save the gate level */\r
+                               /***********************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_82X54ModuleInfo.\r
+                               s_82X54TimerInfo  [b_TimerNbr].\r
+                               b_HardwareGateLevel = b_HardwareGateLevel;\r
+\r
+                               /****************************************************/\r
+                               /* Set the configuration word and disable the timer */\r
+                               /****************************************************/\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_82X54ModuleInfo.\r
+                               s_82X54TimerInfo  [b_TimerNbr].\r
+                               dw_ConfigurationWord = (DWORD) (((b_HardwareGateLevel         << 0) & 0x1) |\r
+                                                               ((b_InputClockLevel           << 1) & 0x2) |\r
+                                                               (((~b_OutputLevel       & 1)  << 2) & 0x4) |\r
+                                                               ((b_InputClockSelection       << 4) & 0x10));\r
+\r
+                               
+                               outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                       s_82X54ModuleInfo.s_82X54TimerInfo  [b_TimerNbr].\r
+                                       dw_ConfigurationWord, devpriv->s_BoardInfos.\r
+                                       ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+\r
+                               /******************************/\r
+                               /* Initialise the 82X54 Timer */\r
+                               /******************************/\r
+\r
+                               
+                               outl((DWORD) b_TimerMode,devpriv->s_BoardInfos.\r
+                                       ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+\r
+                               /**************************/\r
+                               /* Write the reload value */\r
+                               /**************************/\r
+\r
+                               
+                                outl(ul_ReloadValue,devpriv->s_BoardInfos.\r
+                                       ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+\r
+                               } // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))\r
+                            else\r
+                               {\r
+                               /***********************************************/\r
+                               /* Selection from hardware gate level is wrong */\r
+                               /***********************************************/\r
+\r                       DPRINTK("Selection from hardware gate level is wrong\n");
+                               i_ReturnValue = -9;\r
+                               } // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))\r
+                            } // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))\r
+                         else\r
+                            {\r
+                            /**********************************************/\r
+                            /* Selection from output clock level is wrong */\r
+                            /**********************************************/\r
+\r                        DPRINTK("Selection from output clock level is wrong\n");
+                            i_ReturnValue = -8;\r
+                            } // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))\r
+                         } // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))\r
+                      else\r
+                         {\r
+                         /*********************************************/\r
+                         /* Selection from input clock level is wrong */\r
+                         /*********************************************/\r
+\r                     DPRINTK("Selection from input clock level is wrong\n");
+                         i_ReturnValue = -7;\r
+                         } // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))\r
+                      }\r
+                   else\r
+                      {\r
+                      /****************************************/\r
+                      /* Input timer clock selection is wrong */\r
+                      /****************************************/\r
+\r                              DPRINTK("Input timer clock selection is wrong\n");
+                      i_ReturnValue = -6;\r
+                      }\r
+                   } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))\r
+                else\r
+                   {\r
+                   /*********************************/\r
+                   /* Timer mode selection is wrong */\r
+                   /*********************************/\r
+\r                      DPRINTK("Timer mode selection is wrong\n");
+                   i_ReturnValue = -5;\r
+                   } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))\r
+                } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))\r
+             else\r
+                {\r
+                /*************************/\r
+                /* Timer selection wrong */\r
+                /*************************/\r
+\r               DPRINTK("Timer selection wrong\n");
+                i_ReturnValue = -3;\r
+                } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))\r
+             }\r
+          else\r
+             {\r
+             /************************************/\r
+             /* The module is not a TIMER module */\r
+             /************************************/\r
+\r             DPRINTK("The module is not a TIMER module\n");   
+             i_ReturnValue = -4;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_     i_APCI1710_EnableTimer                       |\r
+|                               (BYTE_ b_BoardHandle,                        |\r
+|                                BYTE_ b_ModulNbr,                           |\r
+|                                BYTE_ b_TimerNbr,                           |\r
+|                                BYTE_ b_InterruptEnable)    \r
+INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)                |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable OR Disable the Timer (b_TimerNbr) from selected module     |\r
+|                     (b_ModulNbr). You must calling the                     |\r
+|                     "i_APCI1710_InitTimer" function be for you call this   |\r
+|                     function. If you enable the timer interrupt, the timer |\r
+|                     generate a interrupt after the timer value reach       |\r
+|                     the zero. See function "i_APCI1710_SetBoardIntRoutineX"|\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |\r
+|                                                 APCI-1710                  |\r
+|                     BYTE_   b_ModulNbr        : Selected module number     |\r
+|                                                 (0 to 3)                   |\r
+|                     BYTE_   b_TimerNbr        : Timer number to enable     |\r
+|                                                 (0 to 2)                   |\r
+|                     BYTE_   b_InterruptEnable : Enable or disable the      |\r
+|                                                 timer interrupt.           |\r
+|                                                 APCI1710_ENABLE :          |\r
+|                                                 Enable the timer interrupt |\r
+|                                                 APCI1710_DISABLE :         |\r
+|                                                 Disable the timer interrupt|\r
+i_ReturnValue=insn->n;\r
+       b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);\r
+       b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);\r
+       b_ActionType      = (BYTE) data[0]; // enable disable \r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: Module selection wrong                              |\r
+|                    -3: Timer selection wrong                               |\r
+|                    -4: The module is not a TIMER module                    |\r
+|                    -5: Timer not initialised see function                  |\r
+|                        "i_APCI1710_InitTimer"                              |\r
+|                    -6: Interrupt parameter is wrong                        |\r
+|                    -7: Interrupt function not initialised.                 |\r
+|                        See function "i_APCI1710_SetBoardIntRoutineX"       |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT             i_ReturnValue = 0;\r
+       DWORD   dw_DummyRead;\r
+       BYTE    b_ModulNbr;\r
+       BYTE    b_TimerNbr;\r
+       BYTE    b_ActionType;\r
+       BYTE    b_InterruptEnable;\r
+\r
+       i_ReturnValue=insn->n;\r
+       b_ModulNbr        = (BYTE) CR_AREF(insn->chanspec);\r
+       b_TimerNbr                = (BYTE) CR_CHAN(insn->chanspec);\r
+       b_ActionType      = (BYTE) data[0]; // enable disable \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if 82X54 timer */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER)\r
+             {\r
+             /*************************/\r
+             /* Test the timer number */\r
+             /*************************/\r
+\r
+             if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))\r
+                {\r
+                /*****************************/\r
+                /* Test if timer initialised */\r
+                /*****************************/\r
+\r
+                if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                    s_82X54ModuleInfo.\r
+                    s_82X54TimerInfo  [b_TimerNbr].\r
+                    b_82X54Init == 1)\r
+                   {\r
+\r
+             switch(b_ActionType)\r
+             { \r
+                        case APCI1710_ENABLE:\r
+\r
+                        b_InterruptEnable = (BYTE) data[1];\r
+                   /********************************/\r
+                   /* Test the interrupt selection */\r
+                   /********************************/\r
+\r
+                   if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))\r
+                      {\r
+                      if (b_InterruptEnable == APCI1710_ENABLE)\r
+                         {\r
+                         
+                            dw_DummyRead=inl(devpriv->s_BoardInfos.\r
+                                   ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+\r
+                            /************************/\r
+                            /* Enable the interrupt */\r
+                            /************************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_82X54ModuleInfo.\r
+                            s_82X54TimerInfo  [b_TimerNbr].\r
+                            dw_ConfigurationWord = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                                   s_82X54ModuleInfo.\r
+                                                   s_82X54TimerInfo  [b_TimerNbr].\r
+                                                   dw_ConfigurationWord | 0x8;\r
+\r
+                            \r
+                                 outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                    s_82X54ModuleInfo.\r
+                                    s_82X54TimerInfo  [b_TimerNbr].\r
+                                    dw_ConfigurationWord,devpriv->s_BoardInfos.\r
+                                    ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+                             devpriv->tsk_Current=current; // Save the current process task structure\r
+                          \r
+                          
+                         } // if (b_InterruptEnable == APCI1710_ENABLE)\r
+                      else\r
+                         {\r
+                         /*************************/\r
+                         /* Disable the interrupt */\r
+                         /*************************/\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_82X54ModuleInfo.\r
+                         s_82X54TimerInfo  [b_TimerNbr].\r
+                         dw_ConfigurationWord = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                                s_82X54ModuleInfo.\r
+                                                s_82X54TimerInfo  [b_TimerNbr].\r
+                                                dw_ConfigurationWord & 0xF7;\r
+\r
+                         \r
+                         outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                 s_82X54ModuleInfo.\r
+                                 s_82X54TimerInfo  [b_TimerNbr].\r
+                                 dw_ConfigurationWord,devpriv->s_BoardInfos.\r
+                                 ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+\r
+                         /***************************/\r
+                         /* Save the interrupt flag */\r
+                         /***************************/\r
+\r
+                        devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_82X54ModuleInfo.\r
+                         b_InterruptMask = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                           s_82X54ModuleInfo.\r
+                                               b_InterruptMask & (0xFF - (1 << b_TimerNbr));\r
+                         } // if (b_InterruptEnable == APCI1710_ENABLE)\r
+\r
+                      /***********************/\r
+                      /* Test if error occur */\r
+                      /***********************/\r
+\r
+                      if (i_ReturnValue >= 0)\r
+                         {\r
+                         /***************************/\r
+                         /* Save the interrupt flag */\r
+                         /***************************/\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_82X54ModuleInfo.\r
+                         b_InterruptMask = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                           s_82X54ModuleInfo.\r
+                                           b_InterruptMask | ((1 & b_InterruptEnable) << b_TimerNbr);\r
+\r
+\r
+                         /********************/\r
+                         /* Enable the timer */\r
+                         /********************/\r
+\r
+                         \r
+                         outl(1,devpriv->s_BoardInfos.\r
+                                 ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /********************************/\r
+                      /* Interrupt parameter is wrong */\r
+                      /********************************/\r
+\r                      DPRINTK("\n");
+                      i_ReturnValue = -6;\r
+                      }\r
+                          break;\r
+               case APCI1710_DISABLE:\r
+                       /***************************/\r
+                   /* Test the interrupt flag */\r
+                   /***************************/\r
+\r
+                   if (((devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_82X54ModuleInfo.\r
+                         b_InterruptMask  >> b_TimerNbr) & 1) == 1)\r
+                      {\r
+                      /*************************/\r
+                      /* Disable the interrupt */\r
+                      /*************************/\r
+\r
+                      devpriv->s_ModuleInfo [b_ModulNbr].\r
+                      s_82X54ModuleInfo.\r
+                      s_82X54TimerInfo  [b_TimerNbr].\r
+                      dw_ConfigurationWord = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                             s_82X54ModuleInfo.\r
+                                             s_82X54TimerInfo  [b_TimerNbr].\r
+                                             dw_ConfigurationWord & 0xF7;\r
+\r
+                      \r
+                            outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                              s_82X54ModuleInfo.\r
+                              s_82X54TimerInfo  [b_TimerNbr].\r
+                              dw_ConfigurationWord,devpriv->s_BoardInfos.\r
+                              ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+\r
+                      /***************************/\r
+                      /* Save the interrupt flag */\r
+                      /***************************/\r
+\r
+                      devpriv->s_ModuleInfo [b_ModulNbr].\r
+                      s_82X54ModuleInfo.\r
+                      b_InterruptMask = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                        s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));\r
+                      }\r
+\r
+                   /*********************/\r
+                   /* Disable the timer */\r
+                   /*********************/\r
+\r
+                   
+                       outl(0,devpriv->s_BoardInfos.\r
+                           ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));\r
+                               break;    \r
+                        }// Switch end\r
+                   }\r
+                else\r
+                   {\r
+                   /**************************************/\r
+                   /* Timer not initialised see function */\r
+                   /**************************************/\r
+\r                      DPRINTK("Timer not initialised see function\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*************************/\r
+                /* Timer selection wrong */\r
+                /*************************/\r
+\r               DPRINTK("Timer selection wrong\n");
+                i_ReturnValue = -3;\r
+                } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))\r
+             }\r
+          else\r
+             {\r
+             /************************************/\r
+             /* The module is not a TIMER module */\r
+             /************************************/\r
+\r            DPRINTK("The module is not a TIMER module\n");
+             i_ReturnValue = -4;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+       \r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_     i_APCI1710_ReadAllTimerValue                 |\r
+|                                       (BYTE_     b_BoardHandle,            |\r
+|                                        BYTE_     b_ModulNbr,               |\r
+|                                        PULONG_ pul_TimerValueArray)\r
+INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)        |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the all timer values from selected timer        |\r
+|                     module (b_ModulNbr).                                   |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_   b_BoardHandle     : Handle of board            |\r
+|                                                 APCI-1710                  |\r
+|                     BYTE_   b_ModulNbr        : Selected module number     |\r
+|                                                 (0 to 3)                   |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PULONG_ pul_TimerValueArray : Timer value array.       |\r
+|                           Element 0 contain the timer 0 value.             |\r
+|                           Element 1 contain the timer 1 value.             |\r
+|                           Element 2 contain the timer 2 value.             |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: Module selection wrong                              |\r
+|                    -3: The module is not a TIMER module                    |\r
+|                    -4: Timer 0 not initialised see function                |\r
+|                        "i_APCI1710_InitTimer"                              |\r
+|                    -5: Timer 1 not initialised see function                |\r
+|                        "i_APCI1710_InitTimer"                              |\r
+|                    -6: Timer 2 not initialised see function                |\r
+|                        "i_APCI1710_InitTimer"                              |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       BYTE    b_ModulNbr,b_ReadType;\r
+       PULONG  pul_TimerValueArray;\r
+\r
+       b_ModulNbr=CR_AREF(insn->chanspec);\r
+        b_ReadType=CR_CHAN(insn->chanspec);
+       pul_TimerValueArray=(PULONG) data;\r
+       i_ReturnValue=insn->n;\r
+        
+        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;
+\r        
+         case APCI1710_TIMER_READALLTIMER:
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r       
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if 82X54 timer */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER)\r
+             {\r
+             /********************************/\r
+             /* Test if timer 0 iniutialised */\r
+             /********************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_82X54ModuleInfo.\r
+                 s_82X54TimerInfo  [0].\r
+                 b_82X54Init == 1)\r
+                {\r
+                /********************************/\r
+                /* Test if timer 1 iniutialised */\r
+                /********************************/\r
+\r
+                if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                    s_82X54ModuleInfo.\r
+                    s_82X54TimerInfo  [1].\r
+                    b_82X54Init == 1)\r
+                   {\r
+                   /********************************/\r
+                   /* Test if timer 2 iniutialised */\r
+                   /********************************/\r
+\r
+                   if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                       s_82X54ModuleInfo.\r
+                       s_82X54TimerInfo  [2].\r
+                       b_82X54Init == 1)\r
+                      {\r
+                      /*********************/\r
+                      /* Latch all counter */\r
+                      /*********************/\r
+\r
+                      
+                               outl(0x17,devpriv->s_BoardInfos.\r
+                              ui_Address + 12 + (64 * b_ModulNbr));\r
+\r
+                      /**************************/\r
+                      /* Read the timer 0 value */\r
+                      /**************************/\r
+\r
+                      
+                               pul_TimerValueArray [0]=inl(devpriv->s_BoardInfos.\r
+                             ui_Address + 0 + (64 * b_ModulNbr));\r
+\r
+                      /**************************/\r
+                      /* Read the timer 1 value */\r
+                      /**************************/\r
+\r
+                      
+                               pul_TimerValueArray [1]=inl(devpriv->s_BoardInfos.\r
+                             ui_Address + 4 + (64 * b_ModulNbr));\r
+\r
+                      /**************************/\r
+                      /* Read the timer 2 value */\r
+                      /**************************/\r
+\r
+                      
+                               pul_TimerValueArray [2]=inl(devpriv->s_BoardInfos.\r
+                             ui_Address + 8 + (64 * b_ModulNbr));\r
+                      }\r
+                   else\r
+                      {\r
+                      /****************************************/\r
+                      /* Timer 2 not initialised see function */\r
+                      /****************************************/\r
+\r                      DPRINTK("Timer 2 not initialised see function\n");
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /****************************************/\r
+                   /* Timer 1 not initialised see function */\r
+                   /****************************************/\r
+\r                      DPRINTK("Timer 1 not initialised see function\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /****************************************/\r
+                /* Timer 0 not initialised see function */\r
+                /****************************************/\r
+\r               DPRINTK("Timer 0 not initialised see function\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /************************************/\r
+             /* The module is not a TIMER module */\r
+             /************************************/\r
+\r            DPRINTK("The module is not a TIMER module\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r       }// End of Switch
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+
+/*
++----------------------------------------------------------------------------+
+| 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];
+
+       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 >= 0) && (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 >= 0) && (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 >= 0) && (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 >= 0) && (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);
+       }
+
+\r
+\r
+\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_82x54.h b/comedi/drivers/addi-data/APCI1710_82x54.h
new file mode 100644 (file)
index 0000000..4e958a5
--- /dev/null
@@ -0,0 +1,69 @@
+\r
+\r
+#define APCI1710_PCI_BUS_CLOCK                                         0\r
+#define APCI1710_FRONT_CONNECTOR_INPUT                         1\r
+#define APCI1710_TIMER_READVALUE                               0\r
+#define APCI1710_TIMER_GETOUTPUTLEVEL                  1\r
+#define APCI1710_TIMER_GETPROGRESSSTATUS               2\r
+#define APCI1710_TIMER_WRITEVALUE                              3\r
+
+#define APCI1710_TIMER_READINTERRUPT            1
+#define APCI1710_TIMER_READALLTIMER             2
+
+/*\r
++----------------------------------------------------------------------------+\r
+|                       82X54 TIMER INISIALISATION FUNCTION                  |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+\r
+INT i_APCI1710_InsnConfigInitTimer(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+
+\r
+INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       82X54 READ FUNCTION                                  |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+
+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);
\ No newline at end of file
diff --git a/comedi/drivers/addi-data/APCI1710_Chrono.c b/comedi/drivers/addi-data/APCI1710_Chrono.c
new file mode 100644 (file)
index 0000000..998f86a
--- /dev/null
@@ -0,0 +1,1828 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : CHRONO.C        |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 06.07.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 chronometer module                          |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  | 29/06/98 | S. Weber  | Digital input / output implementation          |\r
+  |----------|-----------|------------------------------------------------|\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+#include "APCI1710_Chrono.h"\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_     i_APCI1710_InitChrono                        |\r
+|                                       (BYTE_     b_BoardHandle,            |\r
+|                                        BYTE_     b_ModulNbr,               |\r
+|                                        BYTE_     b_ChronoMode,             |\r
+|                                        BYTE_     b_PCIInputClock,          |\r
+|                                        BYTE_     b_TimingUnit,             |\r
+|                                        ULONG_   ul_TimingInterval,         |\r
+|                                        PULONG_ pul_RealTimingInterval) \r
+
++----------------------------------------------------------------------------+\r
+| Task              : Configure the chronometer operating mode (b_ChronoMode)|\r
+|                     from selected module (b_ModulNbr).                     |\r
+|                     The ul_TimingInterval and ul_TimingUnit determine the  |\r
+|                     timing base for the measurement.                       |\r
+|                     The pul_RealTimingInterval return the real timing      |\r
+|                     value. You must calling this function be for you call  |\r
+|                     any other function witch access of the chronometer.    |\r
+|                                                                            |\r
+|                     Witch this functionality from the APCI-1710 you have   |\r
+|                     the possibility to measure the timing witch two event. |\r
+|                                                                            |\r
+|                     The mode 0 and 1 is appropriate for period measurement.|\r
+|                     The mode 2 and 3 is appropriate for frequent           |\r
+|                     measurement.                                           |\r
+|                     The mode 4 to 7 is appropriate for measuring the timing|\r
+|                     between  two event.                                    |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_   b_BoardHandle    : Handle of board APCI-1710   |\r
+| BYTE_   b_ModulNbr  CR_AREF(insn->chanspec)  : Module number to configure  |\r
+|                                                (0 to 3)                    |\r
+| BYTE_   b_ChronoMode                         data[0]    : Chronometer action mode     |\r
+|                                                (0 to 7).                   |\r
+| BYTE_   b_PCIInputClock                      data[1] : Selection from PCI bus clock|\r
+|                                                - APCI1710_30MHZ :          |\r
+|                                                  The PC have a PCI bus     |\r
+|                                                  clock from 30 MHz         |\r
+|                                                - APCI1710_33MHZ :          |\r
+|                                                  The PC have a PCI bus     |\r
+|                                                  clock from 33 MHz         |\r
+|                                                - APCI1710_40MHZ            |\r
+|                                                  The APCI-1710 have a      |\r
+|                                                  integrated 40Mhz          |\r
+|                                                  quartz.                   |\r
+|               BYTE_   b_TimingUnit   data[2]    : Base timing unity (0 to 4) |\r
+|                                                 0 : ns                     |\r
+|                                                 1 : µs                     |\r
+|                                                 2 : ms                     |\r
+|                                                 3 : s                      |\r
+|                                                 4 : mn                     |\r
+|         ULONG_ ul_TimingInterval : data[3]    Base timing value.          |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PULONG_  pul_RealTimingInterval : Real  base timing    |\r
+|                                                       value.               \r
+|                     data[0]\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a Chronometer module             |\r
+|                     -4: Chronometer mode selection is wrong                |\r
+|                     -5: The selected PCI input clock is wrong              |\r
+|                     -6: Timing unity selection is wrong                    |\r
+|                     -7: Base timing selection is wrong                     |\r
+|                     -8: You can not used the 40MHz clock selection wich    |\r
+|                         this board                                         |\r
+|                     -9: You can not used the 40MHz clock selection wich    |\r
+|                         this CHRONOS version                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+
+\r
+INT i_APCI1710_InsnConfigInitChrono(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       ULONG ul_TimerValue,ul_TimingInterval,ul_RealTimingInterval;\r
+       double d_RealTimingInterval;\r
+       DWORD dw_ModeArray [8] = {0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06};\r
+       BYTE   b_ModulNbr,b_ChronoMode,b_PCIInputClock,b_TimingUnit;\r
+\r       PULONG pul_RealTimingInterval;
+
+       b_ModulNbr        = CR_AREF(insn->chanspec);\r
+       b_ChronoMode      = (BYTE)  data[0];\r
+       b_PCIInputClock   = (BYTE)  data[1];\r
+       b_TimingUnit      = (BYTE)  data[2];\r
+       ul_TimingInterval =     (ULONG) data[3];  \r
+       i_ReturnValue     =  insn->n;\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if chronometer */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER)\r
+             {\r
+             /*****************************/\r
+             /* Test the chronometer mode */\r
+             /*****************************/\r
+\r
+             if (b_ChronoMode >= 0 && b_ChronoMode <= 7)\r
+                {\r
+                /**************************/\r
+                /* Test the PCI bus clock */\r
+                /**************************/\r
+\r
+                if ((b_PCIInputClock == APCI1710_30MHZ) ||\r
+                    (b_PCIInputClock == APCI1710_33MHZ) ||\r
+                    (b_PCIInputClock == APCI1710_40MHZ))\r
+                   {\r
+                   /*************************/\r
+                   /* Test the timing unity */\r
+                   /*************************/\r
+\r
+                   if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))\r
+                      {\r
+                      /**********************************/\r
+                      /* Test the base timing selection */\r
+                      /**********************************/\r
+\r
+                      if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 66) && (ul_TimingInterval <= 0xFFFFFFFFUL)) ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 143165576UL))  ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 143165UL))     ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 143UL))        ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 2UL))          ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 60) && (ul_TimingInterval <= 0xFFFFFFFFUL)) ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 130150240UL))  ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 130150UL))     ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 130UL))        ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 2UL))          ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 50) && (ul_TimingInterval <= 0xFFFFFFFFUL)) ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 107374182UL))  ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 107374UL))     ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 107UL))        ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1)  && (ul_TimingInterval <= 1UL)))\r
+                         {\r
+                         /**************************/\r
+                         /* Test the board version */\r
+                         /**************************/\r
+\r
+                         if ((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.\r
+                                                                     b_BoardVersion > 0) ||\r
+                             (b_PCIInputClock != APCI1710_40MHZ))\r
+                            {\r
+                            /************************/\r
+                            /* Test the TOR version */\r
+                            /************************/\r
+\r
+                            if ((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.\r
+                                                                         dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3131) ||\r
+                                (b_PCIInputClock != APCI1710_40MHZ))\r
+                               {\r
+                               /****************************************/\r
+                               /* Calculate the timer 0 division fator */\r
+                               /****************************************/\r
+\r
+                               switch (b_TimingUnit)\r
+                                  {\r
+                                  /******/\r
+                                  /* ns */\r
+                                  /******/\r
+\r
+                                  case 0:\r
+                                       \r
+                                          /******************/\r
+                                          /* Timer 0 factor */\r
+                                          /******************/\r
+\r
+                                          ul_TimerValue = (ULONG) (ul_TimingInterval * (0.001 * b_PCIInputClock));\r
+\r
+                                          /*******************/\r
+                                          /* Round the value */\r
+                                          /*******************/\r
+\r
+                                          if ((double) ((double) ul_TimingInterval * (0.001 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                             {\r
+                                             ul_TimerValue = ul_TimerValue + 1;\r
+                                             }\r
+\r
+                                          /*****************************/\r
+                                          /* Calculate the real timing */\r
+                                          /*****************************/\r
+\r
+                                          ul_RealTimingInterval = (ULONG) (ul_TimerValue / (0.001 * (double) b_PCIInputClock));\r
+                                          d_RealTimingInterval = (double) ul_TimerValue / (0.001 * (double) b_PCIInputClock);\r
+\r
+                                          if ((double) ((double) ul_TimerValue / (0.001 * (double) b_PCIInputClock)) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                             {\r
+                                             ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                             }\r
+\r
+                                          ul_TimingInterval = ul_TimingInterval - 1;\r
+                                          ul_TimerValue     = ul_TimerValue - 2;\r
+                                          if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                             {\r
+                                             ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 0.99392);\r
+                                             }\r
+                               \r
+                                       break;\r
+\r
+                                  /******/\r
+                                  /* æs */\r
+                                  /******/\r
+\r
+                                  case 1:\r
+                                       \r
+                                          /******************/\r
+                                          /* Timer 0 factor */\r
+                                          /******************/\r
+\r
+                                          ul_TimerValue = (ULONG) (ul_TimingInterval * (1.0 * b_PCIInputClock));\r
+\r
+                                          /*******************/\r
+                                          /* Round the value */\r
+                                          /*******************/\r
+\r
+                                          if ((double) ((double) ul_TimingInterval * (1.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                             {\r
+                                             ul_TimerValue = ul_TimerValue + 1;\r
+                                             }\r
+\r
+                                          /*****************************/\r
+                                          /* Calculate the real timing */\r
+                                          /*****************************/\r
+\r
+                                          ul_RealTimingInterval = (ULONG) (ul_TimerValue / (1.0 * (double) b_PCIInputClock));\r
+                                          d_RealTimingInterval = (double) ul_TimerValue / ((double) 1.0 * (double) b_PCIInputClock);\r
+\r
+                                          if ((double) ((double) ul_TimerValue / (1.0 * (double) b_PCIInputClock)) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                             {\r
+                                             ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                             }\r
+\r
+                                          ul_TimingInterval = ul_TimingInterval - 1;\r
+                                          ul_TimerValue     = ul_TimerValue - 2;\r
+                                          if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                             {\r
+                                             ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 0.99392);\r
+                                             }\r
+                                       \r
+\r
+                                       break;\r
+\r
+                                  /******/\r
+                                  /* ms */\r
+                                  /******/\r
+\r
+                                  case 2:\r
+                                       \r
+                                          /******************/\r
+                                          /* Timer 0 factor */\r
+                                          /******************/\r
+\r
+                                          ul_TimerValue = ul_TimingInterval * (1000 * b_PCIInputClock);\r
+\r
+                                          /*******************/\r
+                                          /* Round the value */\r
+                                          /*******************/\r
+\r
+                                          if ((double) ((double) ul_TimingInterval * (1000.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                             {\r
+                                             ul_TimerValue = ul_TimerValue + 1;\r
+                                             }\r
+\r
+                                          /*****************************/\r
+                                          /* Calculate the real timing */\r
+                                          /*****************************/\r
+\r
+                                          ul_RealTimingInterval = (ULONG) (ul_TimerValue / (1000.0 * (double) b_PCIInputClock));\r
+                                          d_RealTimingInterval = (double) ul_TimerValue / (1000.0 * (double) b_PCIInputClock);\r
+\r
+                                          if ((double) ((double) ul_TimerValue / (1000.0 * (double) b_PCIInputClock)) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                             {\r
+                                             ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                             }\r
+\r
+                                          ul_TimingInterval = ul_TimingInterval - 1;\r
+                                          ul_TimerValue     = ul_TimerValue - 2;\r
+                                          if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                             {\r
+                                             ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 0.99392);\r
+                                             }\r
+                                       \r
+                                       break;\r
+\r
+                                  /*****/\r
+                                  /* s */\r
+                                  /*****/\r
+\r
+                                  case 3:\r
+                                       \r
+                                          /******************/\r
+                                          /* Timer 0 factor */\r
+                                          /******************/\r
+\r
+                                          ul_TimerValue = (ULONG) (ul_TimingInterval * (1000000.0 * b_PCIInputClock));\r
+\r
+                                          /*******************/\r
+                                          /* Round the value */\r
+                                          /*******************/\r
+\r
+                                          if ((double) ((double) ul_TimingInterval * (1000000.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                             {\r
+                                             ul_TimerValue = ul_TimerValue + 1;\r
+                                             }\r
+\r
+                                          /*****************************/\r
+                                          /* Calculate the real timing */\r
+                                          /*****************************/\r
+\r
+                                          ul_RealTimingInterval = (ULONG) (ul_TimerValue / (1000000.0 * (double) b_PCIInputClock));\r
+                                          d_RealTimingInterval = (double) ul_TimerValue / (1000000.0 * (double) b_PCIInputClock);\r
+\r
+                                          if ((double) ((double) ul_TimerValue / (1000000.0 * (double) b_PCIInputClock)) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                             {\r
+                                             ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                             }\r
+\r
+                                          ul_TimingInterval = ul_TimingInterval - 1;\r
+                                          ul_TimerValue     = ul_TimerValue - 2;\r
+                                          if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                             {\r
+                                             ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 0.99392);\r
+                                             }\r
+                                       \r
+\r
+                                       break;\r
+\r
+                                  /******/\r
+                                  /* mn */\r
+                                  /******/\r
+\r
+                                  case 4:\r
+                                       \r
+                                          /******************/\r
+                                          /* Timer 0 factor */\r
+                                          /******************/\r
+\r
+                                          ul_TimerValue = (ULONG) ((ul_TimingInterval * 60) * (1000000.0 * b_PCIInputClock));\r
+\r
+                                          /*******************/\r
+                                          /* Round the value */\r
+                                          /*******************/\r
+\r
+                                          if ((double) ((double) (ul_TimingInterval * 60.0) * (1000000.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                             {\r
+                                             ul_TimerValue = ul_TimerValue + 1;\r
+                                             }\r
+\r
+                                          /*****************************/\r
+                                          /* Calculate the real timing */\r
+                                          /*****************************/\r
+\r
+                                          ul_RealTimingInterval = (ULONG) (ul_TimerValue / (1000000.0 * (double) b_PCIInputClock)) / 60;\r
+                                          d_RealTimingInterval = ((double) ul_TimerValue / (0.001 * (double) b_PCIInputClock)) / 60.0;\r
+\r
+                                          if ((double) (((double) ul_TimerValue / (1000000.0 * (double) b_PCIInputClock)) / 60.0) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                             {\r
+                                             ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                             }\r
+\r
+                                          ul_TimingInterval = ul_TimingInterval - 1;\r
+                                          ul_TimerValue     = ul_TimerValue - 2;\r
+                                          if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                             {\r
+                                             ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 0.99392);\r
+                                             }\r
+                                       \r
+\r
+                                       break;\r
+                                  }\r
+\r
+                               /****************************/\r
+                               /* Save the PCI input clock */\r
+                               /****************************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_ChronoModuleInfo.\r
+                               b_PCIInputClock = b_PCIInputClock;\r
+\r
+                               /*************************/\r
+                               /* Save the timing unity */\r
+                               /*************************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_ChronoModuleInfo.\r
+                               b_TimingUnit = b_TimingUnit;\r
+\r
+                               /************************/\r
+                               /* Save the base timing */\r
+                               /************************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_ChronoModuleInfo.\r
+                               d_TimingInterval = d_RealTimingInterval;\r
+\r
+                               /****************************/\r
+                               /* Set the chronometer mode */\r
+                               /****************************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_ChronoModuleInfo.\r
+                               dw_ConfigReg = dw_ModeArray [b_ChronoMode];\r
+\r
+                               /***********************/\r
+                               /* Test if 40 MHz used */\r
+                               /***********************/\r
+\r
+                               if (b_PCIInputClock == APCI1710_40MHZ)\r
+                                  {\r
+                                  devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                  s_ChronoModuleInfo.\r
+                                  dw_ConfigReg = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                                 s_ChronoModuleInfo.\r
+                                                 dw_ConfigReg | 0x80;\r
+                                  }\r
+\r
+                               outl(devpriv->s_ModuleInfo [b_ModulNbr].s_ChronoModuleInfo.\r
+                                       dw_ConfigReg,devpriv->s_BoardInfos.\r
+                                       ui_Address + 16 + (64 * b_ModulNbr));\r
+\r
+                               /***********************/\r
+                               /* Write timer 0 value */\r
+                               /***********************/\r
+\r
+                               
+                               outl(ul_TimerValue,devpriv->s_BoardInfos.\r
+                                       ui_Address + (64 * b_ModulNbr));\r
+\r
+                               /*********************/\r
+                               /* Chronometer init. */\r
+                               /*********************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_ChronoModuleInfo.\r
+                               b_ChronoInit = 1;\r
+                               }\r
+                            else\r
+                               {\r
+                               /***********************************************/\r
+                               /* TOR version error for 40MHz clock selection */\r
+                               /***********************************************/\r
+\r                       DPRINTK("TOR version error for 40MHz clock selection\n");
+                               i_ReturnValue = -9;\r
+                               }\r
+                            }\r
+                         else\r
+                            {\r
+                            /**************************************************************/\r
+                            /* You can not used the 40MHz clock selection wich this board */\r
+                            /**************************************************************/\r
+\r                               DPRINTK("You can not used the 40MHz clock selection wich this board\n");
+                            i_ReturnValue = -8;\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         /**********************************/\r
+                         /* Base timing selection is wrong */\r
+                         /**********************************/\r
+\r                        DPRINTK("Base timing selection is wrong\n");
+                         i_ReturnValue = -7;\r
+                         }\r
+                      } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))\r
+                   else\r
+                      {\r
+                      /***********************************/\r
+                      /* Timing unity selection is wrong */\r
+                      /***********************************/\r
+\r                         DPRINTK("Timing unity selection is wrong\n");
+                      i_ReturnValue = -6;\r
+                      } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))\r
+                   } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))\r
+                else\r
+                   {\r
+                   /*****************************************/\r
+                   /* The selected PCI input clock is wrong */\r
+                   /*****************************************/\r
+\r                      DPRINTK("The selected PCI input clock is wrong\n");
+                   i_ReturnValue = -5;\r
+                   } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))\r
+                } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7)\r
+             else\r
+                {\r
+                /***************************************/\r
+                /* Chronometer mode selection is wrong */\r
+                /***************************************/\r
+               \rDPRINTK("Chronometer mode selection is wrong\n");
+                i_ReturnValue = -4;\r
+                } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7)\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a Chronometer module */\r
+             /******************************************/\r
+\r            DPRINTK("The module is not a Chronometer module\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+       data[0] = ul_RealTimingInterval;\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_EnableChrono                          |\r
+|                                               (BYTE_ b_BoardHandle,        |\r
+|                                                BYTE_ b_ModulNbr,           |\r
+|                                                BYTE_ b_CycleMode,          |\r
+|                                                BYTE_ b_InterruptEnable)\r
+INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,\r
+comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)                                           |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable the chronometer from selected module            |\r
+|                     (b_ModulNbr). You must calling the                     |\r
+|                     "i_APCI1710_InitChrono" function be for you call this  |\r
+|                     function.                                              |\r
+|                     If you enable the chronometer interrupt, the           |\r
+|                     chronometer generate a interrupt after the stop signal.|\r
+|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |\r
+|                     Interrupt mask description chapter from this manual.   |\r
+|                     The b_CycleMode parameter determine if you will        |\r
+|                     measured a single or more cycle. \r
+\r
+|                                        Disable the chronometer from selected module           |\r
+|                     (b_ModulNbr). If you disable the chronometer after a   |\r
+|                     start signal occur and you restart the chronometer     |\r
+|                     witch the " i_APCI1710_EnableChrono" function, if no   |\r
+|                     stop signal occur this start signal is ignored.   \r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |\r
+|                     BYTE_ b_ModulNbr   CR_AREF(chanspec)  : Selected module number (0 to 3) |\r
+                                  data[0]  ENABle/Disable chrono\r
+|                     BYTE_ b_CycleMode    : Selected the chronometer        |\r
+|                                  data[1]           acquisition mode                |\r
+|                     BYTE_ b_InterruptEnable : Enable or disable the        |\r
+|                                   data[2]            chronometer interrupt.       |\r
+|                                               APCI1710_ENABLE:             |\r
+|                                               Enable the chronometer       |\r
+|                                               interrupt                    |\r
+|                                               APCI1710_DISABLE:            |\r
+|                                               Disable the chronometer      |\r
+|                                               interrupt                    |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a Chronometer module             |\r
+|                     -4: Chronometer not initialised see function           |\r
+|                         "i_APCI1710_InitChrono"                            |\r
+|                     -5: Chronometer acquisition mode cycle is wrong        |\r
+|                     -6: Interrupt parameter is wrong                       |\r
+|                     -7: Interrupt function not initialised.                |\r
+|                         See function "i_APCI1710_SetBoardIntRoutineX"  \r
+                      -8: data[0] wrong input    |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r\r
+INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       BYTE b_ModulNbr,b_CycleMode,b_InterruptEnable,b_Action;\r
+       b_ModulNbr                      =       CR_AREF(insn->chanspec);\r
+        b_Action            =(BYTE) data[0];
+       b_CycleMode                     =(BYTE) data[1];\r
+       b_InterruptEnable       =(BYTE) data[2];\r
+       i_ReturnValue           =   insn->n;\r
+       
+\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if chronometer */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER)\r
+             {\r
+             /***********************************/\r
+             /* Test if chronometer initialised */\r
+             /***********************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_ChronoModuleInfo.\r
+                 b_ChronoInit == 1)\r
+                {\r
+\r
+\r
+         switch(b_Action)\r
+         {\r
\r
+                case APCI1710_ENABLE :\r
+                            
+                /*********************************/\r
+                /* Test the cycle mode parameter */\r
+                /*********************************/\r
+\r
+                if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))\r
+                   {\r
+                   /***************************/\r
+                   /* Test the interrupt flag */\r
+                   /***************************/\r
+\r
+                   if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))\r
+                      {\r
+                   
+       
+                         /***************************/\r
+                         /* Save the interrupt flag */\r
+                         /***************************/\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_ChronoModuleInfo.\r
+                         b_InterruptMask = b_InterruptEnable;\r
+\r
+                         /***********************/\r
+                         /* Save the cycle mode */\r
+                         /***********************/\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_ChronoModuleInfo.\r
+                         b_CycleMode = b_CycleMode;\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_ChronoModuleInfo.\r
+                         dw_ConfigReg = (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                         s_ChronoModuleInfo.\r
+                                         dw_ConfigReg & 0x8F)           |\r
+                                         ((1 & b_InterruptEnable) << 5) |\r
+                                         ((1 & b_CycleMode) << 6)       |\r
+                                         0x10 ;\r
+\r
+                         /*****************************/\r
+                         /* Test if interrupt enabled */\r
+                         /*****************************/\r
+\r
+                         if (b_InterruptEnable == APCI1710_ENABLE)\r
+                            {\r
+                            /****************************/\r
+                            /* Clear the interrupt flag */\r
+                            /****************************/\r
+\r
+                           \r
+                                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                    s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.\r
+                                    ui_Address + 32 + (64 * b_ModulNbr));\r
+                         devpriv->tsk_Current=current; // Save the current process task structure
+                            }\r
+\r
+                         /***********************************/\r
+                         /* Enable or disable the interrupt */\r
+                         /* Enable the chronometer          */\r
+                         /***********************************/\r
+           
+                         outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                 s_ChronoModuleInfo.dw_ConfigReg,devpriv->s_BoardInfos.\r
+                                 ui_Address + 16 + (64 * b_ModulNbr));\r
+\r
+                         /*************************/\r
+                         /* Clear status register */\r
+                         /*************************/\r
+\r
+                        
+                         outl(0,devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));\r
+                         \r
+                   } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))\r
+                   else\r
+                      {\r
+                      /********************************/\r
+                      /* Interrupt parameter is wrong */\r
+                      /********************************/\r
+\r                         DPRINTK("Interrupt parameter is wrong\n");
+                      i_ReturnValue = -6;\r
+                      } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))\r
+                   } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))\r
+                else\r
+                   {\r
+                   /***********************************************/\r
+                   /* Chronometer acquisition mode cycle is wrong */\r
+                   /***********************************************/\r
+\r                      DPRINTK("Chronometer acquisition mode cycle is wrong\n");
+                   i_ReturnValue = -5;\r
+                   } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))\r
+                break;\r
+\r
+                case APCI1710_DISABLE :\r
+\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_ChronoModuleInfo.\r
+                b_InterruptMask = 0;\r
+\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_ChronoModuleInfo.\r
+                dw_ConfigReg = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_ChronoModuleInfo.\r
+                               dw_ConfigReg & 0x2F;\r
+\r
+                /***************************/\r
+                /* Disable the interrupt   */\r
+                /* Disable the chronometer */\r
+                /***************************/\r
+\r
+                
+                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.\r
+                        ui_Address + 16 + (64 * b_ModulNbr));\r
+\r
+                /***************************/\r
+                /* Test if continuous mode */\r
+                /***************************/\r
+\r
+                if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                    s_ChronoModuleInfo.b_CycleMode == APCI1710_CONTINUOUS)\r
+                   {\r
+                   /*************************/\r
+                   /* Clear status register */\r
+                   /*************************/\r
+\r
+                  
+                       outl(0,devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));\r
+                   }\r
+                   break;\r
+
+                default:\r
+                         DPRINTK("Inputs wrong! Enable or Disable chrono\n");\r
+                         i_ReturnValue = -8;\r
+                 } // switch ENABLE/DISABLE\r
+                }\r
+             else\r
+                {\r
+                /*******************************/\r
+                /* Chronometer not initialised */\r
+                /*******************************/\r
+\r                DPRINTK("Chronometer not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a Chronometer module */\r
+             /******************************************/\r
+\r            DPRINTK("The module is not a Chronometer module\n");      
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r      
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+/*
++----------------------------------------------------------------------------+
+| 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)
+                {
+                
+                   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;
+                      }
+                   
+                }
+             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);
+       }
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)                    |\r
++----------------------------------------------------------------------------+\r
+| Task              : Sets the output witch has been passed with the         |\r
+|                     parameter b_Channel. Setting an output means setting an|\r
+|                     output high.                                           |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |\r
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|\r
+|                     BYTE_ b_OutputChannel : Selection from digital output  |\r
+|                           CR_CHAN()                  channel (0 to 2)               |\r
+|                                              0 : Channel H                 |\r
+|                                              1 : Channel A                 |\r
+|                                              2 : Channel B                 |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a Chronometer module             |\r
+|                     -4: The selected digital output is wrong               |\r
+|                     -5: Chronometer not initialised see function           |\r
+|                         "i_APCI1710_InitChrono"                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_SetChronoChlOff                       |\r
+|                               (BYTE_  b_BoardHandle,                       |\r
+|                                BYTE_  b_ModulNbr,                          |\r
+|                                BYTE_  b_OutputChannel)                     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Resets the output witch has been passed with the       |\r
+|                     parameter b_Channel. Resetting an output means setting |\r
+|                     an output low.                                         |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710 \r
+                        data[0] : Chl ON, Chl OFF , Chl Read , Port Read \r
+                                                        \r
+|                     BYTE_ b_ModulNbr  CR_AREF    : Selected module number (0 to 3)|\r
+|                     BYTE_ b_OutputChannel CR_CHAN : Selection from digital output  |\r
+|                                             channel (0 to 2)               |\r
+|                                              0 : Channel H                 |\r
+|                                              1 : Channel A                 |\r
+|                                              2 : Channel B                 |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a Chronometer module             |\r
+|                     -4: The selected digital output is wrong               |\r
+|                     -5: Chronometer not initialised see function           |\r
+|                         "i_APCI1710_InitChrono"                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ReadChronoChlValue                    |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                BYTE_   b_InputChannel,                     |\r
+|                                PBYTE_ pb_ChannelStatus)                    |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the status from selected digital input          |\r
+|                     (b_InputChannel) from selected chronometer             |\r
+|                     module (b_ModulNbr).                                   |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |\r
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|\r
+|                     BYTE_ b_InputChannel  : Selection from digital input   |\r
+|                                             channel (0 to 2)               |\r
+|                                   CR_CHAN()             0 : Channel E               |\r
+|                                                1 : Channel F               |\r
+|                                                2 : Channel G               |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel status.|\r
+|                                data[0]                0 : Channel is not active   |\r
+|                                                1 : Channel is active       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a Chronometer module             |\r
+|                     -4: The selected digital input is wrong                |\r
+|                     -5: Chronometer not initialised see function           |\r
+|                         "i_APCI1710_InitChrono"                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ReadChronoPortValue                   |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                PBYTE_ pb_PortValue)                        |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the status from digital inputs port from        |\r
+|                     selected  (b_ModulNbr) chronometer module.             |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |\r
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_PortValue   : Digital inputs port status.    \r
+|                     data[0]\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a Chronometer module             |\r
+|                     -4: Chronometer not initialised see function           |\r
+|                         "i_APCI1710_InitChrono"                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+\r
+INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       BYTE  b_ModulNbr,b_OutputChannel,b_InputChannel,b_IOType;
+       DWORD dw_Status;
+       PBYTE pb_ChannelStatus;
+       PBYTE pb_PortValue;\r
+       \r
+       b_ModulNbr      = CR_AREF(insn->chanspec);\r
+       i_ReturnValue = insn->n;\r
+       b_IOType   = (BYTE) data[0];\r
+          \r
+\r
+       
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if chronometer */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER)\r
+             {\r
+             /***********************************/\r
+             /* Test if chronometer initialised */\r
+             /***********************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_ChronoModuleInfo.\r
+                 b_ChronoInit == 1)\r
+                {\r
+                /***********************************/\r
+                /* Test the digital output channel */\r
+                /***********************************/\r
+          switch(b_IOType)\r
+          {\r
+\r
+                case APCI1710_CHRONO_SET_CHANNELOFF:\r
+\r
+               b_OutputChannel = (BYTE) CR_CHAN(insn->chanspec);\r
+                         if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))\r
+                   {\r
+                   
+             outl(0,devpriv->s_BoardInfos.ui_Address + 20 + (b_OutputChannel * 4) + (64 * b_ModulNbr));\r
+                   } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))\r
+                else\r
+                   {\r
+                   /****************************************/\r
+                   /* The selected digital output is wrong */\r
+                   /****************************************/\r
+\r                   DPRINTK("The selected digital output is wrong\n"); 
+                   i_ReturnValue = -4;\r
+\r
+                   } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))\r
+\r
+                 break;\r
+\r
+                 case APCI1710_CHRONO_SET_CHANNELON:\r
+\r
+                b_OutputChannel = (BYTE) CR_CHAN(insn->chanspec);\r
+                if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))\r
+                   {\r
+                   
+                        outl(1,devpriv->s_BoardInfos.ui_Address + 20 + (b_OutputChannel * 4) + (64 * b_ModulNbr));\r
+                   } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))\r
+                else\r
+                   {\r
+                   /****************************************/\r
+                   /* The selected digital output is wrong */\r
+                   /****************************************/\r
+\r                      DPRINTK("The selected digital output is wrong\n");
+                   i_ReturnValue = -4;\r
+\r
+                   } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))\r
+\r
+                       break;\r
+                 \r
+                 case APCI1710_CHRONO_READ_CHANNEL :\r
+                /**********************************/\r
+                /* Test the digital input channel */\r
+                /**********************************/\r
+                pb_ChannelStatus = (PBYTE) &data[0];\r
+                b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);\r
+                \r
+                if ((b_InputChannel >= 0) && (b_InputChannel <= 2))\r
+                   {\r
+                   \r
+                        dw_Status = inl(devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));\r
+\r
+                   *pb_ChannelStatus = (BYTE) (((dw_Status >> b_InputChannel) & 1) ^ 1);\r
+                   } // if ((b_InputChannel >= 0) && (b_InputChannel <= 2))\r
+                else\r
+                   {\r
+                   /***************************************/\r
+                   /* The selected digital input is wrong */\r
+                   /***************************************/\r
+\r                      DPRINTK("The selected digital input is wrong\n");
+                   i_ReturnValue = -4;\r
+                   } // if ((b_InputChannel >= 0) && (b_InputChannel <= 2))\r
+\r
+                 break;\r
+\r
+                 case APCI1710_CHRONO_READ_PORT :\r
+\r
+                       pb_PortValue = (PBYTE) &data[0];\r
+\r
+                       
+                       dw_Status = inl(devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));\r
+\r
+                   *pb_PortValue = (BYTE) ((dw_Status & 0x7) ^ 7);\r
+                         break;\r
+                 }\r
+                }\r
+             else\r
+                {\r
+                /*******************************/\r
+                /* Chronometer not initialised */\r
+                /*******************************/\r
+\r               DPRINTK("Chronometer not initialised\n");      
+                i_ReturnValue = -5;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a Chronometer module */\r
+             /******************************************/\r
+\r             DPRINTK("The module is not a Chronometer module\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+}\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Chrono.h b/comedi/drivers/addi-data/APCI1710_Chrono.h
new file mode 100644 (file)
index 0000000..7d8833b
--- /dev/null
@@ -0,0 +1,78 @@
+\r\r
+\r
+\r
+#define APCI1710_30MHZ           30\r
+#define APCI1710_33MHZ           33\r
+#define APCI1710_40MHZ           40\r
+
+\r
+#define APCI1710_SINGLE     0\r
+#define APCI1710_CONTINUOUS 1\r
+\r
+\r
+#define APCI1710_CHRONO_PROGRESS_STATUS                0\r
+#define APCI1710_CHRONO_READVALUE                      1\r
+#define APCI1710_CHRONO_CONVERTVALUE           2\r
+#define APCI1710_CHRONO_READINTERRUPT       3
+\r
+#define APCI1710_CHRONO_SET_CHANNELON                  0\r
+#define APCI1710_CHRONO_SET_CHANNELOFF         1\r
+#define APCI1710_CHRONO_READ_CHANNEL           2\r
+#define APCI1710_CHRONO_READ_PORT                      3\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                  CHRONOMETER INISIALISATION FUNCTION   |\r
++----------------------------------------------------------------------------+\r */\r
+\r
+INT i_APCI1710_InsnConfigInitChrono(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       CHRONOMETER READ FUNCTION                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+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);
+
+
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION                  |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Dig_io.c b/comedi/drivers/addi-data/APCI1710_Dig_io.c
new file mode 100644 (file)
index 0000000..c39d304
--- /dev/null
@@ -0,0 +1,988 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : DIG_IO.C        |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 16.06.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 digital I/O module                          |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  | 16/06/98 | S. Weber  | Digital input / output implementation          |\r
+  |----------|-----------|------------------------------------------------|\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+#include "APCI1710_Dig_io.h"\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev, |\r
+|                                              comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)|\r
++----------------------------------------------------------------------------+\r
+| Task              : Configure the digital I/O operating mode from selected |\r
+|                     module  (b_ModulNbr). You must calling this function be|\r
+|                     for you call any other function witch access of digital|\r
+|                     I/O.                                                   |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  :                                                                                                       |\r
+|                  BYTE_ b_ModulNbr      data[0]: Module number to               |\r
+|                                             configure (0 to 3)             |\r
+|                     BYTE_ b_ChannelAMode data[1]  : Channel A mode selection       |\r
+|                                             0 : Channel used for digital   |\r
+|                                                 input                      |\r
+|                                             1 : Channel used for digital   |\r
+|                                                 output                     |\r
+|                     BYTE_ b_ChannelBMode data[2] : Channel B mode selection       |\r
+|                                             0 : Channel used for digital   |\r
+|                                                 input                      |\r
+|                                             1 : Channel used for digital   |\r
+|                                                 output                                        |                                          \r
+                                               data[0]   memory on/off\r
+Activates and deactivates the digital output memory. \r
+                                               After having      |\r
+|                 called up this function with memory on,the output you have previously|\r
+|                     activated with the function are not reset\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a digital I/O module              |\r
+|                    -4: Bi-directional channel A configuration error        |\r
+|                    -5: Bi-directional channel B configuration error        |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+    {\r
+       BYTE   b_ModulNbr,b_ChannelAMode,b_ChannelBMode ;
+        BYTE   b_MemoryOnOff,b_ConfigType;\r
+       INT    i_ReturnValue = 0;\r
+       DWORD  dw_WriteConfig = 0;\r
+       
+       b_ModulNbr              =       (BYTE) CR_AREF(insn->chanspec);
+        b_ConfigType\r   =   (BYTE) data[0];// Memory or  Init
+       b_ChannelAMode  =       (BYTE) data[1];\r
+       b_ChannelBMode  =       (BYTE) data[2];\r
+        b_MemoryOnOff   =      (BYTE) data[1]; // if memory operation 
+       i_ReturnValue   =   insn->n;\r
+
+  
+               /**************************/\r
+               /* Test the module number */\r
+               /**************************/\r
+\r
+               if (b_ModulNbr >= 4)\r
+               {\r
+                       DPRINTK("Module Number invalid\n");\r
+                       i_ReturnValue = -2;
+                    return i_ReturnValue;   \r
+               }       \r
+            switch(b_ConfigType)
+              {
+               case APCI1710_DIGIO_MEMORYONOFF:        
+\r
+               if(b_MemoryOnOff) // If Memory ON\r
+               {\r
+                /****************************/\r
+                /* Set the output memory on */\r
+                /****************************/\r
+\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_DigitalIOInfo.\r
+                b_OutputMemoryEnabled = 1;\r
+\r
+                /***************************/\r
+                /* Clear the output memory */\r
+                /***************************/\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_DigitalIOInfo.\r
+                dw_OutputMemory = 0;\r
+               }\r
+               else   // If memory off\r
+               {\r
+                /*****************************/\r
+                /* Set the output memory off */\r
+                /*****************************/\r
+\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_DigitalIOInfo.\r
+                b_OutputMemoryEnabled = 0;     \r
+               }\r
+               break;
+
+        case APCI1710_DIGIO_INIT:
+            
+       /*******************************/\r
+       /* Test if digital I/O counter */\r
+       /*******************************/\r
+\r
+        if((devpriv->s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO)\r
+       {\r
+\r
+       /***************************************************/\r
+       /* Test the bi-directional channel A configuration */\r
+       /***************************************************/\r
+          \r
+                       if ((b_ChannelAMode == 0) || (b_ChannelAMode == 1))\r
+                       {\r
+       /***************************************************/\r
+       /* Test the bi-directional channel B configuration */\r
+       /***************************************************/\r
+\r
+                               if ((b_ChannelBMode == 0) || (b_ChannelBMode == 1))\r
+                               {\r
+                                        devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                               s_DigitalIOInfo.\r
+                                               b_DigitalInit = 1;\r
+\r
+       /********************************/\r
+       /* Save channel A configuration */\r
+       /********************************/\r
+\r
+                                       devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                               s_DigitalIOInfo.\r
+                                               b_ChannelAMode = b_ChannelAMode;\r
+\r
+       /********************************/\r
+       /* Save channel B configuration */\r
+       /********************************/\r
+\r
+                                       devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                               s_DigitalIOInfo.\r
+                                               b_ChannelBMode = b_ChannelBMode;\r
+\r
+       /*****************************************/\r
+       /* Set the channel A and B configuration */\r
+       /*****************************************/\r
+\r
+\r
+                   dw_WriteConfig = (DWORD) (b_ChannelAMode | (b_ChannelBMode * 2));\r
+\r
+       /***************************/\r
+       /* Write the configuration */\r
+       /***************************/\r
+\r
+                        outl(dw_WriteConfig,devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));\r
+\r
+                       }\r
+            else\r
+                       {\r
+       /************************************************/\r
+       /* Bi-directional channel B configuration error */\r
+       /************************************************/      \r
+                        DPRINTK("Bi-directional channel B configuration error\n");     \r
+                        i_ReturnValue = -5;  \r
+                       }               \r
+\r
+               }\r
+        else\r
+                {\r
+       /************************************************/\r
+       /* Bi-directional channel A configuration error */\r
+       /************************************************/\r
+                       DPRINTK("Bi-directional channel A configuration error\n");      \r
+                       i_ReturnValue = -4; \r
+                \r
+                } \r
+\r
+       }\r
+       else\r
+        {\r
+       /******************************************/\r
+       /* The module is not a digital I/O module */\r
+       /******************************************/\r
+                       DPRINTK("The module is not a digital I/O module\n");    \r
+                       i_ReturnValue = -3;\r
+     }
+    } // end of Switch 
+     printk("Return Value %d\n",i_ReturnValue);  \r
+     return i_ReturnValue;\r
+}\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                            INPUT FUNCTIONS                                 |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+\r
+|INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice \r
+*s,    comedi_insn *insn,lsampl_t *data)\r
+\r
++----------------------------------------------------------------------------+\r
+| Task              : Read the status from selected digital I/O digital input|\r
+|                     (b_InputChannel)                                       |\r
++----------------------------------------------------------------------------|\r
+\r
+  \r
+|\r
+|  BYTE_ b_ModulNbr  CR_AREF(chanspec)          : Selected module number   |\r
+|                                                   (0 to 3)                 |\r
+|  BYTE_ b_InputChannel CR_CHAN(chanspec)        : Selection from digital   |\r
+|                                                   input ( 0 to 6)          |\r
+|                                                      0 : Channel C         |\r
+|                                                      1 : Channel D         |\r
+|                                                      2 : Channel E         |\r
+|                                                      3 : Channel F         |\r
+|                                                      4 : Channel G         |\r
+|                                                      5 : Channel A         |\r
+|                                                      6 : Channel B   \r
+\r
+  \r
+       |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters :                                   data[0]   : Digital input channel    |\r
+|                                                   status                   |\r
+|                                                   0 : Channle is not active|\r
+|                                                   1 : Channle is active    |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a digital I/O module              |\r
+|                    -4: The selected digital I/O digital input is wrong     |\r
+|                    -5: Digital I/O not initialised                         |\r
+|                    -6: The digital channel A is used for output            |\r
+|                    -7: The digital channel B is used for output            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+//_INT_   i_APCI1710_ReadDigitalIOChlValue      (BYTE_    b_BoardHandle,\r
+//                                            BYTE_    b_ModulNbr,\r
+//                                            BYTE_    b_InputChannel,\r
+//\r
+//                                            PBYTE_  pb_ChannelStatus)\r
+INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+{\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg;\r
+       BYTE    b_ModulNbr,b_InputChannel;\r
+        PBYTE  pb_ChannelStatus;
+       b_ModulNbr              = (BYTE) CR_AREF(insn->chanspec);\r
+        b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
+        data[0]=0;\r
+        pb_ChannelStatus= (PBYTE) &data[0];
+        i_ReturnValue = insn->n;\r
+\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if digital I/O counter */\r
+          /*******************************/\r
+\r
+          if ((devpriv->s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO)\r
+             {\r
+             /******************************************/\r
+             /* Test the digital imnput channel number */\r
+             /******************************************/\r
+\r
+             if ((b_InputChannel >= 0) && (b_InputChannel <= 6))\r
+                {\r
+                /**********************************************/\r
+                /* Test if the digital I/O module initialised */\r
+                /**********************************************/\r
+\r
+                if (devpriv->s_ModuleInfo[b_ModulNbr].s_DigitalIOInfo.b_DigitalInit == 1)\r
+                   {\r
+                   /**********************************/\r
+                   /* Test if channel A or channel B */\r
+                   /**********************************/\r
+\r
+                   if (b_InputChannel > 4)\r
+                      {\r
+                      /*********************/\r
+                      /* Test if channel A */\r
+                      /*********************/\r
+\r
+                      if (b_InputChannel == 5)\r
+                         {\r
+                         /***************************/\r
+                         /* Test the channel A mode */\r
+                         /***************************/\r
+\r
+                         if (devpriv->s_ModuleInfo [b_ModulNbr].s_DigitalIOInfo.b_ChannelAMode != 0)\r
+                            {\r
+                            /********************************************/\r
+                            /* The digital channel A is used for output */\r
+                            /********************************************/\r
+\r
+                            i_ReturnValue = -6;\r
+                            }\r
+                         } // if (b_InputChannel == 5)\r
+                      else\r
+                         {\r
+                         /***************************/\r
+                         /* Test the channel B mode */\r
+                         /***************************/\r
+\r
+                         if (devpriv->s_ModuleInfo [b_ModulNbr].s_DigitalIOInfo.b_ChannelBMode != 0)\r
+                            {\r
+                            /********************************************/\r
+                            /* The digital channel B is used for output */\r
+                            /********************************************/\r
+\r
+                            i_ReturnValue = -7;\r
+                            }\r
+                         } // if (b_InputChannel == 5)\r
+                      } // if (b_InputChannel > 4)\r
+\r
+                   /***********************/\r
+                   /* Test if error occur */\r
+                   /***********************/\r
+\r
+                   if (i_ReturnValue >= 0)\r
+                      {\r
+                      /**************************/\r
+                      /* Read all digital input */\r
+                      /**************************/\r
+\r
+                      //INPDW (ps_APCI1710Variable->\r
+                          //   s_Board [b_BoardHandle].\r
+                          //   s_BoardInfos.\r
+                           //  ui_Address + (64 * b_ModulNbr),\r
+                            // &dw_StatusReg);\r
+\r
+                           dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+\r
+                      *pb_ChannelStatus = (BYTE) ((dw_StatusReg ^ 0x1C) >> b_InputChannel) & 1;\r
+                        
+                      } // if (i_ReturnValue == 0)\r
+                   }\r
+                else\r
+                   {\r
+                   /*******************************/\r
+                   /* Digital I/O not initialised */\r
+                   /*******************************/\r
+                       DPRINTK("Digital I/O not initialised\n");\r
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /********************************/\r
+                /* Selected digital input error */\r
+                /********************************/\r
+                DPRINTK("Selected digital input error\n"); \r
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a digital I/O module */\r
+             /******************************************/\r
+                 DPRINTK("The module is not a digital I/O module\n"); \r
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+               DPRINTK("Module number error\n"); \r
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                            OUTPUT FUNCTIONS                                |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device \r
+|*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)\r
+\r
++----------------------------------------------------------------------------+\r
+| Task              : Sets or resets the output witch has been passed with the         |\r
+|                     parameter b_Channel. Setting an output means setting   |\r
+|                     an ouput high.                                         |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |\r
+|                     BYTE_ b_ModulNbr (aref )    : Selected module number (0 to 3)|\r
+|                     BYTE_ b_OutputChannel (CR_CHAN) : Selection from digital output  |\r
+|                                             channel (0 to 2)               |\r
+|                                                0 : Channel H               |\r
+|                                                1 : Channel A               |\r
+|                                                2 : Channel B               |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a digital I/O module              |\r
+|                    -4: The selected digital output is wrong                |\r
+|                    -5: digital I/O not initialised see function            |\r
+|                        " i_APCI1710_InitDigitalIO"                         |\r
+|                    -6: The digital channel A is used for input             |\r
+|                    -7: The digital channel B is used for input \r
+                                        -8: Digital Output Memory OFF.                          |\r
+|                        Use previously the function                         |\r
+|                        "i_APCI1710_SetDigitalIOMemoryOn".            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+//_INT_   i_APCI1710_SetDigitalIOChlOn    (BYTE_ b_BoardHandle,\r
+//                                      BYTE_ b_ModulNbr,\r
+//                                      BYTE_ b_OutputChannel)\r
+INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_WriteValue;\r
+       BYTE b_ModulNbr,b_OutputChannel;\r
+       i_ReturnValue   =       insn->n; \r
+       b_ModulNbr              =   CR_AREF(insn->chanspec);  \r
+       b_OutputChannel =   CR_CHAN(insn->chanspec);  \r
+       \r
+       
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if digital I/O counter */\r
+          /*******************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO)\r
+             {\r
+             /**********************************************/\r
+             /* Test if the digital I/O module initialised */\r
+             /**********************************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_DigitalIOInfo.\r
+                 b_DigitalInit == 1)\r
+                {\r
+                /******************************************/\r
+                /* Test the digital output channel number */\r
+                /******************************************/\r
+\r
+                switch (b_OutputChannel)\r
+                   {\r
+                   /*************/\r
+                   /* Channel H */\r
+                   /*************/\r
+\r
+                   case 0:\r
+                        break;\r
+\r
+                   /*************/\r
+                   /* Channel A */\r
+                   /*************/\r
+\r
+                   case 1:\r
+                        if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_DigitalIOInfo.\r
+                            b_ChannelAMode != 1)\r
+                           {\r
+                           /*******************************************/\r
+                           /* The digital channel A is used for input */\r
+                           /*******************************************/\r
+\r
+                           i_ReturnValue = -6;\r
+                           }\r
+                        break;\r
+\r
+                   /*************/\r
+                   /* Channel B */\r
+                   /*************/\r
+\r
+                   case 2:\r
+                        if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_DigitalIOInfo.\r
+                            b_ChannelBMode != 1)\r
+                           {\r
+                           /*******************************************/\r
+                           /* The digital channel B is used for input */\r
+                           /*******************************************/\r
+\r
+                           i_ReturnValue = -7;\r
+                           }\r
+                        break;\r
+\r
+                   default :\r
+                        /****************************************/\r
+                        /* The selected digital output is wrong */\r
+                        /****************************************/\r
+\r
+                        i_ReturnValue = -4;\r
+                        break;\r
+                   }\r
+\r
+                /***********************/\r
+                /* Test if error occur */\r
+                /***********************/\r
+\r
+                if (i_ReturnValue >= 0)\r
+                   {\r
+            \r
+                        \r
+                       /*********************************/\r
+                   /* Test if set channel ON        */\r
+                   /*********************************/ \r
+                        if(data[0])\r
+                        {               \r
+                   /*********************************/\r
+                   /* Test if output memory enabled */\r
+                   /*********************************/\r
+\r
+                   if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                       s_DigitalIOInfo.\r
+                       b_OutputMemoryEnabled == 1)\r
+                      {\r
+                      dw_WriteValue = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                      s_DigitalIOInfo.\r
+                                      dw_OutputMemory | (1 << b_OutputChannel);\r
+\r
+                      devpriv->s_ModuleInfo [b_ModulNbr].\r
+                      s_DigitalIOInfo.\r
+                      dw_OutputMemory = dw_WriteValue;\r
+                      }\r
+                   else\r
+                      {\r
+                      dw_WriteValue = 1 << b_OutputChannel;\r
+                      }\r
+                        } // set channel off\r
+             else\r
+                        {\r
+                               if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                       s_DigitalIOInfo.\r
+                       b_OutputMemoryEnabled == 1)\r
+                      {\r
+                      dw_WriteValue = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                      s_DigitalIOInfo.\r
+                                      dw_OutputMemory & (0xFFFFFFFFUL - (1 << b_OutputChannel));\r
+\r
+                      devpriv->s_ModuleInfo [b_ModulNbr].s_DigitalIOInfo.dw_OutputMemory = dw_WriteValue;\r
+                      }\r
+                   else\r
+                      {\r
+                      /*****************************/\r
+                      /* Digital Output Memory OFF */\r
+                      /*****************************/\r
+                          // +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn"\r
+                      i_ReturnValue = -8;\r
+                      }\r
+\r
+             }\r
+                   /*******************/\r
+                   /* Write the value */\r
+                   /*******************/\r
+\r
+                   //OUTPDW (ps_APCI1710Variable->\r
+                       //    s_Board [b_BoardHandle].\r
+                        //   s_BoardInfos.\r
+                        //   ui_Address + (64 * b_ModulNbr),\r
+                        //   dw_WriteValue);\r
+                       outl(dw_WriteValue,devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*******************************/\r
+                /* Digital I/O not initialised */\r
+                /*******************************/\r
+\r
+                i_ReturnValue = -5;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a digital I/O module */\r
+             /******************************************/\r
+\r
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+    \r
+|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice \r
+       *s,     comedi_insn *insn,lsampl_t *data)\r
++----------------------------------------------------------------------------+\r
+| Task              : write:\r
+                                         Sets or resets one or several outputs from port.                 |\r
+|                     Setting an output means setting an output high.        |\r
+|                     If you have switched OFF the digital output memory     |\r
+|                     (OFF), all the other output are set to "0".            \r
+\r
+|                      read:\r
+                                         Read the status from digital input port                |\r
+|                     from selected digital I/O module (b_ModulNbr)   \r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : \r
+       BYTE_ b_BoardHandle   : Handle of board APCI-1710      |\r
+|   BYTE_ b_ModulNbr  CR_AREF(aref)    : Selected module number (0 to 3)|\r
+|   BYTE_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 )        \r
+|                       data[0]           read or write port\r
+                        data[1]            if write then indicate ON or OFF\r
+\r
+                        if read : data[1] will return port status.\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :\r
+\r
+                INPUT :\r
+   \r
+                                         0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a digital I/O module              |\r
+|                    -4: Digital I/O not initialised                           \r
+\r
+                               OUTPUT:   0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a digital I/O module              |\r
+|                    -4: Output value wrong                                  |\r
+|                    -5: digital I/O not initialised see function            |\r
+|                        " i_APCI1710_InitDigitalIO"                         |\r
+|                    -6: The digital channel A is used for input             |\r
+|                    -7: The digital channel B is used for input \r
+                                       -8: Digital Output Memory OFF.                          |\r
+|                        Use previously the function                         |\r
+|                        "i_APCI1710_SetDigitalIOMemoryOn".               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+//_INT_   i_APCI1710_SetDigitalIOPortOn   (BYTE_ b_BoardHandle,\r
+//                                      BYTE_ b_ModulNbr,\r
+//                                      BYTE_ b_PortValue)\r
+INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_WriteValue,dw_StatusReg;\r
+       BYTE b_ModulNbr,b_PortValue;
+        BYTE b_PortOperation,b_PortOnOFF;
+\r       PBYTE pb_PortValue;
+          
+       b_ModulNbr              = (BYTE) CR_AREF(insn->chanspec);\r
+       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\r
+       i_ReturnValue   = insn->n;\r
+        pb_PortValue    = (PBYTE) &data[0];\r// if input then read value
+       
+\r
+\r
+    switch(b_PortOperation)\r
+       {\r
+    case APCI1710_INPUT  :\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if digital I/O counter */\r
+          /*******************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO)\r
+             {\r
+             /**********************************************/\r
+             /* Test if the digital I/O module initialised */\r
+             /**********************************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_DigitalIOInfo.b_DigitalInit == 1)\r
+                {\r
+                /**************************/\r
+                /* Read all digital input */\r
+                /**************************/\r
+\r
+                //INPDW (ps_APCI1710Variable->\r
+               //      s_Board [b_BoardHandle].\r
+               //      s_BoardInfos.\r
+               //      ui_Address + (64 * b_ModulNbr),\r
+               //      &dw_StatusReg);\r
+\r
+          dw_StatusReg=inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+                *pb_PortValue = (BYTE) (dw_StatusReg ^ 0x1C);\r
+               
+                }\r
+             else\r
+                {\r
+                /*******************************/\r
+                /* Digital I/O not initialised */\r
+                /*******************************/\r
+\r
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a digital I/O module */\r
+             /******************************************/\r
+\r
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r
+          i_ReturnValue = -2;\r
+          }\r
+       \r
+         break;\r
+\r
+       case APCI1710_OUTPUT :\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if digital I/O counter */\r
+          /*******************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO)\r
+             {\r
+             /**********************************************/\r
+             /* Test if the digital I/O module initialised */\r
+             /**********************************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_DigitalIOInfo.\r
+                 b_DigitalInit == 1)\r
+                {\r
+                /***********************/\r
+                /* Test the port value */\r
+                /***********************/\r
+\r
+                if ((b_PortValue >= 0) && (b_PortValue <= 7))\r
+                   {\r
+                   /***********************************/\r
+                   /* Test the digital output channel */\r
+                   /***********************************/\r
+\r
+                   /**************************/\r
+                   /* Test if channel A used */\r
+                   /**************************/\r
+\r
+                   if ((b_PortValue & 2) == 2)\r
+                      {\r
+                      if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                          s_DigitalIOInfo.\r
+                          b_ChannelAMode != 1)\r
+                         {\r
+                         /*******************************************/\r
+                         /* The digital channel A is used for input */\r
+                         /*******************************************/\r
+\r
+                         i_ReturnValue = -6;\r
+                         }\r
+                      } // if ((b_PortValue & 2) == 2)\r
+\r
+                   /**************************/\r
+                   /* Test if channel B used */\r
+                   /**************************/\r
+\r
+                   if ((b_PortValue & 4) == 4)\r
+                      {\r
+                      if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                          s_DigitalIOInfo.\r
+                          b_ChannelBMode != 1)\r
+                         {\r
+                         /*******************************************/\r
+                         /* The digital channel B is used for input */\r
+                         /*******************************************/\r
+\r
+                         i_ReturnValue = -7;\r
+                         }\r
+                      } // if ((b_PortValue & 4) == 4)\r
+\r
+                   /***********************/\r
+                   /* Test if error occur */\r
+                   /***********************/\r
+\r
+                   if (i_ReturnValue >= 0)\r
+                      {\r
+                          \r
+                         //if(data[1])\r
+                         //{\r
+               switch(b_PortOnOFF)\r
+               { \r
+                          /*********************************/\r
+                      /* Test if set Port ON                   */\r
+                      /*********************************/\r
+\r
+                          case APCI1710_ON :\r
+\r
+                      /*********************************/\r
+                      /* Test if output memory enabled */\r
+                      /*********************************/\r
+\r
+                      if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                          s_DigitalIOInfo.\r
+                          b_OutputMemoryEnabled == 1)\r
+                         {\r
+                         dw_WriteValue = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                         s_DigitalIOInfo.\r
+                                         dw_OutputMemory | b_PortValue;\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_DigitalIOInfo.dw_OutputMemory = dw_WriteValue;\r
+                         }\r
+                      else\r
+                         {\r
+                         dw_WriteValue = b_PortValue;\r
+                         }\r
+              break;\r
+\r
+                       // If Set PORT  OFF  \r
+                       case APCI1710_OFF:\r
+                       \r
+                          /*********************************/\r
+                      /* Test if output memory enabled */\r
+                      /*********************************/\r
+\r
+                      if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                          s_DigitalIOInfo.b_OutputMemoryEnabled == 1)\r
+                         {\r
+                         dw_WriteValue = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                         s_DigitalIOInfo.\r
+                                         dw_OutputMemory & (0xFFFFFFFFUL - b_PortValue);\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_DigitalIOInfo.\r
+                         dw_OutputMemory = dw_WriteValue;\r
+                         }\r
+                      else\r
+                         {\r
+                         /*****************************/\r
+                         /* Digital Output Memory OFF */\r
+                         /*****************************/\r
+\r
+                         i_ReturnValue = -8;\r
+                         }\r
+                       } // switch\r
+\r
+                      /*******************/\r
+                      /* Write the value */\r
+                      /*******************/\r
+\r
+                    //  OUTPDW (ps_APCI1710Variable->\r
+                        //      s_Board [b_BoardHandle].\r
+                        //      s_BoardInfos.\r
+                        //      ui_Address + (64 * b_ModulNbr),\r
+                        //      dw_WriteValue);\r
+                               outl(dw_WriteValue,devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /**********************/\r
+                   /* Output value wrong */\r
+                   /**********************/\r
+\r
+                   i_ReturnValue = -4;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*******************************/\r
+                /* Digital I/O not initialised */\r
+                /*******************************/\r
+\r
+                i_ReturnValue = -5;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a digital I/O module */\r
+             /******************************************/\r
+\r
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r
+          i_ReturnValue = -2;\r
+          }\r
+       break;\r
+\r
+       default:\r
+               i_ReturnValue = -9;\r
+               DPRINTK("NO INPUT/OUTPUT specified\n");\r
+  } //switch INPUT / OUTPUT\r
+       return (i_ReturnValue);\r
+}\r
+\r
+\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Dig_io.h b/comedi/drivers/addi-data/APCI1710_Dig_io.h
new file mode 100644 (file)
index 0000000..59c79b5
--- /dev/null
@@ -0,0 +1,38 @@
+\r
+\r
+\r
+#define                APCI1710_ON                             1                       // Digital  Output ON or OFF\r
+#define                APCI1710_OFF                    0\r
+\r
+\r
+#define                APCI1710_INPUT                  0               // Digital I/O\r
+#define                APCI1710_OUTPUT                 1\r
+\r
+#define         APCI1710_DIGIO_MEMORYONOFF  0x10       //      
+#define         APCI1710_DIGIO_INIT         0x11\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       DIGITAL I/O INISIALISATION FUNCTION                  |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+       INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                            INPUT OUTPUT  FUNCTIONS                         |\r
++----------------------------------------------------------------------------+\r
+*/\r
+INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_INCCPT.c b/comedi/drivers/addi-data/APCI1710_INCCPT.c
new file mode 100644 (file)
index 0000000..5751bca
--- /dev/null
@@ -0,0 +1,5376 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : INC_CPT.C       |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 08.01.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 incremental counter module                  |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  |          |           |                                                |\r
+  |----------|-----------|------------------------------------------------|\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+  | 29/06/01 | Guinot C. | - 1100/0231 -> 0701/0232                       |\r
+  |          |           | See i_APCI1710_DisableFrequencyMeasurement     |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+#include "APCI1710_INCCPT.h"\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| INT  i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)\r
+\r
++----------------------------------------------------------------------------+\r
+| Task              : Configuration function for INC_CPT                             |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  :                                                                                                           |      \r
++----------------------------------------------------------------------------+\r
+| Output Parameters : *data\r
++----------------------------------------------------------------------------+\r
+| Return Value      :                 |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+INT    i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)\r
+{ \r
+       UINT  ui_ConfigType; \r
+       INT    i_ReturnValue = 0;\r
+       ui_ConfigType=CR_CHAN(insn->chanspec);\r
+\r       devpriv->tsk_Current=current; // Save the current process task structure
+       switch(ui_ConfigType)\r
+       {\r
+       case    APCI1710_INCCPT_INITCOUNTER     :                               \r
+                       i_ReturnValue =i_APCI1710_InitCounter (dev,\r
+                                       CR_AREF(insn->chanspec),\r
+                                       (BYTE) data[0],\r
+                                       (BYTE) data[1],\r
+                                       (BYTE) data[2],\r
+                                       (BYTE) data[3],\r
+                                       (BYTE) data[4]);\r
+                       break;\r
+\r
+       case    APCI1710_INCCPT_COUNTERAUTOTEST:\r
+                       i_ReturnValue =i_APCI1710_CounterAutoTest (dev,\r
+                                       (PBYTE)   &data[0]);\r
+                       break;\r
+\r
+       case    APCI1710_INCCPT_INITINDEX:\r
+                       i_ReturnValue =i_APCI1710_InitIndex    (dev,\r
+                                       CR_AREF(insn->chanspec),\r
+                                       (BYTE) data[0],\r
+                                       (BYTE) data[1],\r
+                                       (BYTE) data[2],\r
+                                       (BYTE) data[3]);\r
+                       break;\r
+\r
+       case    APCI1710_INCCPT_INITREFERENCE:\r
+                       i_ReturnValue =i_APCI1710_InitReference  (dev,\r
+                                       CR_AREF(insn->chanspec),\r
+                                       (BYTE) data[0]);\r
+                       break;\r
+\r
+       case    APCI1710_INCCPT_INITEXTERNALSTROBE:             \r
+                       i_ReturnValue =i_APCI1710_InitExternalStrobe    (dev,\r
+                                       CR_AREF(insn->chanspec),\r
+                                       (BYTE) data[0],\r
+                                       (BYTE) data[1]);\r
+                       break;\r
+\r
+       case    APCI1710_INCCPT_INITCOMPARELOGIC:\r
+                       i_ReturnValue =i_APCI1710_InitCompareLogic     (dev,\r
+                                       CR_AREF(insn->chanspec),\r
+                                       (UINT) data[0]);\r
+                       break;\r
+\r
+       case    APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:\r
+                       i_ReturnValue =i_APCI1710_InitFrequencyMeasurement      (dev,\r
+                                       CR_AREF(insn->chanspec),\r
+                                       (BYTE) data[0],\r
+                                       (BYTE) data[1],\r
+                                       (ULONG) data[2],\r
+                                       (PULONG) &data[0]);\r
+                       break;\r
+\r
+    default: \r
+                   printk("Insn Config : Config Parameter Wrong\n");\r
+\r
+       }\r
+\r
+    if(i_ReturnValue>=0) i_ReturnValue =insn->n;\r
+       return (i_ReturnValue);\r
+}\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitCounter                           |\r
+|                               (BYTE_          b_BoardHandle,               |\r
+|                                BYTE_          b_ModulNbr,                  |\r
+|                                BYTE_          b_CounterRange,              |\r
+|                                BYTE_          b_FirstCounterModus,         |\r
+|                                BYTE_          b_FirstCounterOption,        |\r
+|                                BYTE_          b_SecondCounterModus,        |\r
+|                                BYTE_          b_SecondCounterOption)       |\r
++----------------------------------------------------------------------------+\r
+| Task              : Configure the counter operating mode from selected     |\r
+|                     module (b_ModulNbr). You must calling this function be |\r
+|                     for you call any other function witch access of        |\r
+|                     counters.                                              |\r
+|                                                                            |\r
+|                          Counter range                                     |\r
+|                          -------------                                     |\r
+| +------------------------------------+-----------------------------------+ |\r
+| | Parameter       Passed value       |        Description                | |\r
+| |------------------------------------+-----------------------------------| |\r
+| |b_ModulNbr   APCI1710_16BIT_COUNTER |  The module is configured for     | |\r
+| |                                    |  two 16-bit counter.              | |\r
+| |                                    |  - b_FirstCounterModus and        | |\r
+| |                                    |    b_FirstCounterOption           | |\r
+| |                                    |    configure the first 16 bit     | |\r
+| |                                    |    counter.                       | |\r
+| |                                    |  - b_SecondCounterModus and       | |\r
+| |                                    |    b_SecondCounterOption          | |\r
+| |                                    |    configure the second 16 bit    | |\r
+| |                                    |    counter.                       | |\r
+| |------------------------------------+-----------------------------------| |\r
+| |b_ModulNbr   APCI1710_32BIT_COUNTER |  The module is configured for one | |\r
+| |                                    |  32-bit counter.                  | |\r
+| |                                    |  - b_FirstCounterModus and        | |\r
+| |                                    |    b_FirstCounterOption           | |\r
+| |                                    |    configure the 32 bit counter.  | |\r
+| |                                    |  - b_SecondCounterModus and       | |\r
+| |                                    |    b_SecondCounterOption          | |\r
+| |                                    |    are not used and have no       | |\r
+| |                                    |    importance.                    | |\r
+| +------------------------------------+-----------------------------------+ |\r
+|                                                                            |\r
+|                      Counter operating mode                                |\r
+|                      ----------------------                                |\r
+|                                                                            |\r
+| +--------------------+-------------------------+-------------------------+ |\r
+| |    Parameter       |     Passed value        |    Description          | |\r
+| |--------------------+-------------------------+-------------------------| |\r
+| |b_FirstCounterModus | APCI1710_QUADRUPLE_MODE | In the quadruple mode,  | |\r
+| |       or           |                         | the edge analysis       | |\r
+| |b_SecondCounterModus|                         | circuit generates a     | |\r
+| |                    |                         | counting pulse from     | |\r
+| |                    |                         | each edge of 2 signals  | |\r
+| |                    |                         | which are phase shifted | |\r
+| |                    |                         | in relation to each     | |\r
+| |                    |                         | other.                  | |\r
+| |--------------------+-------------------------+-------------------------| |\r
+| |b_FirstCounterModus |   APCI1710_DOUBLE_MODE  | Functions in the same   | |\r
+| |       or           |                         | way as the quadruple    | |\r
+| |b_SecondCounterModus|                         | mode, except that only  | |\r
+| |                    |                         | two of the four edges   | |\r
+| |                    |                         | are analysed per        | |\r
+| |                    |                         | period                  | |\r
+| |--------------------+-------------------------+-------------------------| |\r
+| |b_FirstCounterModus |   APCI1710_SIMPLE_MODE  | Functions in the same   | |\r
+| |       or           |                         | way as the quadruple    | |\r
+| |b_SecondCounterModus|                         | mode, except that only  | |\r
+| |                    |                         | one of the four edges   | |\r
+| |                    |                         | is analysed per         | |\r
+| |                    |                         | period.                 | |\r
+| |--------------------+-------------------------+-------------------------| |\r
+| |b_FirstCounterModus |   APCI1710_DIRECT_MODE  | In the direct mode the  | |\r
+| |       or           |                         | both edge analysis      | |\r
+| |b_SecondCounterModus|                         | circuits are inactive.  | |\r
+| |                    |                         | The inputs A, B in the  | |\r
+| |                    |                         | 32-bit mode or A, B and | |\r
+| |                    |                         | C, D in the 16-bit mode | |\r
+| |                    |                         | represent, each, one    | |\r
+| |                    |                         | clock pulse gate circuit| |\r
+| |                    |                         | There by frequency and  | |\r
+| |                    |                         | pulse duration          | |\r
+| |                    |                         | measurements can be     | |\r
+| |                    |                         | performed.              | |\r
+| +--------------------+-------------------------+-------------------------+ |\r
+|                                                                            |\r
+|                                                                            |\r
+|       IMPORTANT!                                                           |\r
+|       If you have configured the module for two 16-bit counter, a mixed    |\r
+|       mode with a counter in quadruple/double/single mode                  |\r
+|       and the other counter in direct mode is not possible!                |\r
+|                                                                            |\r
+|                                                                            |\r
+|         Counter operating option for quadruple/double/simple mode          |\r
+|         ---------------------------------------------------------          |\r
+|                                                                            |\r
+| +----------------------+-------------------------+------------------------+|\r
+| |       Parameter      |     Passed value        |  Description           ||\r
+| |----------------------+-------------------------+------------------------||\r
+| |b_FirstCounterOption  | APCI1710_HYSTERESIS_ON  | In both edge analysis  ||\r
+| |        or            |                         | circuits is available  ||\r
+| |b_SecondCounterOption |                         | one hysteresis circuit.||\r
+| |                      |                         | It suppresses each     ||\r
+| |                      |                         | time the first counting||\r
+| |                      |                         | pulse after a change   ||\r
+| |                      |                         | of rotation.           ||\r
+| |----------------------+-------------------------+------------------------||\r
+| |b_FirstCounterOption  | APCI1710_HYSTERESIS_OFF | The first counting     ||\r
+| |       or             |                         | pulse is not suppress  ||\r
+| |b_SecondCounterOption |                         | after a change of      ||\r
+| |                      |                         | rotation.              ||\r
+| +----------------------+-------------------------+------------------------+|\r
+|                                                                            |\r
+|                                                                            |\r
+|       IMPORTANT!                                                           |\r
+|       This option are only avaible if you have selected the direct mode.   |\r
+|                                                                            |\r
+|                                                                            |\r
+|               Counter operating option for direct mode                     |\r
+|               ----------------------------------------                     |\r
+|                                                                            |\r
+| +----------------------+--------------------+----------------------------+ |\r
+| |      Parameter       |     Passed value   |       Description          | |\r
+| |----------------------+--------------------+----------------------------| |\r
+| |b_FirstCounterOption  | APCI1710_INCREMENT | The counter increment for  | |\r
+| |       or             |                    | each counting pulse        | |\r
+| |b_SecondCounterOption |                    |                            | |\r
+| |----------------------+--------------------+----------------------------| |\r
+| |b_FirstCounterOption  | APCI1710_DECREMENT | The counter decrement for  | |\r
+| |       or             |                    | each counting pulse        | |\r
+| |b_SecondCounterOption |                    |                            | |\r
+| +----------------------+--------------------+----------------------------+ |\r
+|                                                                            |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|\r
+|                     BYTE_ b_ModulNbr            : Module number to         |\r
+|                                                   configure (0 to 3)       |\r
+|                     BYTE_ b_CounterRange        : Selection form counter   |\r
+|                                                   range.                   |\r
+|                     BYTE_ b_FirstCounterModus   : First counter operating  |\r
+|                                                   mode.                    |\r
+|                     BYTE_ b_FirstCounterOption  : First counter  option.   |\r
+|                     BYTE_ b_SecondCounterModus  : Second counter operating |\r
+|                                                   mode.                    |\r
+|                     BYTE_ b_SecondCounterOption : Second counter  option.  |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module is not a counter module                  |\r
+|                    -3: The selected counter range is wrong.                |\r
+|                    -4: The selected first counter operating mode is wrong. |\r
+|                    -5: The selected first counter operating option is wrong|\r
+|                    -6: The selected second counter operating mode is wrong.|\r
+|                    -7: The selected second counter operating option is     |\r
+|                        wrong.                                              |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+\r
+\r
+\r
+INT   i_APCI1710_InitCounter (comedi_device *dev,\r
+                               BYTE          b_ModulNbr,\r
+                               BYTE          b_CounterRange,\r
+                               BYTE          b_FirstCounterModus,\r
+                               BYTE          b_FirstCounterOption,\r
+                               BYTE          b_SecondCounterModus,\r
+                               BYTE          b_SecondCounterOption)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+               \r
+       /*******************************/\r
+       /* Test if incremental counter */\r
+       /*******************************/\r
+\r
+       if ((devpriv->s_BoardInfos.\r
+            dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER)\r
+          {\r
+          /**************************/\r
+          /* Test the counter range */\r
+          /**************************/\r
+\r
+          if (b_CounterRange == APCI1710_16BIT_COUNTER || b_CounterRange == APCI1710_32BIT_COUNTER)\r
+             {\r
+             /********************************/\r
+             /* Test the first counter modus */\r
+             /********************************/\r
+\r
+             if (b_FirstCounterModus == APCI1710_QUADRUPLE_MODE ||\r
+                 b_FirstCounterModus == APCI1710_DOUBLE_MODE    ||\r
+                 b_FirstCounterModus == APCI1710_SIMPLE_MODE    ||\r
+                 b_FirstCounterModus == APCI1710_DIRECT_MODE)\r
+                {\r
+                /*********************************/\r
+                /* Test the first counter option */\r
+                /*********************************/\r
+\r
+                if ((b_FirstCounterModus   == APCI1710_DIRECT_MODE   &&\r
+                     (b_FirstCounterOption == APCI1710_INCREMENT     ||\r
+                      b_FirstCounterOption == APCI1710_DECREMENT))   ||\r
+                    (b_FirstCounterModus   != APCI1710_DIRECT_MODE   &&\r
+                     (b_FirstCounterOption == APCI1710_HYSTERESIS_ON ||\r
+                      b_FirstCounterOption == APCI1710_HYSTERESIS_OFF)))\r
+                   {\r
+                   /**************************/\r
+                   /* Test if 16-bit counter */\r
+                   /**************************/\r
+\r
+                   if (b_CounterRange == APCI1710_16BIT_COUNTER)\r
+                      {\r
+                      /*********************************/\r
+                      /* Test the second counter modus */\r
+                      /*********************************/\r
+\r
+                      if ((b_FirstCounterModus != APCI1710_DIRECT_MODE      &&\r
+                           (b_SecondCounterModus == APCI1710_QUADRUPLE_MODE ||\r
+                            b_SecondCounterModus == APCI1710_DOUBLE_MODE    ||\r
+                            b_SecondCounterModus == APCI1710_SIMPLE_MODE))  ||\r
+                          (b_FirstCounterModus == APCI1710_DIRECT_MODE &&\r
+                           b_SecondCounterModus == APCI1710_DIRECT_MODE))\r
+                         {\r
+                         /**********************************/\r
+                         /* Test the second counter option */\r
+                         /**********************************/\r
+\r
+                         if ((b_SecondCounterModus   == APCI1710_DIRECT_MODE   &&\r
+                              (b_SecondCounterOption == APCI1710_INCREMENT     ||\r
+                               b_SecondCounterOption == APCI1710_DECREMENT))   ||\r
+                             (b_SecondCounterModus   != APCI1710_DIRECT_MODE   &&\r
+                              (b_SecondCounterOption == APCI1710_HYSTERESIS_ON ||\r
+                               b_SecondCounterOption == APCI1710_HYSTERESIS_OFF)))\r
+                            {\r
+                            i_ReturnValue = 0;\r
+                            }\r
+                         else\r
+                            {\r
+                            /*********************************************************/\r
+                            /* The selected second counter operating option is wrong */\r
+                            /*********************************************************/\r
+\r                        DPRINTK("The selected second counter operating option is wrong\n");
+                            i_ReturnValue = -7;\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         /*******************************************************/\r
+                         /* The selected second counter operating mode is wrong */\r
+                         /*******************************************************/\r
+\r                        DPRINTK("The selected second counter operating mode is wrong\n");
+                         i_ReturnValue = -6;\r
+                         }\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /********************************************************/\r
+                   /* The selected first counter operating option is wrong */\r
+                   /********************************************************/\r
+\r                   DPRINTK("The selected first counter operating option is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /******************************************************/\r
+                /* The selected first counter operating mode is wrong */\r
+                /******************************************************/\r
+                 DPRINTK("The selected first counter operating mode is wrong\n");\r
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /***************************************/\r
+             /* The selected counter range is wrong */\r
+             /***************************************/\r
+\r             DPRINTK("The selected counter range is wrong\n");
+             i_ReturnValue = -3;\r
+             }\r
+\r
+          /*************************/\r
+          /* Test if a error occur */\r
+          /*************************/\r
+\r
+          if (i_ReturnValue == 0)\r
+             {\r
+             /**************************/\r
+             /* Test if 16-Bit counter */\r
+             /**************************/\r
+\r
+             if (b_CounterRange == APCI1710_32BIT_COUNTER)\r
+                {\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister1 = b_CounterRange      |\r
+                                  b_FirstCounterModus |\r
+                                  b_FirstCounterOption;\r
+                }\r
+             else\r
+                {\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister1 = b_CounterRange                 |\r
+                                  (b_FirstCounterModus   & 0x5)  |\r
+                                  (b_FirstCounterOption  & 0x20) |\r
+                                  (b_SecondCounterModus  & 0xA)  |\r
+                                  (b_SecondCounterOption & 0x40);\r
+\r
+                /***********************/\r
+                /* Test if direct mode */\r
+                /***********************/\r
+\r
+                if (b_FirstCounterModus == APCI1710_DIRECT_MODE)\r
+                   {\r
+                   devpriv->\r
+                   s_ModuleInfo [b_ModulNbr].\r
+                   s_SiemensCounterInfo.\r
+                   s_ModeRegister.\r
+                   s_ByteModeRegister.\r
+                   b_ModeRegister1 = devpriv->\r
+                                     s_ModuleInfo [b_ModulNbr].\r
+                                     s_SiemensCounterInfo.\r
+                                     s_ModeRegister.\r
+                                     s_ByteModeRegister.\r
+                                     b_ModeRegister1 | APCI1710_DIRECT_MODE;\r
+                   }\r
+                }\r
+\r
+             /***************************/\r
+             /* Write the configuration */\r
+             /***************************/\r
+\r
+          
+                 outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                     s_SiemensCounterInfo.\r
+                     s_ModeRegister.\r
+                     dw_ModeRegister1_2_3_4,\r
+                         devpriv->s_BoardInfos.\r
+                     ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+\r
+             devpriv->\r
+             s_ModuleInfo [b_ModulNbr].\r
+             s_SiemensCounterInfo.\r
+             s_InitFlag.\r
+             b_CounterInit = 1;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /**************************************/\r
+          /* The module is not a counter module */\r
+          /**************************************/\r
+\r          DPRINTK("The module is not a counter module\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_CounterAutoTest                       |\r
+|                                               (BYTE_     b_BoardHandle,    |\r
+|                                                PBYTE_   pb_TestStatus)     |\r
++----------------------------------------------------------------------------+\r
+| Task              : A test mode is intended for testing the component and  |\r
+|                     the connected periphery. All the 8-bit counter chains  |\r
+|                     are operated internally as down counters.              |\r
+|                     Independently from the external signals,               |\r
+|                     all the four 8-bit counter chains are decremented in   |\r
+|                     parallel by each negative clock pulse edge of CLKX.    |\r
+|                                                                            |\r
+|                       Counter auto test conclusion                         |\r
+|                       ----------------------------                         |\r
+|              +-----------------+-----------------------------+             |\r
+|              | pb_TestStatus   |    Error description        |             |\r
+|              |     mask        |                             |             |\r
+|              |-----------------+-----------------------------|             |\r
+|              |    0000         |     No error detected       |             |\r
+|              |-----------------|-----------------------------|             |\r
+|              |    0001         | Error detected of counter 0 |             |\r
+|              |-----------------|-----------------------------|             |\r
+|              |    0010         | Error detected of counter 1 |             |\r
+|              |-----------------|-----------------------------|             |\r
+|              |    0100         | Error detected of counter 2 |             |\r
+|              |-----------------|-----------------------------|             |\r
+|              |    1000         | Error detected of counter 3 |             |\r
+|              +-----------------+-----------------------------+             |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_   b_BoardHandle : Handle of board APCI-1710      |  |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_TestStatus  : Auto test conclusion. See table|\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT  i_APCI1710_CounterAutoTest  (comedi_device *dev,PBYTE   pb_TestStatus)\r
+       {\r
+       BYTE   b_ModulCpt    = 0;\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_LathchValue;\r
+       \r
+       \r
+       *pb_TestStatus = 0;\r
+\r
+       /********************************/\r
+       /* Test if counter module found */\r
+       /********************************/\r
+\r
+       if ((devpriv->\r
+            s_BoardInfos.\r
+            dw_MolduleConfiguration [0] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER ||\r
+           (devpriv->\r
+            s_BoardInfos.\r
+            dw_MolduleConfiguration [1] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER ||\r
+           (devpriv->\r
+            s_BoardInfos.\r
+            dw_MolduleConfiguration [2] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER||\r
+           (devpriv->\r
+            s_BoardInfos.\r
+            dw_MolduleConfiguration [3] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER)\r
+          {\r
+          for (b_ModulCpt = 0; b_ModulCpt < 4 ; b_ModulCpt ++)\r
+             {\r
+             /*******************************/\r
+             /* Test if incremental counter */\r
+             /*******************************/\r
+\r
+             if ((devpriv->\r
+                  s_BoardInfos.\r
+                  dw_MolduleConfiguration [b_ModulCpt] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER)\r
+                {\r
+                /******************/\r
+                /* Start the test */\r
+                /******************/\r
+\r
+                
+                       outl(3,devpriv->s_BoardInfos.\r
+                        ui_Address + 16 + (64 * b_ModulCpt));\r
+\r
+                /*********************/\r
+                /* Tatch the counter */\r
+                /*********************/\r
+\r
+                
+                       outl(1,devpriv->s_BoardInfos.\r
+                        ui_Address + (64 * b_ModulCpt));\r
+\r
+                /************************/\r
+                /* Read the latch value */\r
+                /************************/\r
+\r
+               
+                       dw_LathchValue=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 4 + (64 * b_ModulCpt));\r
+\r
+                if ((dw_LathchValue & 0xFF) != ((dw_LathchValue >> 8)  & 0xFF) &&\r
+                    (dw_LathchValue & 0xFF) != ((dw_LathchValue >> 16) & 0xFF) &&\r
+                    (dw_LathchValue & 0xFF) != ((dw_LathchValue >> 24) & 0xFF))\r
+                   {\r
+                   *pb_TestStatus = *pb_TestStatus | (1 << b_ModulCpt);\r
+                   }\r
+\r
+                /*****************/\r
+                /* Stop the test */\r
+                /*****************/\r
+\r
+                \r
+                outl(0,devpriv->s_BoardInfos.\r
+                        ui_Address + 16 + (64 * b_ModulCpt));\r
+                }\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***************************/\r
+          /* No counter module found */\r
+          /***************************/\r
+\r          DPRINTK("No counter module found\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitIndex (BYTE_ b_BoardHandle,       |\r
+|                                                 BYTE_ b_ModulNbr,          |\r
+|                                                 BYTE_ b_ReferenceAction,   |\r
+|                                                 BYTE_ b_IndexOperation,    |\r
+|                                                 BYTE_ b_AutoMode,          |\r
+|                                                 BYTE_ b_InterruptEnable)   |\r
++----------------------------------------------------------------------------+\r
+| Task              : Initialise the index corresponding to the selected     |\r
+|                     module (b_ModulNbr). If a INDEX flag occur, you have   |\r
+|                     the possibility to clear the 32-Bit counter or to latch|\r
+|                     the current 32-Bit value in to the first latch         |\r
+|                     register. The b_IndexOperation parameter give the      |\r
+|                     possibility to choice the INDEX action.                |\r
+|                     If you have enabled the automatic mode, each INDEX     |\r
+|                     action is cleared automatically, else you must read    |\r
+|                     the index status ("i_APCI1710_ReadIndexStatus")        |\r
+|                     after each INDEX action.                               |\r
+|                                                                            |\r
+|                                                                            |\r
+|                               Index action                                 |\r
+|                               ------------                                 |\r
+|                                                                            |\r
+|           +------------------------+------------------------------------+  |\r
+|           |   b_IndexOperation     |         Operation                  |  |\r
+|           |------------------------+------------------------------------|  |\r
+|           |APCI1710_LATCH_COUNTER  | After a index signal, the counter  |  |\r
+|           |                        | value (32-Bit) is latched in to    |  |\r
+|           |                        | the first latch register           |  |\r
+|           |------------------------|------------------------------------|  |\r
+|           |APCI1710_CLEAR_COUNTER  | After a index signal, the counter  |  |\r
+|           |                        | value is cleared (32-Bit)          |  |\r
+|           +------------------------+------------------------------------+  |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
+|                     BYTE_ b_ReferenceAction : Determine if the reference   |\r
+|                                               must set or no for the       |\r
+|                                               acceptance from index        |\r
+|                                               APCI1710_ENABLE :            |\r
+|                                                  Reference must be set for |\r
+|                                                  accepted the index        |\r
+|                                               APCI1710_DISABLE :           |\r
+|                                                  Reference have not        |\r
+|                                                  importance                |\r
+|                     BYTE_ b_IndexOperation  : Index operating mode.        |\r
+|                                               See table.                   |\r
+|                     BYTE_ b_AutoMode        : Enable or disable the        |\r
+|                                               automatic index reset.       |\r
+|                                               APCI1710_ENABLE :            |\r
+|                                                 Enable the automatic mode  |\r
+|                                               APCI1710_DISABLE :           |\r
+|                                                 Disable the automatic mode |\r
+|                     BYTE_ b_InterruptEnable : Enable or disable the        |\r
+|                                               interrupt.                   |\r
+|                                               APCI1710_ENABLE :            |\r
+|                                               Enable the interrupt         |\r
+|                                               APCI1710_DISABLE :           |\r
+|                                               Disable the interrupt        |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4  The reference action parameter is wrong            |\r
+|                     -5: The index operating mode parameter is wrong        |\r
+|                     -6: The auto mode parameter is wrong                   |\r
+|                     -7: Interrupt parameter is wrong                       |\r
+|                     -8: Interrupt function not initialised.                |\r
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_InitIndex    (comedi_device *dev,\r
+                                BYTE b_ModulNbr,\r
+                                BYTE b_ReferenceAction,\r
+                                BYTE b_IndexOperation,\r
+                                BYTE b_AutoMode,\r
+                                BYTE b_InterruptEnable)\r
+       {\r
+       INT  i_ReturnValue = 0;\r
+       \r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /********************************/\r
+             /* Test the reference parameter */\r
+             /********************************/\r
+\r
+             if (b_ReferenceAction == APCI1710_ENABLE ||\r
+                 b_ReferenceAction == APCI1710_DISABLE)\r
+                {\r
+                /****************************/\r
+                /* Test the index parameter */\r
+                /****************************/\r
+\r
+                if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER           ||\r
+                    b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER            ||\r
+                    b_IndexOperation == APCI1710_HIGH_EDGE_CLEAR_COUNTER           ||\r
+                    b_IndexOperation == APCI1710_LOW_EDGE_CLEAR_COUNTER            ||\r
+                    b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER ||\r
+                    b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)\r
+                   {\r
+                   /********************************/\r
+                   /* Test the auto mode parameter */\r
+                   /********************************/\r
+\r
+                   if (b_AutoMode == APCI1710_ENABLE ||\r
+                       b_AutoMode == APCI1710_DISABLE)\r
+                      {\r
+                      /***************************/\r
+                      /* Test the interrupt mode */\r
+                      /***************************/\r
+\r
+                      if (b_InterruptEnable == APCI1710_ENABLE ||\r
+                          b_InterruptEnable == APCI1710_DISABLE)\r
+                         {\r
+                        \r
+                            /************************************/\r
+                            /* Makte the configuration commando */\r
+                            /************************************/\r
+\r
+                            if (b_ReferenceAction == APCI1710_ENABLE)\r
+                               {\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister2 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister2 | APCI1710_ENABLE_INDEX_ACTION;\r
+                               }\r
+                            else\r
+                               {\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister2 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister2 & APCI1710_DISABLE_INDEX_ACTION;\r
+                               }\r
+\r
+                            /****************************************/\r
+                            /* Test if low level latch or/and clear */\r
+                            /****************************************/\r
+\r
+                            if (b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER ||\r
+                                b_IndexOperation == APCI1710_LOW_EDGE_CLEAR_COUNTER ||\r
+                                b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)\r
+                               {\r
+                               /*************************************/\r
+                               /* Set the index level to low (DQ26) */\r
+                               /*************************************/\r
+\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister4 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister4 | APCI1710_SET_LOW_INDEX_LEVEL;\r
+                               }\r
+                            else\r
+                               {\r
+                               /**************************************/\r
+                               /* Set the index level to high (DQ26) */\r
+                               /**************************************/\r
+\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister4 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister4 & APCI1710_SET_HIGH_INDEX_LEVEL;\r
+                               }\r
+\r
+                            /***********************************/\r
+                            /* Test if latch and clear counter */\r
+                            /***********************************/\r
+\r
+                            if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER ||\r
+                                b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)\r
+                               {\r
+                               /***************************************/\r
+                               /* Set the latch and clear flag (DQ27) */\r
+                               /***************************************/\r
+\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister4 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister4 | APCI1710_ENABLE_LATCH_AND_CLEAR;\r
+                               } // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)\r
+                            else\r
+                               {\r
+                               /*****************************************/\r
+                               /* Clear the latch and clear flag (DQ27) */\r
+                               /*****************************************/\r
+\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister4 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister4 & APCI1710_DISABLE_LATCH_AND_CLEAR;\r
+\r
+                               /*************************/\r
+                               /* Test if latch counter */\r
+                               /*************************/\r
+\r
+                               if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER ||\r
+                                   b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER)\r
+                                  {\r
+                                  /*********************************/\r
+                                  /* Enable the latch from counter */\r
+                                  /*********************************/\r
+\r
+                                  devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister2 = devpriv->\r
+                                                    s_ModuleInfo [b_ModulNbr].\r
+                                                    s_SiemensCounterInfo.\r
+                                                    s_ModeRegister.\r
+                                                    s_ByteModeRegister.\r
+                                                    b_ModeRegister2 | APCI1710_INDEX_LATCH_COUNTER;\r
+                                  }\r
+                               else\r
+                                  {\r
+                                  /*********************************/\r
+                                  /* Enable the clear from counter */\r
+                                  /*********************************/\r
+\r
+                                  devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister2 = devpriv->\r
+                                                    s_ModuleInfo [b_ModulNbr].\r
+                                                    s_SiemensCounterInfo.\r
+                                                    s_ModeRegister.\r
+                                                    s_ByteModeRegister.\r
+                                                    b_ModeRegister2 & (~APCI1710_INDEX_LATCH_COUNTER);\r
+                                  }\r
+                               } // // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)\r
+\r
+\r
+                            if (b_AutoMode == APCI1710_DISABLE)\r
+                               {\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister2 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister2 | APCI1710_INDEX_AUTO_MODE;\r
+                               }\r
+                            else\r
+                               {\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister2 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister2 & (~APCI1710_INDEX_AUTO_MODE);\r
+                               }\r
+\r
+                            if (b_InterruptEnable == APCI1710_ENABLE)\r
+                               {\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister3 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister3 | APCI1710_ENABLE_INDEX_INT;\r
+                               }\r
+                            else\r
+                               {\r
+                               devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister3 = devpriv->\r
+                                                 s_ModuleInfo [b_ModulNbr].\r
+                                                 s_SiemensCounterInfo.\r
+                                                 s_ModeRegister.\r
+                                                 s_ByteModeRegister.\r
+                                                 b_ModeRegister3 & APCI1710_DISABLE_INDEX_INT;\r
+                               }\r
+\r
+                            devpriv->\r
+                            s_ModuleInfo [b_ModulNbr].\r
+                            s_SiemensCounterInfo.\r
+                            s_InitFlag.\r
+                            b_IndexInit = 1;\r
+                           \r
+                         }\r
+                      else\r
+                         {\r
+                         /********************************/\r
+                         /* Interrupt parameter is wrong */\r
+                         /********************************/\r
+                         DPRINTK("Interrupt parameter is wrong\n");    \r
+                         i_ReturnValue = -7;\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /************************************/\r
+                      /* The auto mode parameter is wrong */\r
+                      /************************************/\r
+\r                         DPRINTK("The auto mode parameter is wrong\n");
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /***********************************************/\r
+                   /* The index operating mode parameter is wrong */\r
+                   /***********************************************/\r
+\r                  DPRINTK("The index operating mode parameter is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*******************************************/\r
+                /* The reference action parameter is wrong */\r
+                /*******************************************/\r
+\r               DPRINTK("The reference action parameter is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitReference                         |\r
+|                                                (BYTE_ b_BoardHandle,       |\r
+|                                                 BYTE_ b_ModulNbr,          |\r
+|                                                 BYTE_ b_ReferenceLevel)    |\r
++----------------------------------------------------------------------------+\r
+| Task              : Initialise the reference corresponding to the selected |\r
+|                     module (b_ModulNbr).                                   |\r
+|                                                                            |\r
+|                               Reference level                              |\r
+|                               ---------------                              |\r
+|             +--------------------+-------------------------+               |\r
+|             | b_ReferenceLevel   |         Operation       |               |\r
+|             +--------------------+-------------------------+               |\r
+|             |   APCI1710_LOW     |  Reference occur if "0" |               |\r
+|             |--------------------|-------------------------|               |\r
+|             |   APCI1710_HIGH    |  Reference occur if "1" |               |\r
+|             +--------------------+-------------------------+               |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
+|                     BYTE_ b_ReferenceLevel  : Reference level.             |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number parameter is wrong      |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Reference level parameter is wrong                 |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_InitReference        (comedi_device *dev,\r
+                                        BYTE b_ModulNbr,\r
+                                        BYTE b_ReferenceLevel)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /**************************************/\r
+             /* Test the reference level parameter */\r
+             /**************************************/\r
+\r
+             if (b_ReferenceLevel == 0 ||\r
+                 b_ReferenceLevel == 1)\r
+                {\r
+                if (b_ReferenceLevel == 1)\r
+                   {\r
+                   devpriv->\r
+                   s_ModuleInfo [b_ModulNbr].\r
+                   s_SiemensCounterInfo.\r
+                   s_ModeRegister.\r
+                   s_ByteModeRegister.\r
+                   b_ModeRegister2 = devpriv->\r
+                                     s_ModuleInfo [b_ModulNbr].\r
+                                     s_SiemensCounterInfo.\r
+                                     s_ModeRegister.\r
+                                     s_ByteModeRegister.\r
+                                     b_ModeRegister2 | APCI1710_REFERENCE_HIGH;\r
+                   }\r
+                else\r
+                   {\r
+                   devpriv->\r
+                   s_ModuleInfo [b_ModulNbr].\r
+                   s_SiemensCounterInfo.\r
+                   s_ModeRegister.\r
+                   s_ByteModeRegister.\r
+                   b_ModeRegister2 = devpriv->\r
+                                     s_ModuleInfo [b_ModulNbr].\r
+                                     s_SiemensCounterInfo.\r
+                                     s_ModeRegister.\r
+                                     s_ByteModeRegister.\r
+                                     b_ModeRegister2 & APCI1710_REFERENCE_LOW;\r
+                   }\r
+\r
+                
+                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_SiemensCounterInfo.\r
+                        s_ModeRegister.\r
+                        dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                        ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_InitFlag.\r
+                b_ReferenceInit = 1;\r
+                }\r
+             else\r
+                {\r
+                /**************************************/\r
+                /* Reference level parameter is wrong */\r
+                /**************************************/\r
+\r               DPRINTK("Reference level parameter is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+       \r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_    i_APCI1710_InitExternalStrobe                |\r
+|                                      (BYTE_ b_BoardHandle,                |\r
+|                                       BYTE_ b_ModulNbr,                   |\r
+|                                       BYTE_ b_ExternalStrobe,             |\r
+|                                       BYTE_ b_ExternalStrobeLevel)        |\r
++----------------------------------------------------------------------------+\r
+| Task              : Initialises the external strobe level corresponding to |\r
+|                    the selected module (b_ModulNbr).                      |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
+|                    BYTE_ b_ExternalStrobe  : External strobe selection    |\r
+|                                              0 : External strobe A        |\r
+|                                              1 : External strobe B        |\r
+|                    BYTE_ b_ExternalStrobeLevel : External strobe level    |\r
+|                                              APCI1710_LOW :               |\r
+|                                              External latch occurs if "0" |\r
+|                                              APCI1710_HIGH :              |\r
+|                                              External latch occurs if "1" |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: Counter not initialised.                           |\r
+|                        See function "i_APCI1710_InitCounter"              |\r
+|                     -4: External strobe selection is wrong                 |\r
+|                     -5: External strobe level parameter is wrong           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_InitExternalStrobe   (comedi_device *dev,\r
+                                        BYTE b_ModulNbr,\r
+                                        BYTE b_ExternalStrobe,\r
+                                        BYTE b_ExternalStrobeLevel)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /**************************************/\r
+             /* Test the external strobe selection */\r
+              /**************************************/\r
+\r
+             if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)\r
+                {\r
+                /******************/\r
+                /* Test the level */\r
+                /******************/\r
+\r
+                if ((b_ExternalStrobeLevel == APCI1710_HIGH) ||\r
+                    ((b_ExternalStrobeLevel == APCI1710_LOW && (devpriv->\r
+                                                                s_BoardInfos.\r
+                                                                dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3135)))\r
+                   {\r
+                   /*****************/\r
+                   /* Set the level */\r
+                   /*****************/\r
+\r
+                   devpriv->\r
+                   s_ModuleInfo [b_ModulNbr].\r
+                   s_SiemensCounterInfo.\r
+                   s_ModeRegister.\r
+                   s_ByteModeRegister.\r
+                   b_ModeRegister4 = (devpriv->\r
+                                      s_ModuleInfo [b_ModulNbr].\r
+                                      s_SiemensCounterInfo.\r
+                                      s_ModeRegister.\r
+                                      s_ByteModeRegister.\r
+                                      b_ModeRegister4 & (0xFF - (0x10 << b_ExternalStrobe))) |\r
+                                      ((b_ExternalStrobeLevel^1) << (4 + b_ExternalStrobe));\r
+                   }\r
+                else\r
+                   {\r
+                   /********************************************/\r
+                   /* External strobe level parameter is wrong */\r
+                   /********************************************/\r
+\r                      DPRINTK("External strobe level parameter is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)\r
+             else\r
+                {\r
+                /**************************************/\r
+                /* External strobe selection is wrong */\r
+                /**************************************/\r
+\r               DPRINTK("External strobe selection is wrong\n");
+                i_ReturnValue = -4;\r
+                } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+       /*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitCompareLogic                      |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                UINT_  ui_CompareValue)                     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Set the 32-Bit compare value. At that moment that the  |\r
+|                     incremental counter arrive to the compare value        |\r
+|                     (ui_CompareValue) a interrupt is generated.            |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                     BYTE_  b_ModulNbr       : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
+|                     UINT_ ui_CompareValue   : 32-Bit compare value         |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_InitCompareLogic     (comedi_device *dev,\r
+                                        BYTE   b_ModulNbr,\r
+                                        UINT  ui_CompareValue)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             \r
+                  outl(ui_CompareValue,devpriv->s_BoardInfos.\r
+                     ui_Address + 28 + (64 * b_ModulNbr));\r
+\r
+             devpriv->\r
+             s_ModuleInfo [b_ModulNbr].\r
+             s_SiemensCounterInfo.\r
+             s_InitFlag.\r
+             b_CompareLogicInit = 1;\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitFrequencyMeasurement              |\r
+|                              (BYTE_           b_BoardHandle,              |\r
+|                               BYTE_           b_ModulNbr,                 |\r
+|                               BYTE_           b_PCIInputClock,            |\r
+|                               BYTE_           b_TimingUnity,              |\r
+|                               ULONG_         ul_TimingInterval,           |\r
+|                               PULONG_       pul_RealTimingInterval)       |\r
++----------------------------------------------------------------------------+\r
+| Task              : Sets the time for the frequency measurement.           |\r
+|                    Configures the selected TOR incremental counter of the |\r
+|                    selected module (b_ModulNbr). The ul_TimingInterval and|\r
+|                    ul_TimingUnity determine the time base for the         |\r
+|                    measurement. The pul_RealTimingInterval returns the    |\r
+|                    real time value. You must call up this function before |\r
+|                    you call up any other function which gives access to   |\r
+|                    the frequency measurement.                             |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |\r
+|                                              configured (0 to 3)          |\r
+|                    BYTE_  b_PCIInputClock  : Selection of the PCI bus     |\r
+|                                              clock                        |\r
+|                                              - APCI1710_30MHZ :           |\r
+|                                                The PC has a PCI bus clock |\r
+|                                                of 30 MHz                  |\r
+|                                              - APCI1710_33MHZ :           |\r
+|                                                The PC has a PCI bus clock |\r
+|                                                of 33 MHz                  |\r
+|                    BYTE_  b_TimingUnity    : Base time unit (0 to 2)      |\r
+|                                                0 : ns                     |\r
+|                                                1 : æs                     |\r
+|                                                2 : ms                     |\r
+|                    ULONG_ ul_TimingInterval: Base time value.             |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PULONG_ pul_RealTimingInterval : Real base time value. |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: Counter not initialised see function               |\r
+|                        "i_APCI1710_InitCounter"                           |\r
+|                     -4: The selected PCI input clock is wrong              |\r
+|                     -5: Timing unity selection is wrong                    |\r
+|                     -6: Base timing selection is wrong                     |\r
+|                    -7: 40MHz quartz not on board                          |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_InitFrequencyMeasurement     (comedi_device *dev,\r
+                                                BYTE            b_ModulNbr,\r
+                                                BYTE            b_PCIInputClock,\r
+                                                BYTE            b_TimingUnity,\r
+                                                ULONG           ul_TimingInterval,\r
+                                                PULONG      pul_RealTimingInterval)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       ULONG ul_TimerValue;\r
+       double d_RealTimingInterval;\r
+       DWORD dw_Status      = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /**************************/\r
+             /* Test the PCI bus clock */\r
+             /**************************/\r
+\r
+             if ((b_PCIInputClock == APCI1710_30MHZ) ||\r
+                 (b_PCIInputClock == APCI1710_33MHZ) ||\r
+                 (b_PCIInputClock == APCI1710_40MHZ))\r
+                {\r
+                /************************/\r
+                /* Test the timing unit */\r
+                /************************/\r
+\r
+                if ((b_TimingUnity >= 0) && (b_TimingUnity <= 2))\r
+                   {\r
+                   /**********************************/\r
+                   /* Test the base timing selection */\r
+                   /**********************************/\r
+\r
+                   if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnity == 0) && (ul_TimingInterval >= 266) && (ul_TimingInterval <= 8738133UL)) ||\r
+                       ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnity == 1) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 8738UL))    ||\r
+                       ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnity == 2) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 8UL))       ||\r
+                       ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnity == 0) && (ul_TimingInterval >= 242) && (ul_TimingInterval <= 7943757UL)) ||\r
+                       ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnity == 1) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 7943UL))    ||\r
+                       ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnity == 2) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 7UL))       ||\r
+                       ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnity == 0) && (ul_TimingInterval >= 200) && (ul_TimingInterval <= 6553500UL)) ||\r
+                       ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnity == 1) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 6553UL))    ||\r
+                       ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnity == 2) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 6UL)))\r
+                      {\r
+                      /**********************/\r
+                      /* Test if 40MHz used */\r
+                      /**********************/\r
+\r
+                      if (b_PCIInputClock == APCI1710_40MHZ)\r
+                         {\r
+                         /******************************/\r
+                         /* Test if firmware >= Rev1.5 */\r
+                         /******************************/\r
+\r
+                         if ((devpriv->\r
+                              s_BoardInfos.\r
+                              dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3135)\r
+                            {\r
+                            /*********************************/\r
+                            /* Test if 40MHz quartz on board */\r
+                            /*********************************/\r
+\r
+                            /*INPDW (ps_APCI1710Variable->\r
+                                   s_Board [b_BoardHandle].\r
+                                   s_BoardInfos.\r
+                                   ui_Address + 36 + (64 * b_ModulNbr), &dw_Status);*/\r
+                                 dw_Status=inl(devpriv->s_BoardInfos.\r
+                                   ui_Address + 36 + (64 * b_ModulNbr));\r
+\r
+                            /******************************/\r
+                            /* Test the quartz flag (DQ0) */\r
+                            /******************************/\r
+\r
+                            if ((dw_Status & 1) != 1)\r
+                               {\r
+                               /*****************************/\r
+                               /* 40MHz quartz not on board */\r
+                               /*****************************/\r
+\r                              DPRINTK("40MHz quartz not on board\n");
+                               i_ReturnValue = -7;\r
+                               }\r
+                            }\r
+                         else\r
+                            {\r
+                            /*****************************/\r
+                            /* 40MHz quartz not on board */\r
+                            /*****************************/\r
+                                DPRINTK("40MHz quartz not on board\n");\r
+                            i_ReturnValue = -7;\r
+                            }\r
+                         } // if (b_PCIInputClock == APCI1710_40MHZ)\r
+\r
+                      /***************************/\r
+                      /* Test if not error occur */\r
+                      /***************************/\r
+\r
+                      if (i_ReturnValue == 0)\r
+                         {\r
+                         /****************************/\r
+                         /* Test the INC_CPT version */\r
+                         /****************************/\r
+\r
+                         if ((devpriv->s_BoardInfos.\r
+                              dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3131)\r
+                            {\r
+                           
+                               /**********************/\r
+                               /* Test if 40MHz used */\r
+                               /**********************/\r
+\r
+                               if (b_PCIInputClock == APCI1710_40MHZ)\r
+                                  {\r
+                                  /*********************************/\r
+                                  /* Enable the 40MHz quarz (DQ30) */\r
+                                  /*********************************/\r
+\r
+                                  devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister4 = devpriv->\r
+                                                    s_ModuleInfo [b_ModulNbr].\r
+                                                    s_SiemensCounterInfo.\r
+                                                    s_ModeRegister.\r
+                                                    s_ByteModeRegister.\r
+                                                    b_ModeRegister4 | APCI1710_ENABLE_40MHZ_FREQUENCY;\r
+                                  } // if (b_PCIInputClock == APCI1710_40MHZ)\r
+                               else\r
+                                  {\r
+                                  /**********************************/\r
+                                  /* Disable the 40MHz quarz (DQ30) */\r
+                                  /**********************************/\r
+\r
+                                  devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister4 = devpriv->\r
+                                                    s_ModuleInfo [b_ModulNbr].\r
+                                                    s_SiemensCounterInfo.\r
+                                                    s_ModeRegister.\r
+                                                    s_ByteModeRegister.\r
+                                                    b_ModeRegister4 & APCI1710_DISABLE_40MHZ_FREQUENCY;\r
+\r
+                                  } // if (b_PCIInputClock == APCI1710_40MHZ)\r
+                           
+\r
+                            /********************************/\r
+                            /* Calculate the division fator */\r
+                            /********************************/\r
+\r
+                            switch (b_TimingUnity)\r
+                               {\r
+                               /******/\r
+                               /* ns */\r
+                               /******/\r
+\r
+                               case 0:\r
+                                    \r
+                                       /******************/\r
+                                       /* Timer 0 factor */\r
+                                       /******************/\r
+\r
+                                       ul_TimerValue = (ULONG) (ul_TimingInterval * (0.00025 * b_PCIInputClock));\r
+\r
+                                       /*******************/\r
+                                       /* Round the value */\r
+                                       /*******************/\r
+\r
+                                       if ((double) ((double) ul_TimingInterval * (0.00025 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                          {\r
+                                          ul_TimerValue = ul_TimerValue + 1;\r
+                                          }\r
+\r
+                                       /*****************************/\r
+                                       /* Calculate the real timing */\r
+                                       /*****************************/\r
+\r
+                                       *pul_RealTimingInterval = (ULONG) (ul_TimerValue / (0.00025 * (double) b_PCIInputClock));\r
+                                       d_RealTimingInterval = (double) ul_TimerValue / (0.00025 * (double) b_PCIInputClock);\r
+\r
+                                       if ((double) ((double) ul_TimerValue / (0.00025 * (double) b_PCIInputClock)) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                          {\r
+                                          *pul_RealTimingInterval = *pul_RealTimingInterval + 1;\r
+                                          }\r
+\r
+                                       ul_TimingInterval     = ul_TimingInterval - 1;\r
+                                       ul_TimerValue = ul_TimerValue - 2;\r
+                                    \r
+                                    break;\r
+\r
+                               /******/\r
+                               /* æs */\r
+                               /******/\r
+\r
+                               case 1:\r                                
+                                    \r
+                                       /******************/\r
+                                       /* Timer 0 factor */\r
+                                       /******************/\r
+\r
+                                       ul_TimerValue = (ULONG) (ul_TimingInterval * (0.25 * b_PCIInputClock));\r
+\r
+                                       /*******************/\r
+                                       /* Round the value */\r
+                                       /*******************/\r
+\r
+                                       if ((double) ((double) ul_TimingInterval * (0.25 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                          {\r
+                                          ul_TimerValue = ul_TimerValue + 1;\r
+                                          }\r
+\r
+                                       /*****************************/\r
+                                       /* Calculate the real timing */\r
+                                       /*****************************/\r
+\r
+                                       *pul_RealTimingInterval = (ULONG) (ul_TimerValue / (0.25 * (double) b_PCIInputClock));\r
+                                       d_RealTimingInterval    = (double) ul_TimerValue / ((double) 0.25 * (double) b_PCIInputClock);\r
+\r
+                                       if ((double) ((double) ul_TimerValue / (0.25 * (double) b_PCIInputClock)) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                          {\r
+                                          *pul_RealTimingInterval = *pul_RealTimingInterval + 1;\r
+                                          }\r
+\r
+                                       ul_TimingInterval     = ul_TimingInterval - 1;\r
+                                       ul_TimerValue = ul_TimerValue - 2;\r
+                                    \r
+\r
+                                    break;\r
+\r
+                               /******/\r
+                               /* ms */\r
+                               /******/\r
+\r
+                               case 2:\r                                
+                                    \r
+                                       /******************/\r
+                                       /* Timer 0 factor */\r
+                                       /******************/\r
+\r
+                                       ul_TimerValue = ul_TimingInterval * (250.0 * b_PCIInputClock);\r
+\r
+                                       /*******************/\r
+                                       /* Round the value */\r
+                                       /*******************/\r
+\r
+                                       if ((double) ((double) ul_TimingInterval * (250.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                          {\r
+                                          ul_TimerValue = ul_TimerValue + 1;\r
+                                          }\r
+\r
+                                       /*****************************/\r
+                                       /* Calculate the real timing */\r
+                                       /*****************************/\r
+\r
+                                       *pul_RealTimingInterval = (ULONG) (ul_TimerValue / (250.0 * (double) b_PCIInputClock));\r
+                                       d_RealTimingInterval    = (double) ul_TimerValue / (250.0 * (double) b_PCIInputClock);\r
+\r
+                                       if ((double) ((double) ul_TimerValue / (250.0 * (double) b_PCIInputClock)) >= (double) ((double) *pul_RealTimingInterval + 0.5))\r
+                                          {\r
+                                          *pul_RealTimingInterval = *pul_RealTimingInterval + 1;\r
+                                          }\r
+\r
+                                       ul_TimingInterval     = ul_TimingInterval - 1;\r
+                                       ul_TimerValue = ul_TimerValue - 2;\r
+                                    \r
+                                    break;\r
+                               }\r
+\r
+                            /*************************/\r
+                            /* Write the timer value */\r
+                            /*************************/\r
+\r
+                           \r
+                                        outl(ul_TimerValue,devpriv->s_BoardInfos.\r
+                                    ui_Address + 32 + (64 * b_ModulNbr));\r
+\r
+                            /*******************************/\r
+                            /* Set the initialisation flag */\r
+                            /*******************************/\r
+\r
+                            devpriv->\r
+                            s_ModuleInfo [b_ModulNbr].\r
+                            s_SiemensCounterInfo.\r
+                            s_InitFlag.\r
+                            b_FrequencyMeasurementInit  = 1;\r
+                            }\r
+                         else\r
+                            {\r
+                            /***************************/\r
+                            /* Counter not initialised */\r
+                            /***************************/\r
+\r                        DPRINTK("Counter not initialised\n");  
+                            i_ReturnValue = -3;\r
+                            }\r
+                         } // if (i_ReturnValue == 0)\r
+                      }\r
+                   else\r
+                      {\r
+                      /**********************************/\r
+                      /* Base timing selection is wrong */\r
+                      /**********************************/\r
+\r                         DPRINTK("Base timing selection is wrong\n");  
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /***********************************/\r
+                   /* Timing unity selection is wrong */\r
+                   /***********************************/\r
+\r                      DPRINTK("Timing unity selection is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*****************************************/\r
+                /* The selected PCI input clock is wrong */\r
+                /*****************************************/\r
+\r               DPRINTK("The selected PCI input clock is wrong\n");    
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*########################################################################### */\r
+\r
+                                                       //INSN BITS\r
+/*########################################################################### */\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     :INT       i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)                   |\r
++----------------------------------------------------------------------------+\r
+| Task              : Set & Clear Functions for INC_CPT                                          |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : \r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : \r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+INT    i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)\r
+{\r
+       UINT ui_BitsType;\r
+       INT i_ReturnValue=0;\r
+       ui_BitsType=CR_CHAN(insn->chanspec);\r
+       devpriv->tsk_Current=current; // Save the current process task structure
+\r
+       switch(ui_BitsType)\r
+       {\r
+       case APCI1710_INCCPT_CLEARCOUNTERVALUE:\r
+               i_ReturnValue=i_APCI1710_ClearCounterValue    (dev,\r
+                                        (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+       case APCI1710_INCCPT_CLEARALLCOUNTERVALUE:\r
+               i_ReturnValue=i_APCI1710_ClearAllCounterValue (dev);\r
+               break;\r
+\r
+       case APCI1710_INCCPT_SETINPUTFILTER:\r
+               i_ReturnValue=i_APCI1710_SetInputFilter (dev,\r
+                                                                       (BYTE) CR_AREF(insn->chanspec),\r
+                                    (BYTE) data[0],\r
+                                                                       (BYTE) data[1]);\r
+               break;\r
+\r
+       case APCI1710_INCCPT_LATCHCOUNTER:\r
+               i_ReturnValue=i_APCI1710_LatchCounter (dev,\r
+                                (BYTE) CR_AREF(insn->chanspec),\r
+                                (BYTE) data[0]);\r
+               break;\r
+\r
+       case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE:\r
+               i_ReturnValue=i_APCI1710_SetIndexAndReferenceSource     (dev,\r
+                                                (BYTE) CR_AREF(insn->chanspec),\r
+                                                (BYTE) data[0]);\r
+               break;\r
+\r
+       case APCI1710_INCCPT_SETDIGITALCHLON:\r
+               i_ReturnValue=i_APCI1710_SetDigitalChlOn (dev,\r
+                                    (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+       case APCI1710_INCCPT_SETDIGITALCHLOFF:\r
+               i_ReturnValue=i_APCI1710_SetDigitalChlOff (dev,\r
+                                    (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+       default:\r
+               printk("Bits Config Parameter Wrong\n");\r
+       }\r
+\r
+       if(i_ReturnValue>=0) i_ReturnValue =insn->n;\r
+       return (i_ReturnValue);\r
+}\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ClearCounterValue                     |\r
+|                               (BYTE_      b_BoardHandle,                   |\r
+|                                BYTE_       b_ModulNbr)                     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Clear the counter value from selected module           |\r
+|                     (b_ModulNbr).                                          |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |\r
+|                     BYTE_ b_ModulNbr    : Module number to configure       |\r
+|                                           (0 to 3)                         |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number parameter is wrong      |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_ClearCounterValue    (comedi_device *dev,\r
+                                        BYTE b_ModulNbr)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*********************/\r
+             /* Clear the counter */\r
+             /*********************/\r
+\r
+             \r
+                  outl(1,devpriv->s_BoardInfos.\r
+                     ui_Address + 16 + (64 * b_ModulNbr));\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");             
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");                  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ClearAllCounterValue                  |\r
+|                               (BYTE_      b_BoardHandle)                   |\r
++----------------------------------------------------------------------------+\r
+| Task              : Clear all counter value.                               |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_ClearAllCounterValue (comedi_device *dev)\r
+       {\r
+       BYTE   b_ModulCpt    = 0;\r
+       INT    i_ReturnValue = 0;\r
+       \r
+\r
+       /********************************/\r
+       /* Test if counter module found */\r
+       /********************************/\r
+\r
+       if ((devpriv->s_BoardInfos.\r
+            dw_MolduleConfiguration [0] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER ||\r
+           (devpriv->s_BoardInfos.\r
+            dw_MolduleConfiguration [1] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER ||\r
+           (devpriv->s_BoardInfos.\r
+            dw_MolduleConfiguration [2] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER ||\r
+           (devpriv->s_BoardInfos.\r
+            dw_MolduleConfiguration [3] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER)\r
+          {\r
+          for (b_ModulCpt = 0; b_ModulCpt < 4 ; b_ModulCpt ++)\r
+             {\r
+             /*******************************/\r
+             /* Test if incremental counter */\r
+             /*******************************/\r
+\r
+             if ((devpriv->s_BoardInfos.\r
+                  dw_MolduleConfiguration [b_ModulCpt] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER)\r
+                {\r
+                /*********************/\r
+                /* Clear the counter */\r
+                /*********************/\r
+\r
+                \r
+               outl(1,devpriv->s_BoardInfos.\r
+                        ui_Address + 16 + (64 * b_ModulCpt));\r
+                }\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***************************/\r
+          /* No counter module found */\r
+          /***************************/\r
+\r         DPRINTK("No counter module found\n");        
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_SetInputFilter                        |\r
+|                                      (BYTE_ b_BoardHandle,                |\r
+|                                       BYTE_ b_Module,                     |\r
+|                                       BYTE_ b_PCIInputClock,              |\r
+|                                       BYTE_ b_Filter)                     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Disable or enable the software filter from selected    |\r
+|                    module (b_ModulNbr). b_Filter determine the filter time|\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |\r
+|                                              configured (0 to 3)          |\r
+|                    BYTE_  b_PCIInputClock  : Selection of the PCI bus     |\r
+|                                              clock                        |\r
+|                                              - APCI1710_30MHZ :           |\r
+|                                                The PC has a PCI bus clock |\r
+|                                                of 30 MHz                  |\r
+|                                              - APCI1710_33MHZ :           |\r
+|                                                The PC has a PCI bus clock |\r
+|                                                of 33 MHz                  |\r
+|                                              - APCI1710_40MHZ :           |\r
+|                                                The APCI1710 has a 40MHz    |\r
+|                                                quartz                     |\r
+|                    BYTE_  b_Filter         : Filter selection             |\r
+|                                                                            |\r
+|                              30 MHz                                       |\r
+|                              ------                                       |\r
+|                                      0:  Software filter not used         |\r
+|                                      1:  Filter from 266ns  (3.750000MHz) |\r
+|                                      2:  Filter from 400ns  (2.500000MHz) |\r
+|                                      3:  Filter from 533ns  (1.876170MHz) |\r
+|                                      4:  Filter from 666ns  (1.501501MHz) |\r
+|                                      5:  Filter from 800ns  (1.250000MHz) |\r
+|                                      6:  Filter from 933ns  (1.071800MHz) |\r
+|                                      7:  Filter from 1066ns (0.938080MHz) |\r
+|                                      8:  Filter from 1200ns (0.833333MHz) |\r
+|                                      9:  Filter from 1333ns (0.750000MHz) |\r
+|                                      10: Filter from 1466ns (0.682100MHz) |\r
+|                                      11: Filter from 1600ns (0.625000MHz) |\r
+|                                      12: Filter from 1733ns (0.577777MHz) |\r
+|                                      13: Filter from 1866ns (0.535900MHz) |\r
+|                                      14: Filter from 2000ns (0.500000MHz) |\r
+|                                      15: Filter from 2133ns (0.468800MHz) |\r
+|                                                                           |\r
+|                              33 MHz                                       |\r
+|                              ------                                       |\r
+|                                      0:  Software filter not used         |\r
+|                                      1:  Filter from 242ns  (4.125000MHz) |\r
+|                                      2:  Filter from 363ns  (2.754820MHz) |\r
+|                                      3:  Filter from 484ns  (2.066115MHz) |\r
+|                                      4:  Filter from 605ns  (1.652892MHz) |\r
+|                                      5:  Filter from 726ns  (1.357741MHz) |\r
+|                                      6:  Filter from 847ns  (1.180637MHz) |\r
+|                                      7:  Filter from 968ns  (1.033055MHz) |\r
+|                                      8:  Filter from 1089ns (0.918273MHz) |\r
+|                                      9:  Filter from 1210ns (0.826446MHz) |\r
+|                                      10: Filter from 1331ns (0.751314MHz) |\r
+|                                      11: Filter from 1452ns (0.688705MHz) |\r
+|                                      12: Filter from 1573ns (0.635727MHz) |\r
+|                                      13: Filter from 1694ns (0.590318MHz) |\r
+|                                      14: Filter from 1815ns (0.550964MHz) |\r
+|                                      15: Filter from 1936ns (0.516528MHz) |\r
+|                                                                           |\r
+|                              40 MHz                                       |\r
+|                              ------                                       |\r
+|                                      0:  Software filter not used         |\r
+|                                      1:  Filter from 200ns  (5.000000MHz) |\r
+|                                      2:  Filter from 300ns  (3.333333MHz) |\r
+|                                      3:  Filter from 400ns  (2.500000MHz) |\r
+|                                      4:  Filter from 500ns  (2.000000MHz) |\r
+|                                      5:  Filter from 600ns  (1.666666MHz) |\r
+|                                      6:  Filter from 700ns  (1.428500MHz) |\r
+|                                      7:  Filter from 800ns  (1.250000MHz) |\r
+|                                      8:  Filter from 900ns  (1.111111MHz) |\r
+|                                      9:  Filter from 1000ns (1.000000MHz) |\r
+|                                      10: Filter from 1100ns (0.909090MHz) |\r
+|                                      11: Filter from 1200ns (0.833333MHz) |\r
+|                                      12: Filter from 1300ns (0.769200MHz) |\r
+|                                      13: Filter from 1400ns (0.714200MHz) |\r
+|                                      14: Filter from 1500ns (0.666666MHz) |\r
+|                                      15: Filter from 1600ns (0.625000MHz) |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: The module is not a counter module                 |\r
+|                                        -4: The selected PCI input clock is wrong              |\r
+|                                        -5: The selected filter value is wrong                 |\r
+|                                        -6: 40MHz quartz not on board                          |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_SetInputFilter       (comedi_device *dev,\r
+                                                                       BYTE b_ModulNbr,\r
+                                    BYTE b_PCIInputClock,\r
+                                                                       BYTE b_Filter)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_Status      = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if incremental counter */\r
+          /*******************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER)\r
+             {\r
+             /******************************/\r
+             /* Test if firmware >= Rev1.5 */\r
+             /******************************/\r
+\r
+             if ((devpriv->s_BoardInfos.\r
+                  dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3135)\r
+                {\r
+                /**************************/\r
+                /* Test the PCI bus clock */\r
+                /**************************/\r
+\r
+                if ((b_PCIInputClock == APCI1710_30MHZ) ||\r
+                    (b_PCIInputClock == APCI1710_33MHZ) ||\r
+                    (b_PCIInputClock == APCI1710_40MHZ))\r
+                   {\r
+                   /*************************/\r
+                   /* Test the filter value */\r
+                   /*************************/\r
+\r
+                   if (b_Filter < 16)\r
+                      {\r
+                      /**********************/\r
+                      /* Test if 40MHz used */\r
+                      /**********************/\r
+\r
+                      if (b_PCIInputClock == APCI1710_40MHZ)\r
+                         {\r
+                         /*********************************/\r
+                         /* Test if 40MHz quartz on board */\r
+                         /*********************************/\r
+\r
+                        
+                       dw_Status=      inl(devpriv->s_BoardInfos.\r
+                                ui_Address + 36 + (64 * b_ModulNbr));\r
+\r
+                         /******************************/\r
+                         /* Test the quartz flag (DQ0) */\r
+                         /******************************/\r
+\r
+                         if ((dw_Status & 1) != 1)\r
+                            {\r
+                            /*****************************/\r
+                            /* 40MHz quartz not on board */\r
+                            /*****************************/\r
+\r                        DPRINTK("40MHz quartz not on board\n"); 
+                            i_ReturnValue = -6;\r
+                            }\r
+                         } // if (b_PCIInputClock == APCI1710_40MHZ)\r
+\r
+                      /***************************/\r
+                      /* Test if error not occur */\r
+                      /***************************/\r
+\r
+                      if (i_ReturnValue == 0)\r
+                         {\r
+                         /**********************/\r
+                         /* Test if 40MHz used */\r
+                         /**********************/\r
+\r
+                         if (b_PCIInputClock == APCI1710_40MHZ)\r
+                            {\r
+                            /*********************************/\r
+                            /* Enable the 40MHz quarz (DQ31) */\r
+                            /*********************************/\r
+\r
+                            devpriv->\r
+                            s_ModuleInfo [b_ModulNbr].\r
+                            s_SiemensCounterInfo.\r
+                            s_ModeRegister.\r
+                            s_ByteModeRegister.\r
+                            b_ModeRegister4 = devpriv->\r
+                                              s_ModuleInfo [b_ModulNbr].\r
+                                              s_SiemensCounterInfo.\r
+                                              s_ModeRegister.\r
+                                              s_ByteModeRegister.\r
+                                              b_ModeRegister4 | APCI1710_ENABLE_40MHZ_FILTER;\r
+\r
+                            } // if (b_PCIInputClock == APCI1710_40MHZ)\r
+                         else\r
+                            {\r
+                            /**********************************/\r
+                            /* Disable the 40MHz quarz (DQ31) */\r
+                            /**********************************/\r
+\r
+                            devpriv->\r
+                            s_ModuleInfo [b_ModulNbr].\r
+                            s_SiemensCounterInfo.\r
+                            s_ModeRegister.\r
+                            s_ByteModeRegister.\r
+                            b_ModeRegister4 = devpriv->\r
+                                              s_ModuleInfo [b_ModulNbr].\r
+                                              s_SiemensCounterInfo.\r
+                                              s_ModeRegister.\r
+                                              s_ByteModeRegister.\r
+                                              b_ModeRegister4 & APCI1710_DISABLE_40MHZ_FILTER;\r
+\r
+                            } // if (b_PCIInputClock == APCI1710_40MHZ)\r
+\r
+                         /************************/\r
+                         /* Set the filter value */\r
+                         /************************/\r
+\r
+                         devpriv->\r
+                         s_ModuleInfo [b_ModulNbr].\r
+                         s_SiemensCounterInfo.\r
+                         s_ModeRegister.\r
+                         s_ByteModeRegister.\r
+                         b_ModeRegister3 = (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                            s_SiemensCounterInfo.\r
+                                            s_ModeRegister.\r
+                                            s_ByteModeRegister.\r
+                                            b_ModeRegister3 & 0x1F) | ((b_Filter & 0x7) << 5);\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_SiemensCounterInfo.\r
+                         s_ModeRegister.\r
+                         s_ByteModeRegister.\r
+                         b_ModeRegister4 = (devpriv->\r
+                                            s_ModuleInfo [b_ModulNbr].\r
+                                            s_SiemensCounterInfo.\r
+                                            s_ModeRegister.\r
+                                            s_ByteModeRegister.\r
+                                            b_ModeRegister4 & 0xFE) | ((b_Filter & 0x8) >> 3);\r
+\r
+                         /***************************/\r
+                         /* Write the configuration */\r
+                         /***************************/\r
+\r
+                         \r
+                         outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                 s_SiemensCounterInfo.\r
+                                 s_ModeRegister.\r
+                                 dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                                 ui_Address + 20 + (64 * b_ModulNbr));\r
+                         } // if (i_ReturnValue == 0)\r
+                      } // if (b_Filter < 16)\r
+                   else\r
+                      {\r
+                      /**************************************/\r
+                      /* The selected filter value is wrong */\r
+                      /**************************************/\r
+\r                         DPRINTK("The selected filter value is wrong\n");      
+                      i_ReturnValue = -5;\r
+                      } // if (b_Filter < 16)\r
+                   } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))\r
+                else\r
+                   {\r
+                   /*****************************************/\r
+                   /* The selected PCI input clock is wrong */\r
+                   /*****************************************/\r
+\r                      DPRINTK("The selected PCI input clock is wrong\n");
+                   i_ReturnValue = 4;\r
+                   } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))\r
+                }\r
+             else\r
+                {\r
+                /**************************************/\r
+                /* The module is not a counter module */\r
+                /**************************************/\r
+\r               DPRINTK("The module is not a counter module\n");
+                i_ReturnValue = -3;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /**************************************/\r
+             /* The module is not a counter module */\r
+             /**************************************/\r
+\r            DPRINTK("The module is not a counter module\n");  
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_LatchCounter (BYTE_ b_BoardHandle,    |\r
+|                                                    BYTE_ b_ModulNbr,       |\r
+|                                                    BYTE_ b_LatchReg)       |\r
++----------------------------------------------------------------------------+\r
+| Task              : Latch the courant value from selected module           |\r
+|                     (b_ModulNbr) in to the selected latch register         |\r
+|                     (b_LatchReg).                                          |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |\r
+|                     BYTE_ b_ModulNbr    : Module number to configure       |\r
+|                                           (0 to 3)                         |\r
+|                     BYTE_ b_LatchReg    : Selected latch register          |\r
+|                               0 : for the first latch register             |\r
+|                               1 : for the second latch register            |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: The selected latch register parameter is wrong     |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_LatchCounter (comedi_device *dev,\r
+                                BYTE b_ModulNbr,\r
+                                BYTE b_LatchReg)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*************************************/\r
+             /* Test the latch register parameter */\r
+             /*************************************/\r
+\r
+             if (b_LatchReg < 2)\r
+                {\r
+                /*********************/\r
+                /* Tatch the counter */\r
+                /*********************/\r
+\r
+                       outl(1 << (b_LatchReg * 4),devpriv->s_BoardInfos.\r
+                        ui_Address + (64 * b_ModulNbr));\r
+                }\r
+             else\r
+                {\r
+                /**************************************************/\r
+                /* The selected latch register parameter is wrong */\r
+                /**************************************************/\r
+\r               DPRINTK("The selected latch register parameter is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_    i_APCI1710_SetIndexAndReferenceSource        |\r
+|                                      (BYTE_ b_BoardHandle,                |\r
+|                                       BYTE_ b_ModulNbr,                   |\r
+|                                       BYTE_ b_SourceSelection)            |\r
++----------------------------------------------------------------------------+\r
+| Task              : Determine the hardware source for the index and the    |\r
+|                    reference logic. Per default the index logic is        |\r
+|                    connected to the difference input C and the reference  |\r
+|                    logic is connected to the 24V input E                  |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
+|                    BYTE_ b_SourceSelection : APCI1710_SOURCE_0 :          |\r
+|                                              The index logic is connected |\r
+|                                              to the difference input C and|\r
+|                                              the reference logic is       |\r
+|                                              connected to the 24V input E.|\r
+|                                              This is the default          |\r
+|                                              configuration.               |\r
+|                                              APCI1710_SOURCE_1 :          |\r
+|                                              The reference logic is       |\r
+|                                              connected to the difference  |\r
+|                                              input C and the index logic  |\r
+|                                              is connected to the 24V      |\r
+|                                              input E                      |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                    -2: The selected module number is wrong                |\r
+|                    -3: The module is not a counter module.                |\r
+|                    -4: The source selection is wrong                      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_SetIndexAndReferenceSource   (comedi_device *dev,\r
+                                                BYTE b_ModulNbr,\r
+                                                BYTE b_SourceSelection)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if incremental counter */\r
+          /*******************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER)\r
+             {\r
+             /******************************/\r
+             /* Test if firmware >= Rev1.5 */\r
+             /******************************/\r
+\r
+             if ((devpriv->s_BoardInfos.\r
+                  dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3135)\r
+                {\r
+                /*****************************/\r
+                /* Test the source selection */\r
+                /*****************************/\r
+\r
+                if (b_SourceSelection == APCI1710_SOURCE_0 ||\r
+                    b_SourceSelection == APCI1710_SOURCE_1)\r
+                   {\r
+                   /******************************************/\r
+                   /* Test if invert the index and reference */\r
+                   /******************************************/\r
+\r
+                   if (b_SourceSelection == APCI1710_SOURCE_1)\r
+                      {\r
+                      /********************************************/\r
+                      /* Invert index and reference source (DQ25) */\r
+                      /********************************************/\r
+\r
+                      devpriv->s_ModuleInfo [b_ModulNbr].\r
+                      s_SiemensCounterInfo.\r
+                      s_ModeRegister.\r
+                      s_ByteModeRegister.\r
+                      b_ModeRegister4 = devpriv->\r
+                                        s_ModuleInfo [b_ModulNbr].\r
+                                        s_SiemensCounterInfo.\r
+                                        s_ModeRegister.\r
+                                        s_ByteModeRegister.\r
+                                        b_ModeRegister4 | APCI1710_INVERT_INDEX_RFERENCE;\r
+                      }\r
+                   else\r
+                      {\r
+                      /****************************************/\r
+                      /* Set the default configuration (DQ25) */\r
+                      /****************************************/\r
+\r
+                      devpriv->s_ModuleInfo [b_ModulNbr].\r
+                      s_SiemensCounterInfo.\r
+                      s_ModeRegister.\r
+                      s_ByteModeRegister.\r
+                      b_ModeRegister4 = devpriv->\r
+                                        s_ModuleInfo [b_ModulNbr].\r
+                                        s_SiemensCounterInfo.\r
+                                        s_ModeRegister.\r
+                                        s_ByteModeRegister.\r
+                                        b_ModeRegister4 & APCI1710_DEFAULT_INDEX_RFERENCE;\r
+                      }\r
+                   } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)\r
+                else\r
+                   {\r
+                   /*********************************/\r
+                   /* The source selection is wrong */\r
+                    /*********************************/\r
+\r                   DPRINTK("The source selection is wrong\n");
+                   i_ReturnValue = -4;\r
+                   } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)\r
+                }\r
+             else\r
+                {\r
+                /**************************************/\r
+                /* The module is not a counter module */\r
+                /**************************************/\r
+\r               DPRINTK("The module is not a counter module\n");       
+                i_ReturnValue = -3;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /**************************************/\r
+             /* The module is not a counter module */\r
+             /**************************************/\r
+\r            DPRINTK("The module is not a counter module\n");  
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***************************************/\r
+          /* The selected module number is wrong */\r
+          /***************************************/\r
+\r         DPRINTK("The selected module number is wrong\n");    
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_    i_APCI1710_SetDigitalChlOn                   |\r
+|                                 (BYTE_  b_BoardHandle,                    |\r
+|                                  BYTE_  b_ModulNbr)                       |\r
++----------------------------------------------------------------------------+\r
+| Task              : Sets the digital output H Setting an output means      |\r
+|                    setting an ouput high.                                 |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |\r
+|                                              configured (0 to 3)          |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: Counter not initialised see function               |\r
+|                        "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_SetDigitalChlOn (comedi_device *dev,\r
+                                   BYTE  b_ModulNbr)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             devpriv->\r
+             s_ModuleInfo [b_ModulNbr].\r
+             s_SiemensCounterInfo.\r
+             s_ModeRegister.\r
+             s_ByteModeRegister.\r
+             b_ModeRegister3 = devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister3 | 0x10;\r
+\r
+             /*********************/\r
+             /* Set the output On */\r
+             /*********************/\r
+\r
+                 outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                     s_SiemensCounterInfo.\r
+                     s_ModeRegister.\r
+                     dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                     ui_Address + 20 + (64 * b_ModulNbr));\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r             DPRINTK("Counter not initialised\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_    i_APCI1710_SetDigitalChlOff                  |\r
+|                                 (BYTE_  b_BoardHandle,                    |\r
+|                                  BYTE_  b_ModulNbr)                       |\r
++----------------------------------------------------------------------------+\r
+| Task              : Resets the digital output H. Resetting an output means |\r
+|                    setting an ouput low.                                  |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |\r
+|                                              configured (0 to 3)          |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: Counter not initialised see function               |\r
+|                        "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_SetDigitalChlOff (comedi_device *dev,\r
+                                    BYTE  b_ModulNbr)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             devpriv->\r
+             s_ModuleInfo [b_ModulNbr].\r
+             s_SiemensCounterInfo.\r
+             s_ModeRegister.\r
+             s_ByteModeRegister.\r
+             b_ModeRegister3 = devpriv->\r
+                               s_ModuleInfo [b_ModulNbr].\r
+                               s_SiemensCounterInfo.\r
+                               s_ModeRegister.\r
+                               s_ByteModeRegister.\r
+                               b_ModeRegister3 & 0xEF;\r
+\r
+             /**********************/\r
+             /* Set the output Off */\r
+             /**********************/\r
+\r
+                 outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                     s_SiemensCounterInfo.\r
+                     s_ModeRegister.\r
+                     dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                     ui_Address + 20 + (64 * b_ModulNbr));\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*########################################################################### */\r
+\r
+                                                       // INSN WRITE\r
+/*########################################################################### */\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     :INT       i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)                   |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable Disable functions for INC_CPT                                       |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : \r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : \r
++----------------------------------------------------------------------------+\r
+*/\r
+INT    i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)\r
+{\r
+       UINT ui_WriteType;\r
+       INT i_ReturnValue=0;\r
+        \r
+       ui_WriteType=CR_CHAN(insn->chanspec);\r
+       devpriv->tsk_Current=current; // Save the current process task structure
+\r
+       switch(ui_WriteType)\r
+       {\r
+               case APCI1710_INCCPT_ENABLELATCHINTERRUPT:\r
+                       i_ReturnValue = i_APCI1710_EnableLatchInterrupt (dev,\r
+                                        (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+               case APCI1710_INCCPT_DISABLELATCHINTERRUPT:\r
+                       i_ReturnValue = i_APCI1710_DisableLatchInterrupt (dev,\r
+                                                (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+               case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:\r
+                       i_ReturnValue = i_APCI1710_Write16BitCounterValue       (dev,\r
+                                                (BYTE) CR_AREF(insn->chanspec),\r
+                                                (BYTE)  data[0],\r
+                                                (UINT)  data[1]);\r
+               break;\r
+\r
+               case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:\r
+                        i_ReturnValue = i_APCI1710_Write32BitCounterValue       (dev,\r
+                                                (BYTE) CR_AREF(insn->chanspec),\r
+                                                (ULONG) data[0]);\r
+\r
+               break;\r
+\r
+               case APCI1710_INCCPT_ENABLEINDEX:\r
+                       i_APCI1710_EnableIndex  (dev,\r
+                                (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+               case APCI1710_INCCPT_DISABLEINDEX:                                              \r
+                       i_ReturnValue = i_APCI1710_DisableIndex  (dev,\r
+                                (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+               case APCI1710_INCCPT_ENABLECOMPARELOGIC:                                        \r
+                       i_ReturnValue = i_APCI1710_EnableCompareLogic   (dev,\r
+                                        (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+               case APCI1710_INCCPT_DISABLECOMPARELOGIC:       \r
+                       i_ReturnValue = i_APCI1710_DisableCompareLogic  (dev,\r
+                                        (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+               case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT:                        \r
+                       i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement   (dev,\r
+                                                (BYTE) CR_AREF(insn->chanspec),\r
+                                                (BYTE)          data[0]);\r
+               break;\r
+\r
+               case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT:                                       \r
+                       i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement  (dev,\r
+                                                (BYTE) CR_AREF(insn->chanspec));\r
+               break;\r
+\r
+               default:\r
+                       printk("Write Config Parameter Wrong\n");\r
+       }\r
+\r
+       if(i_ReturnValue>=0) i_ReturnValue =insn->n;\r
+       return (i_ReturnValue);\r
+}\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_EnableLatchInterrupt                  |\r
+|                               (BYTE_ b_BoardHandle,                        |\r
+|                                BYTE_ b_ModulNbr)                           |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable the latch interrupt from selected module        |\r
+|                     (b_ModulNbr). Each software or hardware latch occur a  |\r
+|                     interrupt.                                             |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |\r
+|                     BYTE_ b_ModulNbr    : Module number to configure       |\r
+|                                           (0 to 3)                         |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Interrupt routine not installed see function       |\r
+|                         "i_APCI1710_SetBoardIntRoutine"                    |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT  i_APCI1710_EnableLatchInterrupt (comedi_device *dev,\r
+                                        BYTE b_ModulNbr)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+\r
+                /********************/\r
+                /* Enable interrupt */\r
+                /********************/\r
+\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister2 = devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister2 | APCI1710_ENABLE_LATCH_INT;\r
+\r
+                /***************************/\r
+                /* Write the configuration */\r
+                /***************************/\r
+\r
+                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_SiemensCounterInfo.\r
+                        s_ModeRegister.\r
+                        dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                        ui_Address + 20 + (64 * b_ModulNbr));\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_DisableLatchInterrupt                 |\r
+|                               (BYTE_ b_BoardHandle,                        |\r
+|                                BYTE_ b_ModulNbr)                           |\r
++----------------------------------------------------------------------------+\r
+| Task              : Disable the latch interrupt from selected module       |\r
+|                     (b_ModulNbr).                                          |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |\r
+|                     BYTE_ b_ModulNbr    : Module number to configure       |\r
+|                                           (0 to 3)                         |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Interrupt routine not installed see function       |\r
+|                         "i_APCI1710_SetBoardIntRoutine"                    |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_DisableLatchInterrupt        (comedi_device *dev,\r
+                                                BYTE b_ModulNbr)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+\r
+                /***************************/\r
+                /* Write the configuration */\r
+                /***************************/\r
+\r
+                  outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_SiemensCounterInfo.\r
+                        s_ModeRegister.\r
+                        dw_ModeRegister1_2_3_4 & ((APCI1710_DISABLE_LATCH_INT << 8) | 0xFF),devpriv->s_BoardInfos.\r
+                        ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+                  mdelay(1000);\r
+\r
+                /*********************/\r
+                /* Disable interrupt */\r
+                /*********************/\r
+\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister2 = devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister2 & APCI1710_DISABLE_LATCH_INT;\r
+\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_Write16BitCounterValue                |\r
+|                                               (BYTE_  b_BoardHandle        |\r
+|                                                BYTE_  b_ModulNbr,          |\r
+|                                                BYTE_  b_SelectedCounter,   |\r
+|                                                UINT_ ui_WriteValue)        |\r
++----------------------------------------------------------------------------+\r
+| Task              : Write a 16-Bit value (ui_WriteValue) in to the selected|\r
+|                     16-Bit counter (b_SelectedCounter) from selected module|\r
+|                     (b_ModulNbr).                                          |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                              (0 to 3)                      |\r
+|                     BYTE_ b_SelectedCounter : Selected 16-Bit counter      |\r
+|                                               (0 or 1)                     |\r
+|                     UINT_ ui_WriteValue     : 16-Bit write value           |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: The selected 16-Bit counter parameter is wrong     |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_Write16BitCounterValue       (comedi_device *dev,\r
+                                                BYTE  b_ModulNbr,\r
+                                                BYTE  b_SelectedCounter,\r
+                                                UINT  ui_WriteValue)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /******************************/\r
+             /* Test the counter selection */\r
+             /******************************/\r
+\r
+             if (b_SelectedCounter < 2)\r
+                {\r
+                /*******************/\r
+                /* Write the value */\r
+                /*******************/\r
+\r
+               outl((ULONG) ((ULONG) (ui_WriteValue) << (16 * b_SelectedCounter)),devpriv->s_BoardInfos.\r
+                        ui_Address + 8 + (b_SelectedCounter * 4) + (64 * b_ModulNbr));\r
+                }\r
+             else\r
+                {\r
+                /**************************************************/\r
+                /* The selected 16-Bit counter parameter is wrong */\r
+                /**************************************************/\r
+\r               DPRINTK("The selected 16-Bit counter parameter is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_Write32BitCounterValue                |\r
+|                                               (BYTE_   b_BoardHandle       |\r
+|                                                BYTE_   b_ModulNbr,         |\r
+|                                                ULONG_ ul_WriteValue)       |\r
++----------------------------------------------------------------------------+\r
+| Task              : Write a 32-Bit value (ui_WriteValue) in to the selected|\r
+|                     module (b_ModulNbr).                                   |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                              (0 to 3)                      |\r
+|                     ULONG_ ul_WriteValue    : 32-Bit write value           |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_Write32BitCounterValue       (comedi_device *dev,\r
+                                                BYTE   b_ModulNbr,\r
+                                                ULONG ul_WriteValue)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*******************/\r
+             /* Write the value */\r
+             /*******************/\r
+\r
+                  outl(ul_WriteValue,devpriv->s_BoardInfos.\r
+                     ui_Address + 4 + (64 * b_ModulNbr));\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_EnableIndex (BYTE_  b_BoardHandle,    |\r
+|                                                   BYTE_  b_ModulNbr)       |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable the INDEX actions                               |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Index not initialised see function                 |\r
+|                         "i_APCI1710_InitIndex"                             |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_EnableIndex  (comedi_device *dev,\r
+                                BYTE b_ModulNbr)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       ULONG ul_InterruptLatchReg;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*****************************/\r
+             /* Test if index initialised */\r
+             /*****************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_IndexInit)\r
+                {\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister2 = devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister2 | APCI1710_ENABLE_INDEX;\r
+\r
+                 ul_InterruptLatchReg=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 24 + (64 * b_ModulNbr));\r
+\r
+\r
+                 outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_SiemensCounterInfo.\r
+                        s_ModeRegister.\r
+                        dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                        ui_Address + 20 + (64 * b_ModulNbr));\r
+                }\r
+             else\r
+                {\r
+                /*************************************************************/\r
+                /* Index not initialised see function "i_APCI1710_InitIndex" */\r
+                /*************************************************************/\r
+\r               DPRINTK("Index not initialised \n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_DisableIndex (BYTE_  b_BoardHandle,   |\r
+|                                                    BYTE_  b_ModulNbr)      |\r
++----------------------------------------------------------------------------+\r
+| Task              : Disable the INDEX actions                              |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Index not initialised see function                 |\r
+|                         "i_APCI1710_InitIndex"                             |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT  i_APCI1710_DisableIndex (comedi_device *dev,\r
+                                BYTE b_ModulNbr)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*****************************/\r
+             /* Test if index initialised */\r
+             /*****************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_IndexInit)\r
+                {\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister2 = devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister2 & APCI1710_DISABLE_INDEX;\r
+\r
+                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_SiemensCounterInfo.\r
+                        s_ModeRegister.\r
+                        dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                        ui_Address + 20 + (64 * b_ModulNbr));\r
+                }\r
+             else\r
+                {\r
+                /*************************************************************/\r
+                /* Index not initialised see function "i_APCI1710_InitIndex" */\r
+                /*************************************************************/\r
+\r               DPRINTK("Index not initialised  \n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_EnableCompareLogic                    |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr)                         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable the 32-Bit compare logic. At that moment that   |\r
+|                     the incremental counter arrive to the compare value a  |\r
+|                     interrupt is generated.                                |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                     BYTE_  b_ModulNbr       : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Compare logic not initialised.                     |\r
+|                         See function "i_APCI1710_InitCompareLogic"         |\r
+|                     -5: Interrupt function not initialised.                |\r
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_EnableCompareLogic   (comedi_device *dev,\r
+                                        BYTE   b_ModulNbr)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*************************************/\r
+             /* Test if compare logic initialised */\r
+             /*************************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_CompareLogicInit == 1)\r
+                {\r
+                   devpriv->\r
+                   s_ModuleInfo [b_ModulNbr].\r
+                   s_SiemensCounterInfo.\r
+                   s_ModeRegister.\r
+                   s_ByteModeRegister.\r
+                   b_ModeRegister3 = devpriv->\r
+                                     s_ModuleInfo [b_ModulNbr].\r
+                                     s_SiemensCounterInfo.\r
+                                     s_ModeRegister.\r
+                                     s_ByteModeRegister.\r
+                                     b_ModeRegister3 | APCI1710_ENABLE_COMPARE_INT;\r
+\r
+                   /***************************/\r
+                   /* Write the configuration */\r
+                   /***************************/\r
+\r
+                       outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                           s_SiemensCounterInfo.\r
+                           s_ModeRegister.\r
+                           dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                           ui_Address + 20 + (64 * b_ModulNbr));\r
+                }\r
+             else\r
+                {\r
+                /*********************************/\r
+                /* Compare logic not initialised */\r
+                /*********************************/\r
+\r               DPRINTK("Compare logic not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_DisableCompareLogic                   |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr)                         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Disable the 32-Bit compare logic.\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                     BYTE_  b_ModulNbr       : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Compare logic not initialised.                     |\r
+|                         See function "i_APCI1710_InitCompareLogic"         |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_DisableCompareLogic  (comedi_device *dev,\r
+                                        BYTE   b_ModulNbr)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*************************************/\r
+             /* Test if compare logic initialised */\r
+             /*************************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_CompareLogicInit == 1)\r
+                {\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister3 = devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister3 & APCI1710_DISABLE_COMPARE_INT;\r
+\r
+                /***************************/\r
+                /* Write the configuration */\r
+                /***************************/\r
+\r
+                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_SiemensCounterInfo.\r
+                        s_ModeRegister.\r
+                        dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                        ui_Address + 20 + (64 * b_ModulNbr));\r
+                }\r
+             else\r
+                {\r
+                /*********************************/\r
+                /* Compare logic not initialised */\r
+                /*********************************/\r
+\r               DPRINTK("Compare logic not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+       /*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_EnableFrequencyMeasurement            |\r
+|                              (BYTE_   b_BoardHandle,                      |\r
+|                               BYTE_   b_ModulNbr,                         |\r
+|                               BYTE_   b_InterruptEnable)                  |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enables the frequency measurement function             |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |\r
+|                                              configured (0 to 3)          |\r
+|                    BYTE_  b_InterruptEnable: Enable or disable the        |\r
+|                                              interrupt.                   |\r
+|                                              APCI1710_ENABLE:             |\r
+|                                              Enable the interrupt         |\r
+|                                              APCI1710_DISABLE:            |\r
+|                                              Disable the interrupt        |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: Counter not initialised see function               |\r
+|                        "i_APCI1710_InitCounter"                           |\r
+|                     -4: Frequency measurement logic not initialised.       |\r
+|                        See function "i_APCI1710_InitFrequencyMeasurement" |\r
+|                     -5: Interrupt parameter is wrong                       |\r
+|                     -6: Interrupt function not initialised.                |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_EnableFrequencyMeasurement   (comedi_device *dev,\r
+                                                BYTE    b_ModulNbr,\r
+                                                BYTE    b_InterruptEnable)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /********************************************/\r
+             /* Test if frequency mesurement initialised */\r
+             /********************************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_FrequencyMeasurementInit == 1)\r
+                {\r
+                /***************************/\r
+                /* Test the interrupt mode */\r
+                /***************************/\r
+\r
+                if ((b_InterruptEnable == APCI1710_DISABLE) ||\r
+                    (b_InterruptEnable == APCI1710_ENABLE))\r
+                   {\r
+\r
+                      /************************************/\r
+                      /* Enable the frequency measurement */\r
+                      /************************************/\r
+\r
+                      devpriv->\r
+                      s_ModuleInfo [b_ModulNbr].\r
+                      s_SiemensCounterInfo.\r
+                      s_ModeRegister.\r
+                      s_ByteModeRegister.\r
+                      b_ModeRegister3 = devpriv->\r
+                                        s_ModuleInfo [b_ModulNbr].\r
+                                        s_SiemensCounterInfo.\r
+                                        s_ModeRegister.\r
+                                        s_ByteModeRegister.\r
+                                        b_ModeRegister3 | APCI1710_ENABLE_FREQUENCY;\r
+\r
+                      /*********************************************/\r
+                      /* Disable or enable the frequency interrupt */\r
+                      /*********************************************/\r
+\r
+                      devpriv->\r
+                      s_ModuleInfo [b_ModulNbr].\r
+                      s_SiemensCounterInfo.\r
+                      s_ModeRegister.\r
+                      s_ByteModeRegister.\r
+                      b_ModeRegister3 = (devpriv->\r
+                                         s_ModuleInfo [b_ModulNbr].\r
+                                         s_SiemensCounterInfo.\r
+                                         s_ModeRegister.\r
+                                         s_ByteModeRegister.\r
+                                         b_ModeRegister3 & APCI1710_DISABLE_FREQUENCY_INT) | (b_InterruptEnable << 3);\r
+\r
+                      /***************************/\r
+                      /* Write the configuration */\r
+                      /***************************/\r
+\r
+                          outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                              s_SiemensCounterInfo.\r
+                              s_ModeRegister.\r
+                              dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                              ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+                      devpriv->\r
+                      s_ModuleInfo [b_ModulNbr].\r
+                      s_SiemensCounterInfo.\r
+                      s_InitFlag.\r
+                      b_FrequencyMeasurementEnable = 1;\r
+                   }\r
+                else\r
+                   {\r
+                   /********************************/\r
+                   /* Interrupt parameter is wrong */\r
+                   /********************************/\r
+\r                  DPRINTK("Interrupt parameter is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /***********************************************/\r
+                /* Frequency measurement logic not initialised */\r
+                /***********************************************/\r
+\r               DPRINTK("Frequency measurement logic not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r          DPRINTK("The selected module number parameter is wrong\n"); 
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+       /*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_DisableFrequencyMeasurement           |\r
+|                              (BYTE_   b_BoardHandle,                      |\r
+|                               BYTE_   b_ModulNbr)                         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Disables the frequency measurement function             |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |\r
+|                                              configured (0 to 3)          |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: Counter not initialised see function               |\r
+|                        "i_APCI1710_InitCounter"                           |\r
+|                     -4: Frequency measurement logic not initialised.       |\r
+|                        See function "i_APCI1710_InitFrequencyMeasurement" |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_DisableFrequencyMeasurement  (comedi_device *dev,\r
+                                                BYTE    b_ModulNbr)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /********************************************/\r
+             /* Test if frequency mesurement initialised */\r
+             /********************************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_FrequencyMeasurementInit == 1)\r
+                {\r
+                /*************************************/\r
+                /* Disable the frequency measurement */\r
+                /*************************************/\r
+\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_ModeRegister.\r
+                s_ByteModeRegister.\r
+                b_ModeRegister3 = devpriv->\r
+                                  s_ModuleInfo [b_ModulNbr].\r
+                                  s_SiemensCounterInfo.\r
+                                  s_ModeRegister.\r
+                                  s_ByteModeRegister.\r
+                                  b_ModeRegister3 & APCI1710_DISABLE_FREQUENCY\r
+                                  // Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared\r
+                                  & APCI1710_DISABLE_FREQUENCY_INT;\r
+                                  // End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared\r
+\r
+                /***************************/\r
+                /* Write the configuration */\r
+                /***************************/\r
+\r
+                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_SiemensCounterInfo.\r
+                        s_ModeRegister.\r
+                        dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos.\r
+                        ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+                /*************************************/\r
+                /* Disable the frequency measurement */\r
+                /*************************************/\r
+\r
+                devpriv->\r
+                s_ModuleInfo [b_ModulNbr].\r
+                s_SiemensCounterInfo.\r
+                s_InitFlag.\r
+                b_FrequencyMeasurementEnable = 0;\r
+                }\r
+             else\r
+                {\r
+                /***********************************************/\r
+                /* Frequency measurement logic not initialised */\r
+                /***********************************************/\r
+\r               DPRINTK("Frequency measurement logic not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*########################################################################### */\r
+\r
+                                                       // INSN READ\r
+\r
+/*########################################################################### */\r
+\r
+                                        \r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     :INT       i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)                   |\r
++----------------------------------------------------------------------------+\r
+| Task              : Read and Get functions for INC_CPT                                       |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : \r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : \r
++----------------------------------------------------------------------------+\r
+*/\r
+INT    i_APCI1710_InsnReadINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data)\r
+{\r
+       UINT ui_ReadType;\r
+       INT  i_ReturnValue=0;
+        \r
+       ui_ReadType=CR_CHAN(insn->chanspec);\r
+\r       devpriv->tsk_Current=current; // Save the current process task structure
+       switch(ui_ReadType)\r
+       {\r
+       case APCI1710_INCCPT_READLATCHREGISTERSTATUS:\r
+               i_ReturnValue=i_APCI1710_ReadLatchRegisterStatus      (dev,\r
+                                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                                (BYTE)   CR_RANGE(insn->chanspec),\r
+                                                (PBYTE)  &data[0]);\r
+       break;\r
+\r
+       case APCI1710_INCCPT_READLATCHREGISTERVALUE:\r
+               i_ReturnValue=i_APCI1710_ReadLatchRegisterValue       (dev,\r
+                                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                                (BYTE)   CR_RANGE(insn->chanspec),\r
+                                                (PULONG) &data[0]);\r
+                printk("Latch Register Value %d\n",data[0]);
+       break;\r
+\r
+       case APCI1710_INCCPT_READ16BITCOUNTERVALUE:\r
+               i_ReturnValue=i_APCI1710_Read16BitCounterValue        (dev,\r
+                                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                                (BYTE)   CR_RANGE(insn->chanspec),\r
+                                                (PUINT) &data[0]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_READ32BITCOUNTERVALUE:\r
+               i_ReturnValue=i_APCI1710_Read32BitCounterValue        (dev,\r
+                                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                                (PULONG)  &data[0]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_GETINDEXSTATUS:\r
+                i_ReturnValue=i_APCI1710_GetIndexStatus      (dev,\r
+                                       (BYTE)   CR_AREF(insn->chanspec),\r
+                                       (PBYTE) &data[0]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_GETREFERENCESTATUS:\r
+                i_ReturnValue=i_APCI1710_GetReferenceStatus      (dev,\r
+                                           (BYTE)   CR_AREF(insn->chanspec),\r
+                                           (PBYTE)  &data[0]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_GETUASSTATUS:\r
+               i_ReturnValue=i_APCI1710_GetUASStatus (dev,\r
+                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                (PBYTE) &data[0]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_GETCBSTATUS:\r
+               i_ReturnValue=i_APCI1710_GetCBStatus  (dev,\r
+                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                (PBYTE) &data[0]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_GET16BITCBSTATUS:\r
+               i_ReturnValue=i_APCI1710_Get16BitCBStatus       (dev,\r
+                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                (PBYTE) &data[0],\r
+                                (PBYTE) &data[1]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_GETUDSTATUS:\r
+               i_ReturnValue=i_APCI1710_GetUDStatus  (dev,\r
+                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                (PBYTE) &data[0]);
+       
+       break;\r
+    \r
+       case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:\r
+               i_ReturnValue=i_APCI1710_GetInterruptUDLatchedStatus  (dev,\r
+                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                (PBYTE) &data[0]);\r
+       break;\r
+    \r
+       case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:\r
+               i_ReturnValue=i_APCI1710_ReadFrequencyMeasurement (dev,\r
+                                (BYTE)   CR_AREF(insn->chanspec),\r
+                                (PBYTE)  &data[0],\r
+                                (PBYTE)  &data[1],\r
+                                (PULONG) &data[2]);\r
+       break;\r
+         
+        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;                      
+    \r
+       default:\r
+               printk("ReadType Parameter wrong\n");\r
+       }\r
+\r
+       if(i_ReturnValue>=0) i_ReturnValue =insn->n;\r
+       return (i_ReturnValue); \r
+\r
+}\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ReadLatchRegisterStatus               |\r
+|                                                   (BYTE_   b_BoardHandle,  |\r
+|                                                    BYTE_   b_ModulNbr,     |\r
+|                                                    BYTE_   b_LatchReg,     |\r
+|                                                    PBYTE_ pb_LatchStatus)  |\r
++----------------------------------------------------------------------------+\r
+| Task              : Read the latch register status from selected module    |\r
+|                     (b_ModulNbr) and selected latch register (b_LatchReg). |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |\r
+|                     BYTE_ b_ModulNbr    : Module number to configure       |\r
+|                                           (0 to 3)                         |\r
+|                     BYTE_ b_LatchReg    : Selected latch register          |\r
+|                               0 : for the first latch register             |\r
+|                               1 : for the second latch register            |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_LatchStatus :   Latch register status.       |\r
+|                                               0 : No latch occur           |\r
+|                                               1 : A software latch occur   |\r
+|                                               2 : A hardware latch occur   |\r
+|                                               3 : A software and hardware  |\r
+|                                                   latch occur              |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: The selected latch register parameter is wrong     |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_ReadLatchRegisterStatus      (comedi_device *dev,\r
+                                                BYTE   b_ModulNbr,\r
+                                                BYTE   b_LatchReg,\r
+                                                PBYTE pb_LatchStatus)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_LatchReg;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*************************************/\r
+             /* Test the latch register parameter */\r
+             /*************************************/\r
+\r
+             if (b_LatchReg < 2)\r
+                {\r
+                       dw_LatchReg=inl(devpriv->s_BoardInfos.\r
+                                                       ui_Address + (64 * b_ModulNbr));\r
+\r
+                *pb_LatchStatus = (BYTE) ((dw_LatchReg >> (b_LatchReg * 4)) & 0x3);\r
+                }\r
+             else\r
+                {\r
+                /**************************************************/\r
+                /* The selected latch register parameter is wrong */\r
+                /**************************************************/\r
+\r                DPRINTK("The selected latch register parameter is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ReadLatchRegisterValue                |\r
+|                                                   (BYTE_     b_BoardHandle,|\r
+|                                                    BYTE_     b_ModulNbr,   |\r
+|                                                    BYTE_     b_LatchReg,   |\r
+|                                                    PULONG_ pul_LatchValue) |\r
++----------------------------------------------------------------------------+\r
+| Task              : Read the latch register value from selected module     |\r
+|                     (b_ModulNbr) and selected latch register (b_LatchReg). |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle : Handle of board APCI-1710        |\r
+|                     BYTE_ b_ModulNbr    : Module number to configure       |\r
+|                                           (0 to 3)                         |\r
+|                     BYTE_ b_LatchReg    : Selected latch register          |\r
+|                               0 : for the first latch register             |\r
+|                               1 : for the second latch register            |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PULONG_ pul_LatchValue : Latch register value          |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: The selected latch register parameter is wrong     |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_ReadLatchRegisterValue       (comedi_device *dev,\r
+                                                BYTE     b_ModulNbr,\r
+                                                BYTE     b_LatchReg,\r
+                                                PULONG pul_LatchValue)\r
+       {\r
+       INT i_ReturnValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*************************************/\r
+             /* Test the latch register parameter */\r
+             /*************************************/\r
+\r
+             if (b_LatchReg < 2)\r
+                {\r
+                       *pul_LatchValue=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + ((b_LatchReg + 1) * 4) + (64 * b_ModulNbr));
+                    
+                }\r
+             else\r
+                {\r
+                /**************************************************/\r
+                /* The selected latch register parameter is wrong */\r
+                /**************************************************/\r
+\r               DPRINTK("The selected latch register parameter is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_Read16BitCounterValue                 |\r
+|                                       (BYTE_     b_BoardHandle,            |\r
+|                                        BYTE_     b_ModulNbr,               |\r
+|                                        BYTE_     b_SelectedCounter,        |\r
+|                                        PUINT_   pui_CounterValue)          |\r
++----------------------------------------------------------------------------+\r
+| Task              : Latch the selected 16-Bit counter (b_SelectedCounter)  |\r
+|                     from selected module (b_ModulNbr) in to the first      |\r
+|                     latch register and return the latched value.           |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                              (0 to 3)                      |\r
+|                     BYTE_ b_SelectedCounter : Selected 16-Bit counter      |\r
+|                                               (0 or 1)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PUINT_ pui_CounterValue : 16-Bit counter value         |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: The selected 16-Bit counter parameter is wrong     |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_Read16BitCounterValue        (comedi_device *dev,\r
+                                                BYTE    b_ModulNbr,\r
+                                                BYTE    b_SelectedCounter,\r
+                                                PUINT pui_CounterValue)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_LathchValue = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /******************************/\r
+             /* Test the counter selection */\r
+             /******************************/\r
+\r
+             if (b_SelectedCounter < 2)\r
+                {\r
+                /*********************/\r
+                /* Latch the counter */\r
+                /*********************/\r
+\r
+                         outl(1,devpriv->s_BoardInfos.\r
+                        ui_Address + (64 * b_ModulNbr));\r
+\r
+                /************************/\r
+                /* Read the latch value */\r
+                /************************/\r
+\r
+                       dw_LathchValue=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 4 + (64 * b_ModulNbr));\r
+\r
+                *pui_CounterValue = (UINT) ((dw_LathchValue >> (16 * b_SelectedCounter)) & 0xFFFFU);\r
+                }\r
+             else\r
+                {\r
+                /**************************************************/\r
+                /* The selected 16-Bit counter parameter is wrong */\r
+                /**************************************************/\r
+\r               DPRINTK("The selected 16-Bit counter parameter is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_Read32BitCounterValue                 |\r
+|                                       (BYTE_     b_BoardHandle,            |\r
+|                                        BYTE_     b_ModulNbr,               |\r
+|                                        PULONG_ pul_CounterValue)           |\r
++----------------------------------------------------------------------------+\r
+| Task              : Latch the 32-Bit counter from selected module          |\r
+|                     (b_ModulNbr) in to the first latch register and return |\r
+|                     the latched value.                                     |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                              (0 to 3)                      |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PULONG_  pul_CounterValue : 32-Bit counter value       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_Read32BitCounterValue        (comedi_device *dev,\r
+                                                BYTE      b_ModulNbr,\r
+                                                PULONG  pul_CounterValue)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*********************/\r
+             /* Tatch the counter */\r
+             /*********************/\r
+\r
+                  outl(1,devpriv->s_BoardInfos.\r
+                     ui_Address + (64 * b_ModulNbr));\r
+\r
+             /************************/\r
+             /* Read the latch value */\r
+             /************************/\r
+\r
+                  *pul_CounterValue=inl(devpriv->s_BoardInfos.\r
+                    ui_Address + 4 + (64 * b_ModulNbr));\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetIndexStatus (BYTE_   b_BoardHandle,|\r
+|                                                      BYTE_   b_ModulNbr,   |\r
+|                                                      PBYTE_ pb_IndexStatus)|\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the index status                                |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_IndexStatus   : 0 : No INDEX occur           |\r
+|                                               1 : A INDEX occur            |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Index not initialised see function                 |\r
+|                         "i_APCI1710_InitIndex"                             |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_GetIndexStatus      (comedi_device *dev,\r
+                                       BYTE   b_ModulNbr,\r
+                                       PBYTE pb_IndexStatus)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg   = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*****************************/\r
+             /* Test if index initialised */\r
+             /*****************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_IndexInit)\r
+                {\r
+                        dw_StatusReg= inl(devpriv->s_BoardInfos.\r
+                        ui_Address + 12 + (64 * b_ModulNbr));\r
+\r
+                *pb_IndexStatus = (BYTE) (dw_StatusReg & 1);\r
+                }\r
+             else\r
+                {\r
+                /*************************************************************/\r
+                /* Index not initialised see function "i_APCI1710_InitIndex" */\r
+                /*************************************************************/\r
+\r               DPRINTK("Index not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetReferenceStatus                    |\r
+|                                                (BYTE_   b_BoardHandle,     |\r
+|                                                 BYTE_   b_ModulNbr,        |\r
+|                                                 PBYTE_ pb_ReferenceStatus) |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the reference status                            |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_ReferenceStatus   : 0 : No REFERENCE occur   |\r
+|                                                   1 : A REFERENCE occur    |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Reference not initialised see function             |\r
+|                         "i_APCI1710_InitReference"                         |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_GetReferenceStatus      (comedi_device *dev,\r
+                                           BYTE   b_ModulNbr,\r
+                                           PBYTE  pb_ReferenceStatus)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg   = 0;\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*********************************/\r
+             /* Test if reference initialised */\r
+             /*********************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_ReferenceInit)\r
+                {\r
+                       dw_StatusReg=inl(devpriv->s_BoardInfos.\r
+                        ui_Address + 24 + (64 * b_ModulNbr));\r
+\r
+                *pb_ReferenceStatus = (BYTE) (~dw_StatusReg & 1);\r
+                }\r
+             else\r
+                {\r
+                /*********************************************************************/\r
+                /* Reference not initialised see function "i_APCI1710_InitReference" */\r
+                /*********************************************************************/\r
+\r               DPRINTK("Reference not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetUASStatus                          |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                PBYTE_ pb_UASStatus)                        |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the error signal (UAS) status                   |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_UASStatus      : 0 : UAS is low "0"          |\r
+|                                                1 : UAS is high "1"         |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_GetUASStatus (comedi_device *dev,\r
+                                BYTE   b_ModulNbr,\r
+                                PBYTE pb_UASStatus)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg   = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+                  dw_StatusReg=inl(devpriv->s_BoardInfos.\r
+                     ui_Address + 24 + (64 * b_ModulNbr));\r
+\r
+             *pb_UASStatus = (BYTE) ((dw_StatusReg >> 1) & 1);\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r 
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetCBStatus                           |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                PBYTE_ pb_CBStatus)                         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the counter overflow status                     |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_CBStatus      : 0 : Counter no overflow      |\r
+|                                               1 : Counter overflow         |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_GetCBStatus  (comedi_device *dev,\r
+                                BYTE   b_ModulNbr,\r
+                                PBYTE pb_CBStatus)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg   = 0;\r
+       \r
+\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+                       dw_StatusReg=inl(devpriv->s_BoardInfos.\r
+                     ui_Address + 16 + (64 * b_ModulNbr));\r
+\r
+             *pb_CBStatus = (BYTE) (dw_StatusReg & 1);\r                              
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_Get16BitCBStatus                      |\r
+|                                      (BYTE_     b_BoardHandle,            |\r
+|                                       BYTE_     b_ModulNbr,               |\r
+|                                       PBYTE_ pb_CBStatusCounter0,         |\r
+|                                       PBYTE_ pb_CBStatusCounter1)         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Returns the counter overflow (counter initialised to   |\r
+|                    2*16-bit) status from selected incremental counter     |\r
+|                    module                                                 |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_CBStatusCounter0 : 0 : No overflow occur for |\r
+|                                                     the first 16-bit      |\r
+|                                                     counter               |\r
+|                                                 1 : Overflow occur for the|\r
+|                                                     first 16-bit counter  |\r
+|                    PBYTE_ pb_CBStatusCounter1 : 0 : No overflow occur for |\r
+|                                                     the second 16-bit     |\r
+|                                                     counter               |\r
+|                                                 1 : Overflow occur for the|\r
+|                                                     second 16-bit counter |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Counter not initialised to 2*16-bit mode.          |\r
+|                        See function "i_APCI1710_InitCounter"              |\r
+|                     -5: Firmware revision error                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_Get16BitCBStatus     (comedi_device *dev,\r
+                                        BYTE     b_ModulNbr,\r
+                                        PBYTE pb_CBStatusCounter0,\r
+                                        PBYTE pb_CBStatusCounter1)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg   = 0;\r
+       \r
+\r       
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /*************************/\r
+             /* Test if 2*16-Bit mode */\r
+             /*************************/\r
+\r
+             if ((devpriv->\r
+                  s_ModuleInfo [b_ModulNbr].\r
+                  s_SiemensCounterInfo.\r
+                  s_ModeRegister.\r
+                  s_ByteModeRegister.\r
+                  b_ModeRegister1 & 0x10) == 0x10)\r
+                {\r
+                /*****************************/\r
+                /* Test the Firmware version */\r
+                /*****************************/\r
+\r
+                if ((devpriv->\r
+                     s_BoardInfos.\r
+                     dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)\r
+                   {\r
+                        dw_StatusReg=inl(devpriv->s_BoardInfos.\r
+                           ui_Address + 16 + (64 * b_ModulNbr));\r
+\r
+                   *pb_CBStatusCounter1 = (BYTE) ((dw_StatusReg >> 0) & 1);\r
+                   *pb_CBStatusCounter0 = (BYTE) ((dw_StatusReg >> 1) & 1);\r
+                   } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)\r
+                else\r
+                   {\r
+                   /****************************/\r
+                   /* Firmware revision error  */\r
+                   /****************************/\r
+\r
+                   i_ReturnValue = -5;\r
+                   } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)\r
+                } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)\r
+             else\r
+                {\r
+                /********************************************/\r
+                /* Counter not initialised to 2*16-bit mode */\r
+                /* "i_APCI1710_InitCounter"                 */\r
+                /********************************************/\r
+\r               DPRINTK("Counter not initialised\n");
+                i_ReturnValue = -4;\r
+                } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)\r
+             } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");             
+             i_ReturnValue = -3;\r
+             } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)\r
+          } // if (b_ModulNbr < 4)\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          } // if (b_ModulNbr < 4)\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetUDStatus                           |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                PBYTE_ pb_UDStatus)                         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the counter progress status                     |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |\r
+|                                                   selected mode down       |\r
+|                                               1 : Counter progress in the  |\r
+|                                                   selected mode up         |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_GetUDStatus  (comedi_device *dev,\r
+                                BYTE   b_ModulNbr,\r
+                                PBYTE pb_UDStatus)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg   = 0;\r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+                  dw_StatusReg=inl(devpriv->s_BoardInfos.\r
+                     ui_Address + 24 + (64 * b_ModulNbr));\r
+\r
+             *pb_UDStatus = (BYTE) ((dw_StatusReg >> 2) & 1);\r
+               
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetInterruptUDLatchedStatus           |\r
+|                               (BYTE_   b_BoardHandle,                      |\r
+|                                BYTE_   b_ModulNbr,                         |\r
+|                                PBYTE_ pb_UDStatus)                         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the counter progress latched status after a     |\r
+|                     index interrupt occur.                                 |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle     : Handle of board APCI-1710    |\r
+|                     BYTE_ b_ModulNbr        : Module number to configure   |\r
+|                                               (0 to 3)                     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |\r
+|                                                   selected mode down       |\r
+|                                               1 : Counter progress in the  |\r
+|                                                   selected mode up         |\r
+|                                               2 : No index interrupt occur |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: No counter module found                            |\r
+|                     -3: Counter not initialised see function               |\r
+|                         "i_APCI1710_InitCounter"                           |\r
+|                     -4: Interrupt function not initialised.                |\r
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_GetInterruptUDLatchedStatus  (comedi_device *dev,\r
+                                                BYTE   b_ModulNbr,\r
+                                                PBYTE pb_UDStatus)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg   = 0;\r
+       \r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+                /*********************************/\r
+                /* Test if index interrupt occur */\r
+                /*********************************/\r
+\r
+                if (devpriv->\r
+                    s_ModuleInfo [b_ModulNbr].\r
+                    s_SiemensCounterInfo.\r
+                    s_InitFlag.\r
+                    b_IndexInterruptOccur == 1)\r
+                   {\r
+                   devpriv->\r
+                   s_ModuleInfo [b_ModulNbr].\r
+                   s_SiemensCounterInfo.\r
+                   s_InitFlag.\r
+                   b_IndexInterruptOccur = 0;\r
+\r
+                       dw_StatusReg=inl(devpriv->s_BoardInfos.\r
+                           ui_Address + 12 + (64 * b_ModulNbr));\r
+\r
+                   *pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 1);\r
+                   }\r
+                else\r
+                   {\r
+                   /****************************/\r
+                   /* No index interrupt occur */\r
+                   /****************************/\r
+\r
+                   *pb_UDStatus = 2;\r
+                   }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");  
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+       /*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ReadFrequencyMeasurement              |\r
+|                              (BYTE_            b_BoardHandle,             |\r
+|                               BYTE_            b_ModulNbr,                |\r
+|                               PBYTE_          pb_Status,                  |\r
+|                               PULONG_        pul_ReadValue)               |\r
++----------------------------------------------------------------------------+\r
+| Task              : Returns the status (pb_Status) and the number of       |\r
+|                    increments in the set time.                            |\r
+|                    See function " i_APCI1710_InitFrequencyMeasurement "   |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle    : Handle of board APCI-1710    |\r
+|                    BYTE_  b_ModulNbr       : Number of the module to be   |\r
+|                                              configured (0 to 3)          |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_   pb_Status     : Returns the frequency        |\r
+|                                              measurement status           |\r
+|                                              0 : Counting cycle not       |\r
+|                                                  started.                 |\r
+|                                              1 : Counting cycle started.  |\r
+|                                              2 : Counting cycle stopped.  |\r
+|                                                  The measurement cycle is |\r
+|                                                  completed.               |\r
+|                    PBYTE_ pb_UDStatus      : 0 : Counter progress in the  |\r
+|                                                   selected mode down       |\r
+|                                               1 : Counter progress in the  |\r
+|                                                   selected mode up         |\r
+|                    PULONG_ pul_ReadValue   : Return the number of         |\r
+|                                              increments in the defined    |\r
+|                                              time base.                   |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: The selected module number is wrong                |\r
+|                     -3: Counter not initialised see function               |\r
+|                        "i_APCI1710_InitCounter"                           |\r
+|                     -4: Frequency measurement logic not initialised.       |\r
+|                        See function "i_APCI1710_InitFrequencyMeasurement" |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT    i_APCI1710_ReadFrequencyMeasurement (comedi_device *dev,\r
+                                            BYTE        b_ModulNbr,\r
+                                            PBYTE       pb_Status,\r
+                                            PBYTE       pb_UDStatus,\r
+                                            PULONG      pul_ReadValue)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       UINT  ui_16BitValue;\r
+       DWORD dw_StatusReg;\r
+       \r
+\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /*******************************/\r
+          /* Test if counter initialised */\r
+          /*******************************/\r
+\r
+          if (devpriv->\r
+              s_ModuleInfo [b_ModulNbr].\r
+              s_SiemensCounterInfo.\r
+              s_InitFlag.\r
+              b_CounterInit == 1)\r
+             {\r
+             /********************************************/\r
+             /* Test if frequency mesurement initialised */\r
+             /********************************************/\r
+\r
+             if (devpriv->\r
+                 s_ModuleInfo [b_ModulNbr].\r
+                 s_SiemensCounterInfo.\r
+                 s_InitFlag.\r
+                 b_FrequencyMeasurementInit == 1)\r
+                {\r
+                /******************/\r
+                /* Test if enable */\r
+                /******************/\r
+\r
+                if (devpriv->\r
+                    s_ModuleInfo [b_ModulNbr].\r
+                    s_SiemensCounterInfo.\r
+                    s_InitFlag.\r
+                    b_FrequencyMeasurementEnable == 1)\r
+                   {\r
+                   /*******************/\r
+                   /* Read the status */\r
+                   /*******************/\r
+\r
+                        dw_StatusReg=inl(devpriv->s_BoardInfos.\r
+                          ui_Address + 32 + (64 * b_ModulNbr));\r
+\r
+                   /**************************/\r
+                   /* Test if frequency stop */\r
+                   /**************************/\r
+\r
+                   if (dw_StatusReg & 1)\r
+                      {\r
+                      *pb_Status   = 2;\r
+                      *pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 3);\r
+\r
+                      /******************/\r
+                      /* Read the value */\r
+                      /******************/\r
+\r
+                          *pul_ReadValue=inl(devpriv->s_BoardInfos.\r
+                             ui_Address + 28 + (64 * b_ModulNbr));\r                                                 
+\r
+                      if (*pb_UDStatus == 0)\r
+                         {\r
+                         /*************************/\r
+                         /* Test the counter mode */\r
+                         /*************************/\r
+\r
+                         if ((devpriv->\r
+                              s_ModuleInfo [b_ModulNbr].\r
+                              s_SiemensCounterInfo.\r
+                              s_ModeRegister.\r
+                              s_ByteModeRegister.\r
+                              b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER)\r
+                            {\r
+                            /****************************************/\r
+                            /* Test if 16-bit counter 1 pulse occur */\r
+                            /****************************************/\r
+\r
+                            if ((*pul_ReadValue & 0xFFFFU) != 0)\r
+                               {\r
+                               ui_16BitValue  = (UINT) *pul_ReadValue & 0xFFFFU;\r
+                               *pul_ReadValue = (*pul_ReadValue & 0xFFFF0000UL) | (0xFFFFU - ui_16BitValue);\r
+                               }\r
+\r
+                            /****************************************/\r
+                            /* Test if 16-bit counter 2 pulse occur */\r
+                            /****************************************/\r
+\r
+                            if ((*pul_ReadValue & 0xFFFF0000UL) != 0)\r
+                               {\r
+                               ui_16BitValue  = (UINT) ((*pul_ReadValue >> 16) & 0xFFFFU);\r
+                               *pul_ReadValue = (*pul_ReadValue & 0xFFFFUL) | ((0xFFFFU - ui_16BitValue) << 16);\r
+                               }\r
+                            }\r
+                         else\r
+                            {\r
+                            if (*pul_ReadValue != 0)\r
+                               {\r
+                               *pul_ReadValue = 0xFFFFFFFFUL - *pul_ReadValue;\r
+                               }\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         if (*pb_UDStatus == 1)\r
+                            {\r
+                            /****************************************/\r
+                            /* Test if 16-bit counter 2 pulse occur */\r
+                            /****************************************/\r
+\r
+                            if ((*pul_ReadValue & 0xFFFF0000UL) != 0)\r
+                               {\r
+                               ui_16BitValue  = (UINT) ((*pul_ReadValue >> 16) & 0xFFFFU);\r
+                               *pul_ReadValue = (*pul_ReadValue & 0xFFFFUL) | ((0xFFFFU - ui_16BitValue) << 16);\r
+                               }\r
+                            }\r
+                         else\r
+                            {\r
+                            if (*pb_UDStatus == 2)\r
+                               {\r
+                               /****************************************/\r
+                               /* Test if 16-bit counter 1 pulse occur */\r
+                               /****************************************/\r
+\r
+                               if ((*pul_ReadValue & 0xFFFFU) != 0)\r
+                                  {\r
+                                  ui_16BitValue  = (UINT) *pul_ReadValue & 0xFFFFU;\r
+                                  *pul_ReadValue = (*pul_ReadValue & 0xFFFF0000UL) | (0xFFFFU - ui_16BitValue);\r
+                                  }\r
+                               }\r
+                            }\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      *pb_Status   = 1;\r
+                      *pb_UDStatus = 0;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   *pb_Status   = 0;\r
+                   *pb_UDStatus = 0;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /***********************************************/\r
+                /* Frequency measurement logic not initialised */\r
+                /***********************************************/\r
+\r               DPRINTK("Frequency measurement logic not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /****************************************/\r
+             /* Counter not initialised see function */\r
+             /* "i_APCI1710_InitCounter"             */\r
+             /****************************************/\r
+\r            DPRINTK("Counter not initialised\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*************************************************/\r
+          /* The selected module number parameter is wrong */\r
+          /*************************************************/\r
+\r         DPRINTK("The selected module number parameter is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
diff --git a/comedi/drivers/addi-data/APCI1710_INCCPT.h b/comedi/drivers/addi-data/APCI1710_INCCPT.h
new file mode 100644 (file)
index 0000000..5f3bb09
--- /dev/null
@@ -0,0 +1,308 @@
+\r
+\r
+
+#define APCI1710_16BIT_COUNTER                         0x10\r
+#define APCI1710_32BIT_COUNTER                         0x0\r
+#define APCI1710_QUADRUPLE_MODE                        0x0\r
+#define APCI1710_DOUBLE_MODE                           0x3\r
+#define APCI1710_SIMPLE_MODE                           0xF\r
+#define APCI1710_DIRECT_MODE                           0x80\r
+#define APCI1710_HYSTERESIS_ON                         0x60\r
+#define APCI1710_HYSTERESIS_OFF                        0x0\r
+#define APCI1710_INCREMENT                             0x60\r
+#define APCI1710_DECREMENT                             0x0\r
+#define APCI1710_LATCH_COUNTER                         0x1\r
+#define APCI1710_CLEAR_COUNTER                         0x0\r
+#define APCI1710_LOW                                   0x0\r
+#define APCI1710_HIGH                                  0x1\r
+\r
+/*********************/\r
+/* Version 0600-0229 */\r
+/*********************/\r
+\r
+#define APCI1710_HIGH_EDGE_CLEAR_COUNTER               0x0\r
+#define APCI1710_HIGH_EDGE_LATCH_COUNTER               0x1\r
+#define APCI1710_LOW_EDGE_CLEAR_COUNTER                0x2\r
+#define APCI1710_LOW_EDGE_LATCH_COUNTER                0x3\r
+#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER     0x4\r
+#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER      0x5\r
+#define APCI1710_SOURCE_0                              0x0\r
+#define APCI1710_SOURCE_1                              0x1\r
+\r
+\r
+\r
+#define APCI1710_30MHZ           30\r
+#define APCI1710_33MHZ           33\r
+#define APCI1710_40MHZ           40\r
+\r
+\r
+#define APCI1710_ENABLE_LATCH_INT              0x80\r
+#define APCI1710_DISABLE_LATCH_INT             (~APCI1710_ENABLE_LATCH_INT)\r
+\r
+#define APCI1710_INDEX_LATCH_COUNTER           0x10\r
+#define APCI1710_INDEX_AUTO_MODE               0x8\r
+#define APCI1710_ENABLE_INDEX                  0x4\r
+#define APCI1710_DISABLE_INDEX                 (~APCI1710_ENABLE_INDEX)\r
+#define APCI1710_ENABLE_LATCH_AND_CLEAR        0x8\r
+#define APCI1710_DISABLE_LATCH_AND_CLEAR       (~APCI1710_ENABLE_LATCH_AND_CLEAR)\r
+#define APCI1710_SET_LOW_INDEX_LEVEL           0x4\r
+#define APCI1710_SET_HIGH_INDEX_LEVEL           (~APCI1710_SET_LOW_INDEX_LEVEL)\r
+#define APCI1710_INVERT_INDEX_RFERENCE         0x2\r
+#define APCI1710_DEFAULT_INDEX_RFERENCE         (~APCI1710_INVERT_INDEX_RFERENCE)\r
+\r
+#define APCI1710_ENABLE_INDEX_INT              0x1\r
+#define APCI1710_DISABLE_INDEX_INT             (~APCI1710_ENABLE_INDEX_INT)\r
+\r
+#define APCI1710_ENABLE_FREQUENCY              0x4\r
+#define APCI1710_DISABLE_FREQUENCY             (~APCI1710_ENABLE_FREQUENCY)\r
+\r
+#define APCI1710_ENABLE_FREQUENCY_INT          0x8\r
+#define APCI1710_DISABLE_FREQUENCY_INT         (~APCI1710_ENABLE_FREQUENCY_INT)\r
+\r
+#define APCI1710_ENABLE_40MHZ_FREQUENCY                0x40\r
+#define APCI1710_DISABLE_40MHZ_FREQUENCY       (~APCI1710_ENABLE_40MHZ_FREQUENCY)\r
+\r
+#define APCI1710_ENABLE_40MHZ_FILTER           0x80\r
+#define APCI1710_DISABLE_40MHZ_FILTER          (~APCI1710_ENABLE_40MHZ_FILTER)\r
+\r
+#define APCI1710_ENABLE_COMPARE_INT            0x2\r
+#define APCI1710_DISABLE_COMPARE_INT           (~APCI1710_ENABLE_COMPARE_INT)\r
+\r
+#define APCI1710_ENABLE_INDEX_ACTION           0x20\r
+#define APCI1710_DISABLE_INDEX_ACTION          (~APCI1710_ENABLE_INDEX_ACTION)\r
+#define APCI1710_REFERENCE_HIGH                0x40\r
+#define APCI1710_REFERENCE_LOW                 (~APCI1710_REFERENCE_HIGH)\r
+\r
+
+   #define APCI1710_TOR_GATE_LOW               0x40\r
+   #define APCI1710_TOR_GATE_HIGH              (~APCI1710_TOR_GATE_LOW)\r
+
+\r
+//     INSN CONFIG \r
+#define        APCI1710_INCCPT_INITCOUNTER                                                     100\r
+#define APCI1710_INCCPT_COUNTERAUTOTEST                                                101\r
+#define APCI1710_INCCPT_INITINDEX                                                      102\r
+#define APCI1710_INCCPT_INITREFERENCE                                          103\r
+#define APCI1710_INCCPT_INITEXTERNALSTROBE                                     104\r
+#define APCI1710_INCCPT_INITCOMPARELOGIC                                       105\r
+#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT                       106\r
+\r
+// INSN READ\r
+#define APCI1710_INCCPT_READLATCHREGISTERSTATUS                                200                                              \r
+#define APCI1710_INCCPT_READLATCHREGISTERVALUE                         201\r
+#define APCI1710_INCCPT_READ16BITCOUNTERVALUE                          202        \r
+#define APCI1710_INCCPT_READ32BITCOUNTERVALUE                          203\r
+#define APCI1710_INCCPT_GETINDEXSTATUS                                         204\r
+#define APCI1710_INCCPT_GETREFERENCESTATUS                                     205\r
+#define APCI1710_INCCPT_GETUASSTATUS                                           206\r
+#define APCI1710_INCCPT_GETCBSTATUS                                                    207\r
+#define APCI1710_INCCPT_GET16BITCBSTATUS                                       208\r
+#define APCI1710_INCCPT_GETUDSTATUS                                                    209\r
+#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS                    210\r
+#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT                       211\r
+#define APCI1710_INCCPT_READINTERRUPT                       212
+\r
+//INSN BITS\r
+#define APCI1710_INCCPT_CLEARCOUNTERVALUE                                      300\r
+#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE                           301\r
+#define APCI1710_INCCPT_SETINPUTFILTER                                         302\r
+#define APCI1710_INCCPT_LATCHCOUNTER                                           303\r
+#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE                     304\r
+#define APCI1710_INCCPT_SETDIGITALCHLON                                                305\r
+#define APCI1710_INCCPT_SETDIGITALCHLOFF                                       306\r
+\r
+// INSN WRITE\r
+#define APCI1710_INCCPT_ENABLELATCHINTERRUPT                           400\r
+#define APCI1710_INCCPT_DISABLELATCHINTERRUPT                          401\r
+#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE                         402\r
+#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE                         403\r
+#define APCI1710_INCCPT_ENABLEINDEX                                                    404     \r
+#define APCI1710_INCCPT_DISABLEINDEX                                           405\r
+#define APCI1710_INCCPT_ENABLECOMPARELOGIC                                     406     \r
+#define APCI1710_INCCPT_DISABLECOMPARELOGIC                                    407\r
+#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT                     408\r
+#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT                    409\r
+\r
+\r
+/************ Main Functions *************/  \r
+INT    i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data);\r
+\r
+INT    i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data);\r
+\r
+INT    i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data);\r
+\r
+INT    i_APCI1710_InsnReadINCCPT(comedi_device *dev,comedi_subdevice *s,\r
+comedi_insn *insn,lsampl_t *data);\r
+\r
+/*********** Supplementary Functions********/\r
+\r
+\r
+// INSN CONFIG\r
+\r
+INT   i_APCI1710_InitCounter (comedi_device *dev,\r
+                               BYTE          b_ModulNbr,\r
+                               BYTE          b_CounterRange,\r
+                               BYTE          b_FirstCounterModus,\r
+                               BYTE          b_FirstCounterOption,\r
+                               BYTE          b_SecondCounterModus,\r
+                               BYTE          b_SecondCounterOption);\r
+\r
+INT  i_APCI1710_CounterAutoTest  (comedi_device *dev,PBYTE   pb_TestStatus);\r
+\r
+INT   i_APCI1710_InitIndex    (comedi_device *dev,\r
+                                BYTE b_ModulNbr,\r
+                                BYTE b_ReferenceAction,\r
+                                BYTE b_IndexOperation,\r
+                                BYTE b_AutoMode,\r
+                                BYTE b_InterruptEnable);\r
+\r
+INT   i_APCI1710_InitReference        (comedi_device *dev,\r
+                                        BYTE b_ModulNbr,\r
+                                        BYTE b_ReferenceLevel);\r
+\r
+INT    i_APCI1710_InitExternalStrobe   (comedi_device *dev,\r
+                                        BYTE b_ModulNbr,\r
+                                        BYTE b_ExternalStrobe,\r
+                                        BYTE b_ExternalStrobeLevel);\r
+\r
+INT   i_APCI1710_InitCompareLogic     (comedi_device *dev,\r
+                                        BYTE   b_ModulNbr,\r
+                                        UINT  ui_CompareValue);\r
+\r
+INT    i_APCI1710_InitFrequencyMeasurement     (comedi_device *dev,\r
+                                                BYTE            b_ModulNbr,\r
+                                                BYTE            b_PCIInputClock,\r
+                                                BYTE            b_TimingUnity,\r
+                                                ULONG           ul_TimingInterval,\r
+                                                PULONG      pul_RealTimingInterval);\r
+\r
+\r
+//INSN BITS\r
+\r
+INT   i_APCI1710_ClearCounterValue    (comedi_device *dev,\r
+                                        BYTE b_ModulNbr);\r
+\r
+INT   i_APCI1710_ClearAllCounterValue (comedi_device *dev);\r
+\r
+INT    i_APCI1710_SetInputFilter       (comedi_device *dev,\r
+                                                                       BYTE b_ModulNbr,\r
+                                    BYTE b_PCIInputClock,\r
+                                                                       BYTE b_Filter);\r
+\r
+INT   i_APCI1710_LatchCounter (comedi_device *dev,\r
+                                BYTE b_ModulNbr,\r
+                                BYTE b_LatchReg);\r
+\r
+INT    i_APCI1710_SetIndexAndReferenceSource   (comedi_device *dev,\r
+                                                BYTE b_ModulNbr,\r
+                                                BYTE b_SourceSelection);\r
+\r
+INT    i_APCI1710_SetDigitalChlOn (comedi_device *dev,\r
+                                   BYTE  b_ModulNbr);\r
+\r
+INT    i_APCI1710_SetDigitalChlOff (comedi_device *dev,\r
+                                    BYTE  b_ModulNbr);\r
+\r
+\r
+// INSN WRITE\r
+INT  i_APCI1710_EnableLatchInterrupt (comedi_device *dev,\r
+                                        BYTE b_ModulNbr);\r
+\r
+\r
+INT   i_APCI1710_DisableLatchInterrupt        (comedi_device *dev,\r
+                                                BYTE b_ModulNbr);\r
+\r
+INT   i_APCI1710_Write16BitCounterValue       (comedi_device *dev,\r
+                                                BYTE  b_ModulNbr,\r
+                                                BYTE  b_SelectedCounter,\r
+                                                UINT  ui_WriteValue);\r
+\r
+INT   i_APCI1710_Write32BitCounterValue       (comedi_device *dev,\r
+                                                BYTE   b_ModulNbr,\r
+                                                ULONG ul_WriteValue);\r
+\r
+INT   i_APCI1710_EnableIndex  (comedi_device *dev,\r
+                                BYTE b_ModulNbr);\r
+\r
+INT  i_APCI1710_DisableIndex (comedi_device *dev,\r
+                                BYTE b_ModulNbr);\r
+\r
+INT   i_APCI1710_EnableCompareLogic   (comedi_device *dev,\r
+                                        BYTE   b_ModulNbr);\r
+\r
+INT   i_APCI1710_DisableCompareLogic  (comedi_device *dev,\r
+                                        BYTE   b_ModulNbr);\r
+\r
+INT    i_APCI1710_EnableFrequencyMeasurement   (comedi_device *dev,\r
+                                                BYTE    b_ModulNbr,\r
+                                                BYTE    b_InterruptEnable);\r
+\r
+INT    i_APCI1710_DisableFrequencyMeasurement  (comedi_device *dev,\r
+                                                BYTE    b_ModulNbr);\r
+\r
+\r
+// INSN READ\r
+\r
+INT   i_APCI1710_ReadLatchRegisterStatus      (comedi_device *dev,\r
+                                                BYTE   b_ModulNbr,\r
+                                                BYTE   b_LatchReg,\r
+                                                PBYTE pb_LatchStatus);\r
+\r
+INT   i_APCI1710_ReadLatchRegisterValue       (comedi_device *dev,\r
+                                                BYTE     b_ModulNbr,\r
+                                                BYTE     b_LatchReg,\r
+                                                PULONG pul_LatchValue);\r
+\r
+INT   i_APCI1710_Read16BitCounterValue        (comedi_device *dev,\r
+                                                BYTE    b_ModulNbr,\r
+                                                BYTE    b_SelectedCounter,\r
+                                                PUINT pui_CounterValue);\r
+\r
+INT   i_APCI1710_Read32BitCounterValue        (comedi_device *dev,\r
+                                                BYTE      b_ModulNbr,\r
+                                                PULONG  pul_CounterValue);\r
+\r
+INT   i_APCI1710_GetIndexStatus      (comedi_device *dev,\r
+                                       BYTE   b_ModulNbr,\r
+                                       PBYTE pb_IndexStatus);\r
+\r
+INT   i_APCI1710_GetReferenceStatus      (comedi_device *dev,\r
+                                           BYTE   b_ModulNbr,\r
+                                           PBYTE  pb_ReferenceStatus);\r
+\r
+INT   i_APCI1710_GetUASStatus (comedi_device *dev,\r
+                                BYTE   b_ModulNbr,\r
+                                PBYTE pb_UASStatus);\r
+\r
+INT   i_APCI1710_GetCBStatus  (comedi_device *dev,\r
+                                BYTE   b_ModulNbr,\r
+                                PBYTE pb_CBStatus);\r
+\r
+INT   i_APCI1710_Get16BitCBStatus      (comedi_device *dev,\r
+                                        BYTE     b_ModulNbr,\r
+                                        PBYTE pb_CBStatusCounter0,\r
+                                        PBYTE pb_CBStatusCounter1);\r
+\r
+INT   i_APCI1710_GetUDStatus  (comedi_device *dev,\r
+                                BYTE   b_ModulNbr,\r
+                                PBYTE pb_UDStatus);\r
+\r
+INT   i_APCI1710_GetInterruptUDLatchedStatus  (comedi_device *dev,\r
+                                                BYTE   b_ModulNbr,\r
+                                                PBYTE pb_UDStatus);\r
+\r
+INT    i_APCI1710_ReadFrequencyMeasurement (comedi_device *dev,\r
+                                            BYTE        b_ModulNbr,\r
+                                            PBYTE       pb_Status,\r
+                                            PBYTE       pb_UDStatus,\r
+                                            PULONG      pul_ReadValue);\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
new file mode 100644 (file)
index 0000000..bd27ada
--- /dev/null
@@ -0,0 +1,760 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : INP_CPT.C       |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 27.08.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 pulse encoder module                        |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  |          |           |                                                |\r
+  |----------|-----------|------------------------------------------------|\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+#include "APCI1710_Inp_cpt.h"\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitPulseEncoder                      |\r
+|                               (BYTE_          b_BoardHandle,               |\r
+|                                BYTE_          b_ModulNbr,                  |\r
+|                                BYTE_          b_PulseEncoderNbr,           |\r
+|                                BYTE_          b_InputLevelSelection,       |\r
+|                                BYTE_          b_TriggerOutputAction,       |\r
+|                                ULONG_        ul_StartValue)                |\r
++----------------------------------------------------------------------------+\r
+| Task              : Configure the pulse encoder operating mode selected via|\r
+|                     b_ModulNbr and b_PulseEncoderNbr. The pulse encoder    |\r
+|                     after each pulse decrement the counter value from 1.   |\r
+|                                                                            |\r
+|                     You must calling this function be for you call any     |\r
+|                     other function witch access of pulse encoders.         |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|\r
+|                     BYTE_ b_ModulNbr            : Module number to         |\r
+|                                                   configure (0 to 3)       |\r
+|                     BYTE_ b_PulseEncoderNbr     : Pulse encoder selection  |\r
+|                                                   (0 to 3)                 |\r
+|                     BYTE_ b_InputLevelSelection : Input level selection    |\r
+|                                                   (0 or 1)                 |\r
+|                                                       0 : Set pulse encoder|\r
+|                                                           count the the low|\r
+|                                                           level pulse.     |\r
+|                                                       1 : Set pulse encoder|\r
+|                                                           count the the    |\r
+|                                                           high level pulse.|\r
+|                     BYTE_ b_TriggerOutputAction : Digital TRIGGER output   |\r
+|                                                   action                   |\r
+|                                                       0 : No action        |\r
+|                                                       1 : Set the trigger  |\r
+|                                                           output to "1"    |\r
+|                                                           (high) after the |\r
+|                                                           passage from 1 to|\r
+|                                                           0 from pulse     |\r
+|                                                           encoder.         |\r
+|                                                       2 : Set the trigger  |\r
+|                                                           output to "0"    |\r
+|                                                           (low) after the  |\r
+|                                                           passage from 1 to|\r
+|                                                           0 from pulse     |\r
+|                                                           encoder          |\r
+|                     ULONG_ ul_StartValue        : Pulse encoder start value|\r
+|                                                   (1 to 4294967295) \r
+       b_ModulNbr                              =(BYTE) CR_AREF(insn->chanspec);\r
+       b_PulseEncoderNbr               =(BYTE) data[0];\r
+       b_InputLevelSelection   =(BYTE) data[1];\r
+       b_TriggerOutputAction   =(BYTE) data[2];\r
+       ul_StartValue                   =(ULONG) data[3];\r
+       |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module is not a pulse encoder module            |\r
+|                    -3: Pulse encoder selection is wrong                    |\r
+|                    -4: Input level selection is wrong                      |\r
+|                    -5: Digital TRIGGER output action selection is wrong    |\r
+|                    -6: Pulse encoder start value is wrong                  |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT  i_APCI1710_InsnConfigInitPulseEncoder(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_IntRegister;\r
+       \r
+       BYTE   b_ModulNbr;\r
+       BYTE   b_PulseEncoderNbr;\r
+       BYTE   b_InputLevelSelection;\r
+       BYTE   b_TriggerOutputAction;\r
+       ULONG  ul_StartValue;\r
+    \r
+       b_ModulNbr                              =(BYTE)  CR_AREF(insn->chanspec);\r
+       b_PulseEncoderNbr               =(BYTE)  data[0];\r
+       b_InputLevelSelection   =(BYTE)  data[1];\r
+       b_TriggerOutputAction   =(BYTE)  data[2];\r
+       ul_StartValue                   =(ULONG) data[3];\r
+\r       i_ReturnValue           =insn->n;
+       \r
+\r
+       /***********************************/\r
+       /* Test the selected module number */\r
+       /***********************************/\r
+\r
+       if (b_ModulNbr >= 0 && b_ModulNbr <= 3)\r
+          {\r
+          /*************************/\r
+          /* Test if pulse encoder */\r
+          /*************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & APCI1710_PULSE_ENCODER) == APCI1710_PULSE_ENCODER)\r
+             {\r
+             /******************************************/\r
+             /* Test the selected pulse encoder number */\r
+             /******************************************/\r
+\r
+             if (b_PulseEncoderNbr >= 0 && b_PulseEncoderNbr <= 3)\r
+                {\r
+                /************************/\r
+                /* Test the input level */\r
+                /************************/\r
+\r
+                if ((b_InputLevelSelection == 0) || (b_InputLevelSelection == 1))\r
+                   {\r
+                   /*******************************************/\r
+                   /* Test the ouput TRIGGER action selection */\r
+                   /*******************************************/\r
+\r
+                   if ((b_TriggerOutputAction >= 0 && b_TriggerOutputAction <= 2) || (b_PulseEncoderNbr > 0))\r
+                      {\r
+                      if (ul_StartValue > 1)\r
+                         {\r
+                        \r
+                                dw_IntRegister= inl(devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+                         /***********************/\r
+                         /* Set the start value */\r
+                         /***********************/\r
+\r
+\r
+                                outl(ul_StartValue,devpriv->s_BoardInfos.ui_Address + (b_PulseEncoderNbr * 4) + (64 * b_ModulNbr));\r
+\r
+                         /***********************/\r
+                         /* Set the input level */\r
+                         /***********************/\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_PulseEncoderModuleInfo.\r
+                         dw_SetRegister = (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                           s_PulseEncoderModuleInfo.\r
+                                           dw_SetRegister & (0xFFFFFFFFUL - (1UL << (8 + b_PulseEncoderNbr)))) |\r
+                                          ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr));\r
+\r
+                         /*******************************/\r
+                         /* Test if output trigger used */\r
+                         /*******************************/\r
+\r
+                         if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1))\r
+                            {\r
+                            /****************************/\r
+                            /* Enable the output action */\r
+                            /****************************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_PulseEncoderModuleInfo.\r
+                            dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                             s_PulseEncoderModuleInfo.\r
+                                             dw_SetRegister |\r
+                                             (1UL << (4 + b_PulseEncoderNbr));\r
+\r
+                            /*********************************/\r
+                            /* Set the output TRIGGER action */\r
+                            /*********************************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_PulseEncoderModuleInfo.\r
+                            dw_SetRegister = (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                              s_PulseEncoderModuleInfo.\r
+                                              dw_SetRegister & (0xFFFFFFFFUL - (1UL << (12 + b_PulseEncoderNbr)))) |\r
+                                             ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr));\r
+                            }\r
+                         else\r
+                            {\r
+                            /*****************************/\r
+                            /* Disable the output action */\r
+                            /*****************************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_PulseEncoderModuleInfo.\r
+                            dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                             s_PulseEncoderModuleInfo.\r
+                                             dw_SetRegister & (0xFFFFFFFFUL - (1UL << (4 + b_PulseEncoderNbr)));\r
+                            }\r
+\r
+                         /*************************/\r
+                         /* Set the configuration */\r
+                         /*************************/\r
+\r
+                         \r
+                         outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                 s_PulseEncoderModuleInfo.dw_SetRegister,devpriv->s_BoardInfos.\r
+                                 ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_PulseEncoderModuleInfo.\r
+                         s_PulseEncoderInfo [b_PulseEncoderNbr].\r
+                         b_PulseEncoderInit = 1;\r
+                         }\r
+                      else\r
+                         {\r
+                         /**************************************/\r
+                         /* Pulse encoder start value is wrong */\r
+                         /**************************************/\r
+\r                        DPRINTK("Pulse encoder start value is wrong\n");
+                         i_ReturnValue = -6;\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /****************************************************/\r
+                      /* Digital TRIGGER output action selection is wrong */\r
+                      /****************************************************/\r
+\r                         DPRINTK("Digital TRIGGER output action selection is wrong\n");       
+                      i_ReturnValue = -5;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /**********************************/\r
+                   /* Input level selection is wrong */\r
+                   /**********************************/\r
+\r                  DPRINTK("Input level selection is wrong\n");
+                   i_ReturnValue = -4;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /************************************/\r
+                /* Pulse encoder selection is wrong */\r
+                /************************************/\r
+\r               DPRINTK("Pulse encoder selection is wrong\n");
+                i_ReturnValue = -3;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /********************************************/\r
+             /* The module is not a pulse encoder module */\r
+             /********************************************/\r
+\r            DPRINTK("The module is not a pulse encoder module\n");    
+             i_ReturnValue = -2;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /********************************************/\r
+          /* The module is not a pulse encoder module */\r
+          /********************************************/\r
+\r         DPRINTK("The module is not a pulse encoder module\n");       
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_EnablePulseEncoder                    |\r
+|                                       (BYTE_  b_BoardHandle,               |\r
+|                                        BYTE_  b_ModulNbr,                  |\r
+|                                        BYTE_  b_PulseEncoderNbr,           |\r
+|                                        BYTE_  b_CycleSelection,            |\r
+|                                        BYTE_  b_InterruptHandling)         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enableor disable  the selected pulse encoder (b_PulseEncoderNbr)  |\r
+|                     from selected module (b_ModulNbr). Each input pulse    |\r
+|                     decrement the pulse encoder counter value from 1.      |\r
+|                     If you enabled the interrupt (b_InterruptHandling), a  |\r
+|                     interrupt is generated when the pulse encoder has run  |\r
+|                     down.                                                  |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_   b_BoardHandle       : Handle of board APCI-1710|\r
+|                     BYTE_   b_ModulNbr          : Module number to         |\r
+|                                                   configure (0 to 3)       |\r
+|                     BYTE_   b_PulseEncoderNbr   : Pulse encoder selection  |\r
+|                                                   (0 to 3)                 |\r
+|                     BYTE_   b_CycleSelection    : APCI1710_CONTINUOUS:     |\r
+|                                                       Each time the        |\r
+|                                                       counting value is set|\r
+|                                                       on "0", the pulse    |\r
+|                                                       encoder load the     |\r
+|                                                       start value after    |\r
+|                                                       the next pulse.      |\r
+|                                                   APCI1710_SINGLE:         |\r
+|                                                       If the counter is set|\r
+|                                                       on "0", the pulse    |\r
+|                                                       encoder is stopped.  |\r
+|                     BYTE_   b_InterruptHandling : Interrupts can be        |\r
+|                                                   generated, when the pulse|\r
+|                                                   encoder has run down.    |\r
+|                                                   With this parameter the  |\r
+|                                                   user decides if          |\r
+|                                                   interrupts are used or   |\r
+|                                                   not.                     |\r
+|                                                     APCI1710_ENABLE:       |\r
+|                                                     Interrupts are enabled |\r
+|                                                     APCI1710_DISABLE:      |\r
+|                                                     Interrupts are disabled\r
+\r
+       b_ModulNbr                      =(BYTE) CR_AREF(insn->chanspec);\r
+       b_Action                        =(BYTE) data[0];\r
+       b_PulseEncoderNbr       =(BYTE) data[1];\r
+       b_CycleSelection        =(BYTE) data[2];\r
+       b_InterruptHandling     =(BYTE) data[3];|\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection is wrong                          |\r
+|                     -3: Pulse encoder selection is wrong                   |\r
+|                     -4: Pulse encoder not initialised.                     |\r
+|                         See function "i_APCI1710_InitPulseEncoder"         |\r
+|                     -5: Cycle selection mode is wrong                      |\r
+|                     -6: Interrupt handling mode is wrong                   |\r
+|                     -7: Interrupt routine not installed.                   |\r
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+
+ INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       BYTE  b_ModulNbr;\r
+       BYTE  b_PulseEncoderNbr ;\r
+       BYTE  b_CycleSelection  ;\r
+       BYTE  b_InterruptHandling;\r
+       BYTE  b_Action;\r
+\r
+       i_ReturnValue           =insn->n;\r
+       b_ModulNbr                      =(BYTE) CR_AREF(insn->chanspec);\r
+       b_Action                        =(BYTE) data[0];\r
+       b_PulseEncoderNbr       =(BYTE) data[1];\r
+       b_CycleSelection        =(BYTE) data[2];\r
+       b_InterruptHandling     =(BYTE) data[3];\r
+\r
+\r       
+       /***********************************/\r
+       /* Test the selected module number */\r
+       /***********************************/\r
+\r
+       if (b_ModulNbr >= 0 && b_ModulNbr <= 3)\r
+          {\r
+          /******************************************/\r
+          /* Test the selected pulse encoder number */\r
+          /******************************************/\r
+\r
+          if (b_PulseEncoderNbr >= 0 && b_PulseEncoderNbr <= 3)\r
+             {\r
+             /*************************************/\r
+             /* Test if pulse encoder initialised */\r
+             /*************************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_PulseEncoderModuleInfo.\r
+                 s_PulseEncoderInfo [b_PulseEncoderNbr].\r
+                 b_PulseEncoderInit == 1)\r
+                {\r
+                       switch(b_Action)\r
+                       {\r
+\r
+                       case APCI1710_ENABLE:\r
+                /****************************/\r
+                /* Test the cycle selection */\r
+                /****************************/\r
+\r
+                if (b_CycleSelection == APCI1710_CONTINUOUS || b_CycleSelection == APCI1710_SINGLE)\r
+                   {\r
+                   /*******************************/\r
+                   /* Test the interrupt handling */\r
+                   /*******************************/\r
+\r
+                   if (b_InterruptHandling == APCI1710_ENABLE || b_InterruptHandling == APCI1710_DISABLE)\r
+                      {\r
+                      /******************************/\r
+                      /* Test if interrupt not used */\r
+                      /******************************/\r
+\r
+                      if (b_InterruptHandling == APCI1710_DISABLE)\r
+                         {\r
+                         /*************************/\r
+                         /* Disable the interrupt */\r
+                         /*************************/\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_PulseEncoderModuleInfo.\r
+                         dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                          s_PulseEncoderModuleInfo.\r
+                                          dw_SetRegister & (0xFFFFFFFFUL - (1UL << b_PulseEncoderNbr));\r
+                         }\r
+                      else\r
+                         {\r
+                                               \r
+                            /************************/\r
+                            /* Enable the interrupt */\r
+                            /************************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_PulseEncoderModuleInfo.\r
+                            dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                             s_PulseEncoderModuleInfo.\r
+                                             dw_SetRegister | (1UL << b_PulseEncoderNbr);\r
+                               devpriv->tsk_Current=current; // Save the current process task structure
+\r
+                          
+                         }\r
+\r
+                      if (i_ReturnValue>=0)\r
+                         {\r
+                         /***********************************/\r
+                         /* Enable or disable the interrupt */\r
+                         /***********************************/\r
+\r
+                         
+                               outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                 s_PulseEncoderModuleInfo.\r
+                                 dw_SetRegister,devpriv->s_BoardInfos.\r
+                                 ui_Address + 20 + (64 * b_ModulNbr));\r
+\r
+                         /****************************/\r
+                         /* Enable the pulse encoder */\r
+                         /****************************/\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_PulseEncoderModuleInfo.\r
+                         dw_ControlRegister = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                              s_PulseEncoderModuleInfo.\r
+                                              dw_ControlRegister | (1UL << b_PulseEncoderNbr);\r
+\r
+                         /**********************/\r
+                         /* Set the cycle mode */\r
+                         /**********************/\r
+\r
+                         devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_PulseEncoderModuleInfo.\r
+                         dw_ControlRegister = (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                               s_PulseEncoderModuleInfo.\r
+                                               dw_ControlRegister & (0xFFFFFFFFUL - (1 << (b_PulseEncoderNbr + 4)))) |\r
+                                               ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr));\r
+\r
+                         /****************************/\r
+                         /* Enable the pulse encoder */\r
+                         /****************************/\r
+\r
+                         
+                         outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                 s_PulseEncoderModuleInfo.\r
+                                 dw_ControlRegister,devpriv->s_BoardInfos.\r
+                                 ui_Address + 16 + (64 * b_ModulNbr));\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /************************************/\r
+                      /* Interrupt handling mode is wrong */\r
+                      /************************************/\r
+\r                         DPRINTK("Interrupt handling mode is wrong\n");
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /*********************************/\r
+                   /* Cycle selection mode is wrong */\r
+                   /*********************************/\r
+\r                      DPRINTK("Cycle selection mode is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                break;\r
+\r
+                case APCI1710_DISABLE:\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_PulseEncoderModuleInfo.\r
+                dw_ControlRegister = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                     s_PulseEncoderModuleInfo.\r
+                                     dw_ControlRegister & (0xFFFFFFFFUL - (1UL << b_PulseEncoderNbr));\r
+\r
+                /*****************************/\r
+                /* Disable the pulse encoder */\r
+                /*****************************/\r
+\r
+               \r
+                outl(devpriv->s_ModuleInfo [b_ModulNbr].\r
+                        s_PulseEncoderModuleInfo.\r
+                        dw_ControlRegister,devpriv->s_BoardInfos.\r
+                        ui_Address + 16 + (64 * b_ModulNbr));\r
+\r
+                       break;\r
+                }// switch End\r
+\r
+                }\r
+             else\r
+                {\r
+                /*********************************/\r
+                /* Pulse encoder not initialised */\r
+                /*********************************/\r
+\r               DPRINTK("Pulse encoder not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /************************************/\r
+             /* Pulse encoder selection is wrong */\r
+             /************************************/\r
+\r            DPRINTK("Pulse encoder selection is wrong\n");    
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*****************************/\r
+          /* Module selection is wrong */\r
+          /*****************************/\r
+\r         DPRINTK("Module selection is wrong\n");      
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ReadPulseEncoderStatus                |\r
+|                                       (BYTE_  b_BoardHandle,               |\r
+|                                        BYTE_  b_ModulNbr,                  |\r
+|                                        BYTE_  b_PulseEncoderNbr,           |\r
+|                                        PBYTE_ pb_Status)                   |\r
++----------------------------------------------------------------------------+\r
+| Task    APCI1710_PULSEENCODER_READ          : Reads the pulse encoder status \r
+                                                                                       and valuefrom selected pulse     |\r
+|                     encoder (b_PulseEncoderNbr) from selected module       |\r
+|                     (b_ModulNbr).                                          |\r
++----------------------------------------------------------------------------+\r
+       BYTE   b_Type; data[0]\r
+   APCI1710_PULSEENCODER_WRITE                         \r
+ Writes a 32-bit value (ul_WriteValue) into the selected|\r
+|                     pulse encoder (b_PulseEncoderNbr) from selected module |\r
+|                     (b_ModulNbr). This operation set the new start pulse   |\r
+|                     encoder value.\r
+ APCI1710_PULSEENCODER_READ\r
+| Input Parameters  : BYTE_   b_BoardHandle       : Handle of board APCI-1710|\r
+|            CRAREF()         BYTE_   b_ModulNbr          : Module number to         |\r
+|                                                   configure (0 to 3)       |\r
+|              data[1]       BYTE_   b_PulseEncoderNbr   : Pulse encoder selection  |\r
+|                                                   (0 to 3)   \r
+   APCI1710_PULSEENCODER_WRITE  \r
+                               data[2]         ULONG_ ul_WriteValue        : 32-bit value to be       |\r
+|                                                   written             |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_ pb_Status            : Pulse encoder status.    |\r
+|                                                       0 : No overflow occur|\r
+|                                                       1 : Overflow occur \r
+                                               PULONG_ pul_ReadValue       : Pulse encoder value      |  |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection is wrong                          |\r
+|                     -3: Pulse encoder selection is wrong                   |\r
+|                     -4: Pulse encoder not initialised.                     |\r
+|                         See function "i_APCI1710_InitPulseEncoder"         |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+/*_INT_   i_APCI1710_ReadPulseEncoderStatus       (BYTE_   b_BoardHandle,\r
+                                                BYTE_   b_ModulNbr,\r
+                                                BYTE_   b_PulseEncoderNbr,\r
+\r
+                                                PBYTE_ pb_Status)\r
+                                                */\r
+INT   i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusRegister;\r
+       BYTE   b_ModulNbr;\r
+       BYTE   b_PulseEncoderNbr;\r
+       PBYTE  pb_Status;\r
+       BYTE   b_Type;\r
+       PULONG pul_ReadValue;\r
+       ULONG ul_WriteValue ; \r
+                             \r
+       i_ReturnValue=insn->n;
+       b_ModulNbr              =(BYTE) CR_AREF(insn->chanspec);
+       b_Type                  =(BYTE)   data[0] ;\r
+       b_PulseEncoderNbr=(BYTE) data[1];
+       pb_Status               =(PBYTE) &data[0];\r
+       pul_ReadValue   =(PULONG) &data[1];\r
+    \r
+       /***********************************/\r
+       /* Test the selected module number */\r
+       /***********************************/\r
+\r
+       if (b_ModulNbr >= 0 && b_ModulNbr <= 3)\r
+          {\r
+          /******************************************/\r
+          /* Test the selected pulse encoder number */\r
+          /******************************************/\r
+\r
+          if (b_PulseEncoderNbr >= 0 && b_PulseEncoderNbr <= 3)\r
+             {\r
+             /*************************************/\r
+             /* Test if pulse encoder initialised */\r
+             /*************************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_PulseEncoderModuleInfo.\r
+                 s_PulseEncoderInfo [b_PulseEncoderNbr].\r
+                 b_PulseEncoderInit == 1)\r
+                {\r
+\r
+               switch(b_Type)\r
+               {\r
+               case APCI1710_PULSEENCODER_READ:\r
+                /****************************/\r
+                /* Read the status register */\r
+                /****************************/\r
+\r
+               
+                       dw_StatusRegister=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 16 + (64 * b_ModulNbr));\r
+\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_PulseEncoderModuleInfo.\r
+                dw_StatusRegister = devpriv->\r
+                                    s_ModuleInfo [b_ModulNbr].\r
+                                    s_PulseEncoderModuleInfo.\r
+                                    dw_StatusRegister | dw_StatusRegister;\r
+\r
+                *pb_Status = (BYTE) (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                             s_PulseEncoderModuleInfo.\r
+                             dw_StatusRegister >> (1 + b_PulseEncoderNbr)) & 1;\r
+\r
+                devpriv->s_ModuleInfo [b_ModulNbr].\r
+                s_PulseEncoderModuleInfo.\r
+                dw_StatusRegister = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                    s_PulseEncoderModuleInfo.\r
+                                    dw_StatusRegister & (0xFFFFFFFFUL - (1 << (1 + b_PulseEncoderNbr)));\r
+\r
+                /******************/\r
+                /* Read the value */\r
+                /******************/\r
+                
+\r
+               *pul_ReadValue=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + (4 * b_PulseEncoderNbr) + (64 * b_ModulNbr));\r
+                break;\r
+\r
+               case APCI1710_PULSEENCODER_WRITE:\r
+                       ul_WriteValue = (ULONG) data[2];\r
+                       /*******************/\r
+                       /* Write the value */\r
+                       /*******************/\r
+\r
+                       
+                       outl(ul_WriteValue,devpriv->s_BoardInfos.\r
+                        ui_Address + (4 * b_PulseEncoderNbr) + (64 * b_ModulNbr));\r
+\r
+               }//end of switch\r
+                }\r
+             else\r
+                {\r
+                /*********************************/\r
+                /* Pulse encoder not initialised */\r
+                /*********************************/\r
+\r               DPRINTK("Pulse encoder not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /************************************/\r
+             /* Pulse encoder selection is wrong */\r
+             /************************************/\r
+\r            DPRINTK("Pulse encoder selection is wrong\n");            
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /*****************************/\r
+          /* Module selection is wrong */\r
+          /*****************************/\r
+\r         DPRINTK("Module selection is wrong\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+
+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;
+
+
+}
+
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
new file mode 100644 (file)
index 0000000..7265a72
--- /dev/null
@@ -0,0 +1,38 @@
+\r\r
+\r
+\r
+   #define APCI1710_SINGLE     0\r
+   #define APCI1710_CONTINUOUS 1\r
+
+\r
+#define APCI1710_PULSEENCODER_READ             0   \r
+#define APCI1710_PULSEENCODER_WRITE            1\r
+\r
+\r
+INT  i_APCI1710_InsnConfigInitPulseEncoder(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+\r
+\r
+\r
+INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       READ PULSE ENCODER FUNCTIONS                         |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data);
+
+/*\r
++----------------------------------------------------------------------------+\r
+|                       WRITE PULSE ENCODER FUNCTIONS                        |\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+ INT   i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);
+
+
diff --git a/comedi/drivers/addi-data/APCI1710_Pwm.c b/comedi/drivers/addi-data/APCI1710_Pwm.c
new file mode 100644 (file)
index 0000000..588dc35
--- /dev/null
@@ -0,0 +1,2517 @@
+
+
+
+
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : PWM.C           |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 22.01.99             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 Wulse wide modulation module                |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +-----------------------------------------------------------------------+\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+#include "APCI1710_Pwm.h"\r
+\r
+
+
+/*
++----------------------------------------------------------------------------+
+| 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;
+       ULONG ul_HighTimerValue;
+       DWORD dw_Command;
+       double d_RealLowTiming;
+       double d_RealHighTiming;
+       
+
+
+       /**************************/
+       /* 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 >= 0 && 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 >= 0) && (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 */
+                               /************************************/
+
+                               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;
+                                  }
+
+                               /****************************/
+                               /* 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 >= 0 && 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);
+       }
+\r
+\r
+\r
+
+
+/*
++----------------------------------------------------------------------------+
+| 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 >= 0 && 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 >= 0 && b_StartLevel <= 1)
+                      {
+                      /**********************/
+                      /* Test the stop mode */
+                      /**********************/
+
+                      if (b_StopMode >= 0 && b_StopMode <= 1)
+                         {
+                         /***********************/
+                         /* Test the stop level */
+                         /***********************/
+
+                         if (b_StopLevel >= 0 && b_StopLevel <= 2)
+                            {
+                            /*****************************/
+                            /* Test the extern gate mode */
+                            /*****************************/
+
+                            if (b_ExternGate >= 0 && 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 >= 0 && 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;
+       ULONG ul_HighTimerValue;
+       ULONG ul_RealLowTiming;
+       ULONG ul_RealHighTiming;
+       DWORD dw_Status;
+       DWORD dw_Command;
+       double d_RealLowTiming;
+       double d_RealHighTiming;
+       
+
+
+       /**************************/
+       /* 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 >= 0 && 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 >= 0) && (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 */
+                            /************************************/
+
+                            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;
+                               }
+                            /************************/
+                            /* 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);
+       }
+
+
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetPWMStatus                          |\r
+|                               (BYTE_    b_BoardHandle,                     |\r
+|                                BYTE_    b_ModulNbr,                        |\r
+|                                BYTE_    b_PWM,                             |\r
+|                                PBYTE_  pb_PWMOutputStatus,                 |\r
+|                                PBYTE_  pb_ExternGateStatus)                |\r
++----------------------------------------------------------------------------+\r
+| Task              : Return the status from selected PWM (b_PWM) from       |\r
+|                     selected module (b_ModulNbr).                          |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_  b_BoardHandle : Handle of board APCI-1710       |\r
+|                     BYTE_  b_PWM         : Selected PWM (0 or 1)           |\r
+|                     BYTE_  b_ModulNbr    : Selected module number (0 to 3)\r
+       b_ModulNbr                      =(BYTE)  CR_AREF(insn->chanspec);\r
+       b_PWM                           =(BYTE)  data[0];\r
+       \r
+ |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_  pb_PWMOutputStatus  : Return the PWM output    |\r
+|                                                   level status.            |\r
+|                                                    0 : The PWM output level|\r
+|                                                        is low.             |\r
+|                                                    1 : The PWM output level|\r
+|                                                        is high.            |\r
+|                     PBYTE_  pb_ExternGateStatus : Return the extern gate   |\r
+|                                                   level status.            |\r
+|                                                    0 : The extern gate is  |\r
+|                                                        low.                |\r
+|                                                    1 : The extern gate is  |\r
+|                                                        high.  \r
+    pb_PWMOutputStatus =(PBYTE) data[0];\r
+       pb_ExternGateStatus =(PBYTE) data[1];             |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a PWM module                     |\r
+|                     -4: PWM selection is wrong                             |\r
+|                     -5: PWM not initialised see function                   |\r
+|                         "i_APCI1710_InitPWM"                               |\r
+|                     -6: PWM not enabled see function "i_APCI1710_EnablePWM"|\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT i_APCI1710_InsnReadGetPWMStatus(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD  dw_Status;\r
+\r
+       BYTE    b_ModulNbr;\r
+       BYTE    b_PWM;\r
+       PBYTE   pb_PWMOutputStatus;\r
+       PBYTE   pb_ExternGateStatus;\r
+       \r
+       i_ReturnValue           = insn->n;\r
+       b_ModulNbr                      =(BYTE)  CR_AREF(insn->chanspec);\r
+       b_PWM                           =(BYTE)  CR_CHAN(insn->chanspec);\r
+       pb_PWMOutputStatus      =(PBYTE) &data[0];\r
+       pb_ExternGateStatus =(PBYTE) &data[1];\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***************/\r
+          /* Test if PWM */\r
+          /***************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_PWM)\r
+             {\r
+             /**************************/\r
+             /* Test the PWM selection */\r
+             /**************************/\r
+\r
+             if (b_PWM >= 0 && b_PWM <= 1)\r
+                {\r
+                /***************************/\r
+                /* Test if PWM initialised */\r
+                /***************************/\r
+\r
+                dw_Status=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr));\r
+\r
+                if (dw_Status & 0x10)\r
+                   {\r
+                   /***********************/\r
+                   /* Test if PWM enabled */\r
+                   /***********************/\r
+\r
+                   if (dw_Status & 0x1)\r
+                      {\r
+                      *pb_PWMOutputStatus  = (BYTE) ((dw_Status >> 7) & 1);\r
+                      *pb_ExternGateStatus = (BYTE) ((dw_Status >> 6) & 1);\r
+                      } // if (dw_Status & 0x1)\r
+                   else\r
+                      {\r
+                      /*******************/\r
+                      /* PWM not enabled */\r
+                      /*******************/\r
+\r                      DPRINTK("PWM not enabled \n");
+                      i_ReturnValue = -6;\r
+                      } // if (dw_Status & 0x1)\r
+                   } // if (dw_Status & 0x10)\r
+                else\r
+                   {\r
+                   /***********************/\r
+                   /* PWM not initialised */\r
+                   /***********************/\r
+\r                      DPRINTK("PWM not initialised\n");
+                   i_ReturnValue = -5;\r
+                   } // if (dw_Status & 0x10)\r
+                } // if (b_PWM >= 0 && b_PWM <= 1)\r
+             else\r
+                {\r
+                /******************************/\r
+                /* Tor PWM selection is wrong */\r
+                /******************************/\r
+\r               DPRINTK("Tor PWM selection is wrong\n");
+                i_ReturnValue = -4;\r
+                } // if (b_PWM >= 0 && b_PWM <= 1)\r
+             }\r
+          else\r
+             {\r
+             /**********************************/\r
+             /* The module is not a PWM module */\r
+             /**********************************/\r
+\r             DPRINTK("The module is not a PWM module\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+
+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/comedi/drivers/addi-data/APCI1710_Pwm.h b/comedi/drivers/addi-data/APCI1710_Pwm.h
new file mode 100644 (file)
index 0000000..f6e265b
--- /dev/null
@@ -0,0 +1,78 @@
+\r
+\r
+
+\r
+
+   #define APCI1710_30MHZ           30\r
+   #define APCI1710_33MHZ           33\r
+   #define APCI1710_40MHZ           40\r
+
+\r
+#define APCI1710_PWM_INIT                      0\r
+#define APCI1710_PWM_GETINITDATA       1\r
+\r
+#define APCI1710_PWM_DISABLE        0\r
+#define APCI1710_PWM_ENABLE                    1\r
+#define APCI1710_PWM_NEWTIMING      2 \r
+
+
+\r
+
+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);
+\r
+INT i_APCI1710_InsnReadGetPWMStatus(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+
+INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data);
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Ssi.c b/comedi/drivers/addi-data/APCI1710_Ssi.c
new file mode 100644 (file)
index 0000000..99282f7
--- /dev/null
@@ -0,0 +1,766 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : SSI.C           |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 14.01.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 SSI counter module                          |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  | 13/05/98 | S. Weber  | SSI digital input / output implementation      |\r
+  |----------|-----------|------------------------------------------------|\r
+  | 22/03/00 | C.Guinot  | 0100/0226 -> 0200/0227                         |\r
+  |          |           | Änderung in InitSSI Funktion                   |\r
+  |          |           | b_SSIProfile >= 2 anstatt b_SSIProfile > 2     |\r
+  |          |           |                                                |\r
+  +-----------------------------------------------------------------------+\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+#include "APCI1710_Ssi.h"\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitSSI                               |\r
+|                               (BYTE_    b_BoardHandle,                     |\r
+|                                BYTE_    b_ModulNbr,                        |\r
+|                                BYTE_    b_SSIProfile,                      |\r
+|                                BYTE_    b_PositionTurnLength,              |\r
+|                                BYTE_    b_TurnCptLength,                   |\r
+|                                BYTE_    b_PCIInputClock,                   |\r
+|                                ULONG_  ul_SSIOutputClock,                  |\r
+|                                BYTE_    b_SSICountingMode)                 |\r
++----------------------------------------------------------------------------+\r
+| Task              : Configure the SSI operating mode from selected module  |\r
+|                     (b_ModulNbr). You must calling this function be for you|\r
+|                     call any other function witch access of SSI.           |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|\r
+|                     BYTE_ b_ModulNbr            : Module number to         |\r
+|                                                   configure (0 to 3)       |\r
+|                     BYTE_  b_SSIProfile         : Selection from SSI       |\r
+|                                                   profile length (2 to 32).|\r
+|                     BYTE_  b_PositionTurnLength : Selection from SSI       |\r
+|                                                   position data length     |\r
+|                                                   (1 to 31).               |\r
+|                     BYTE_  b_TurnCptLength      : Selection from SSI turn  |\r
+|                                                   counter data length      |\r
+|                                                   (1 to 31).               |\r
+|                     BYTE   b_PCIInputClock      : Selection from PCI bus   |\r
+|                                                   clock                    |\r
+|                                                 - APCI1710_30MHZ :         |\r
+|                                                   The PC have a PCI bus    |\r
+|                                                   clock from 30 MHz        |\r
+|                                                 - APCI1710_33MHZ :         |\r
+|                                                   The PC have a PCI bus    |\r
+|                                                   clock from 33 MHz        |\r
+|                     ULONG_ ul_SSIOutputClock    : Selection from SSI output|\r
+|                                                   clock.                   |\r
+|                                                   From  229 to 5 000 000 Hz|\r
+|                                                   for 30 MHz selection.    |\r
+|                                                   From  252 to 5 000 000 Hz|\r
+|                                                   for 33 MHz selection.    |\r
+|                     BYTE   b_SSICountingMode    : SSI counting mode        |\r
+|                                                   selection                |\r
+|                                                 - APCI1710_BINARY_MODE :   |\r
+|                                                    Binary counting mode.   |\r
+|                                                 - APCI1710_GRAY_MODE :     |\r
+|                                                    Gray counting mode.\r
+\r
+       b_ModulNbr                      = CR_AREF(insn->chanspec);\r
+       b_SSIProfile            = (BYTE) data[0];  \r
+       b_PositionTurnLength= (BYTE) data[1];  \r
+       b_TurnCptLength         = (BYTE) data[2];\r
+       b_PCIInputClock         = (BYTE) data[3];\r
+       ul_SSIOutputClock       = (ULONG) data[4];\r
+       b_SSICountingMode       = (BYTE)  data[5];     |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a SSI module                      |\r
+|                    -4: The selected SSI profile length is wrong            |\r
+|                    -5: The selected SSI position data length is wrong      |\r
+|                    -6: The selected SSI turn counter data length is wrong  |\r
+|                    -7: The selected PCI input clock is wrong               |\r
+|                    -8: The selected SSI output clock is wrong              |\r
+|                    -9: The selected SSI counting mode parameter is wrong   |\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+\r
+INT   i_APCI1710_InsnConfigInitSSI(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       UINT   ui_TimerValue;\r
+       BYTE   b_ModulNbr,b_SSIProfile,b_PositionTurnLength,b_TurnCptLength,b_PCIInputClock,b_SSICountingMode;\r
+       ULONG  ul_SSIOutputClock;\r
+                       \r
+       b_ModulNbr                      = CR_AREF(insn->chanspec);\r
+       b_SSIProfile            = (BYTE) data[0];  \r
+       b_PositionTurnLength= (BYTE) data[1];  \r
+       b_TurnCptLength         = (BYTE) data[2];\r
+       b_PCIInputClock         = (BYTE) data[3];\r
+       ul_SSIOutputClock       = (ULONG) data[4];\r
+       b_SSICountingMode       = (BYTE)  data[5];\r
+\r
+       i_ReturnValue           = insn->n;\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if SSI counter */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_SSI_COUNTER)\r
+             {\r
+             /*******************************/\r
+             /* Test the SSI profile length */\r
+             /*******************************/\r
+\r
+             // CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2\r
+             if (b_SSIProfile >= 2 && b_SSIProfile < 33)\r
+                {\r
+                /*************************************/\r
+                /* Test the SSI position data length */\r
+                /*************************************/\r
+\r
+                if (b_PositionTurnLength > 0 && b_PositionTurnLength < 32)\r
+                   {\r
+                   /*****************************************/\r
+                   /* Test the SSI turn counter data length */\r
+                   /*****************************************/\r
+\r
+                   if (b_TurnCptLength > 0 && b_TurnCptLength < 32)\r
+                      {\r
+                      /***************************/\r
+                      /* Test the profile length */\r
+                      /***************************/\r
+\r
+                      if ((b_TurnCptLength + b_PositionTurnLength) <= b_SSIProfile)\r
+                         {\r
+                         /****************************/\r
+                         /* Test the PCI input clock */\r
+                         /****************************/\r
+\r
+                         if (b_PCIInputClock == APCI1710_30MHZ || b_PCIInputClock == APCI1710_33MHZ)\r
+                            {\r
+                            /*************************/\r
+                            /* Test the output clock */\r
+                            /*************************/\r
+\r
+                            if ((b_PCIInputClock == APCI1710_30MHZ &&\r
+                                 (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) ||\r
+                                (b_PCIInputClock == APCI1710_33MHZ &&\r
+                                 (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL)))\r
+                               {\r
+                               if (b_SSICountingMode == APCI1710_BINARY_MODE ||\r
+                                   b_SSICountingMode == APCI1710_GRAY_MODE)\r
+                                  {\r
+                                  /**********************/\r
+                                  /* Save configuration */\r
+                                  /**********************/\r
+                                  devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                  s_SSICounterInfo.\r
+                                  b_SSIProfile = b_SSIProfile;\r
+\r
+                                  \r
+                                  devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                  s_SSICounterInfo.\r
+                                  b_PositionTurnLength = b_PositionTurnLength;\r
+\r
+                                  devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                  s_SSICounterInfo.\r
+                                  b_TurnCptLength = b_TurnCptLength;\r
+\r
+                                  /*********************************/\r
+                                  /* Initialise the profile length */\r
+                                  /*********************************/\r
+\r
+                                  if (b_SSICountingMode == APCI1710_BINARY_MODE)\r
+                                     {\r
+                                   
+                                       outl(b_SSIProfile + 1,devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));\r
+                                     }\r
+                                  else\r
+                                     {\r
+                                               
+                                          outl(b_SSIProfile,devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));\r
+                                     }\r
+\r
+                                  /******************************/\r
+                                  /* Calculate the output clock */\r
+                                  /******************************/\r
+\r
+                                  ui_TimerValue = (UINT) (((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);\r
+\r
+                                  /************************/\r
+                                  /* Initialise the timer */\r
+                                  /************************/\r
+\r
+                                 \r
+                                   outl(ui_TimerValue,devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+\r
+\r
+                                  /********************************/\r
+                                  /* Initialise the counting mode */\r
+                                  /********************************/\r
+                                       \r
+                                       outl(7 * b_SSICountingMode,devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));\r
+                                  \r
+                                       devpriv->s_ModuleInfo [b_ModulNbr].s_SSICounterInfo.b_SSIInit = 1;\r
+                                  }\r
+                               else\r
+                                  {\r
+                                  /*****************************************************/\r
+                                  /* The selected SSI counting mode parameter is wrong */\r
+                                  /*****************************************************/\r
+\r                          DPRINTK("The selected SSI counting mode parameter is wrong\n");
+                                  i_ReturnValue = -9;\r
+                                  }\r
+                               }\r
+                            else\r
+                               {\r
+                               /******************************************/\r
+                               /* The selected SSI output clock is wrong */\r
+                               /******************************************/\r
+\r                              DPRINTK("The selected SSI output clock is wrong\n");
+                               i_ReturnValue = -8;\r
+                               }\r
+                            }\r
+                         else\r
+                            {\r
+                            /*****************************************/\r
+                            /* The selected PCI input clock is wrong */\r
+                            /*****************************************/\r
+\r                               DPRINTK("The selected PCI input clock is wrong\n");
+                            i_ReturnValue = -7;\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         /********************************************/\r
+                         /* The selected SSI profile length is wrong */\r
+                         /********************************************/\r
+\r                        DPRINTK("The selected SSI profile length is wrong\n");        
+                         i_ReturnValue = -4;\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /******************************************************/\r
+                      /* The selected SSI turn counter data length is wrong */\r
+                      /******************************************************/\r
+\r                         DPRINTK("The selected SSI turn counter data length is wrong\n");     
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /**************************************************/\r
+                   /* The selected SSI position data length is wrong */\r
+                   /**************************************************/\r
+\r                      DPRINTK("The selected SSI position data length is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /********************************************/\r
+                /* The selected SSI profile length is wrong */\r
+                /********************************************/\r
+\r               DPRINTK("The selected SSI profile length is wrong\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /**********************************/\r
+             /* The module is not a SSI module */\r
+             /**********************************/\r
+\r            DPRINTK("The module is not a SSI module\n");      
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_  i_APCI1710_Read1SSIValue                        |\r
+|                               (BYTE_     b_BoardHandle,                    |\r
+|                                BYTE_     b_ModulNbr,                       |\r
+|                                BYTE_     b_SelectedSSI,                    |\r
+|                                PULONG_ pul_Position,                       |\r
+|                                PULONG_ pul_TurnCpt) \r
+ INT i_APCI1710_ReadSSIValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)                       |\r
++----------------------------------------------------------------------------+\r
+| Task              :\r
+\r
+  \r
+                                               Read the selected SSI counter (b_SelectedSSI) from     |\r
+|                     selected module (b_ModulNbr).\r
+                                               or Read all SSI counter (b_SelectedSSI) from              |\r
+|                     selected module (b_ModulNbr).                            |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|\r
+|                     BYTE_ b_ModulNbr            : Module number to         |\r
+|                                                   configure (0 to 3)       |\r
+|                     BYTE_ b_SelectedSSI         : Selection from SSI       |\r
+|                                                   counter (0 to 2)    \r
+\r
+    b_ModulNbr         =   (BYTE) CR_AREF(insn->chanspec);\r
+       b_SelectedSSI   =       (BYTE) CR_CHAN(insn->chanspec); (in case of single ssi)\r
+       b_ReadType              =       (BYTE) CR_RANGE(insn->chanspec);\r
+|\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PULONG_  pul_Position       : SSI position in the turn |\r
+|                     PULONG_  pul_TurnCpt        : Number of turns \r
+\r
+pul_Position   =       (PULONG) &data[0];\r
+       pul_TurnCpt             =       (PULONG) &data[1];         |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a SSI module                      |\r
+|                    -4: SSI not initialised see function                    |\r
+|                        "i_APCI1710_InitSSI"                                |\r
+|                    -5: The selected SSI is wrong                           |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+   INT i_APCI1710_InsnReadSSIValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       BYTE   b_Cpt;\r
+       BYTE   b_Length;\r
+       BYTE   b_Schift;\r
+       BYTE   b_SSICpt;\r
+       DWORD dw_And;\r
+       DWORD dw_And1;\r
+       DWORD dw_And2;\r
+       DWORD dw_StatusReg;\r
+       DWORD dw_CounterValue;\r
+       BYTE  b_ModulNbr;\r
+       BYTE  b_SelectedSSI;\r
+       BYTE  b_ReadType;\r
+       PULONG pul_Position;\r
+       PULONG pul_TurnCpt;\r
+       PULONG pul_Position1;
+       PULONG pul_TurnCpt1;
+
+\r
+       i_ReturnValue   =       insn->n;         \r
+       pul_Position1   =       (PULONG) &data[0];\r// For Read1
+       pul_TurnCpt1    =       (PULONG) &data[1];\r// For Read all
+               pul_Position    =       (PULONG) &data[0];//0-2
+       pul_TurnCpt     =       (PULONG) &data[3];//3-5
+       b_ModulNbr              =   (BYTE) CR_AREF(insn->chanspec);\r
+       b_SelectedSSI   =       (BYTE) CR_CHAN(insn->chanspec);\r
+       b_ReadType              =       (BYTE) CR_RANGE(insn->chanspec);\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if SSI counter */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_SSI_COUNTER)\r
+             {\r
+             /***************************/\r
+             /* Test if SSI initialised */\r
+             /***************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_SSICounterInfo.\r
+                 b_SSIInit == 1)\r
+                {\r
+          \r
+                       switch(b_ReadType)\r
+                       {\r
+\r
+                       case APCI1710_SSI_READ1VALUE :\r
+                /****************************************/\r
+                /* Test the selected SSI counter number */\r
+                /****************************************/\r
+\r
+                if (b_SelectedSSI < 3)\r
+                   {\r
+                   /************************/\r
+                   /* Start the conversion */\r
+                   /************************/\r
+\r\r
+                       outl(0,devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr));\r
+                       \r
+\r
+                   do\r
+                      {\r
+                      /*******************/\r
+                      /* Read the status */\r
+                      /*******************/\r
+                               \r
+                               dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+                      }\r
+                   while ((dw_StatusReg & 0x1) != 0);\r
+\r
+                   /******************************/\r
+                   /* Read the SSI counter value */\r
+                   /******************************/\r
+               
+                       dw_CounterValue = inl(devpriv->s_BoardInfos.ui_Address + 4 + (b_SelectedSSI * 4) + (64 * b_ModulNbr));\r
+\r
+                   b_Length = devpriv->s_ModuleInfo [b_ModulNbr].s_SSICounterInfo.b_SSIProfile / 2;\r
+\r
+                   if ((b_Length * 2) != devpriv->s_ModuleInfo [b_ModulNbr].s_SSICounterInfo.b_SSIProfile)\r
+                      {\r
+                      b_Length ++;\r
+                      }\r
+\r
+                   b_Schift = b_Length - devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                         s_SSICounterInfo.\r
+                                         b_PositionTurnLength;\r
+\r
+\r
+                   *pul_Position1 = dw_CounterValue >> b_Schift;\r
+\r
+                   dw_And = 1;\r
+\r
+                   for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                           s_SSICounterInfo.\r
+                                           b_PositionTurnLength; b_Cpt ++)\r
+                      {\r
+                      dw_And = dw_And * 2;\r
+                      }\r
+\r
+                   *pul_Position1 = *pul_Position1 & ((dw_And) - 1);\r
+\r
+                   *pul_TurnCpt1 = dw_CounterValue >> b_Length;\r
+\r
+                   dw_And = 1;\r
+\r
+                   for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                           s_SSICounterInfo.\r
+                                           b_TurnCptLength; b_Cpt ++)\r
+                      {\r
+                      dw_And = dw_And * 2;\r
+                      }\r
+\r
+                   *pul_TurnCpt1 = *pul_TurnCpt1 & ((dw_And) - 1);\r
+                   }\r
+                else\r
+                   {\r
+                   /*****************************/\r
+                   /* The selected SSI is wrong */\r
+                   /*****************************/\r
+\r                   DPRINTK("The selected SSI is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+               break;\r
+\r
+                case APCI1710_SSI_READALLVALUE :\r
+                        dw_And1 = 1;\r
+\r
+                for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                        s_SSICounterInfo.\r
+                                        b_PositionTurnLength; b_Cpt ++)\r
+                   {\r
+                   dw_And1 = dw_And1 * 2;\r
+                   }\r
+\r
+                dw_And2 = 1;\r
+\r
+                for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                        s_SSICounterInfo.\r
+                                        b_TurnCptLength; b_Cpt ++)\r
+                   {\r
+                   dw_And2 = dw_And2 * 2;\r
+                   }\r
+\r
+                /************************/\r
+                /* Start the conversion */\r
+                /************************/\r
+               
+                outl(0,devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr));\r
+\r
+                do\r
+                   {\r
+                   /*******************/\r
+                   /* Read the status */\r
+                   /*******************/\r
+                       \r
+                       dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+                   }\r
+                while ((dw_StatusReg & 0x1) != 0);\r
+\r
+                for (b_SSICpt = 0; b_SSICpt < 3; b_SSICpt ++)\r
+                   {\r
+                   /******************************/\r
+                   /* Read the SSI counter value */\r
+                   /******************************/\r
+\r
+                 \r
+                        dw_CounterValue = inl(devpriv->s_BoardInfos.ui_Address + 4 + (b_SSICpt * 4) + (64 * b_ModulNbr));\r
+\r
+                   b_Length = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                              s_SSICounterInfo.\r
+                              b_SSIProfile / 2;\r
+\r
+                   if ((b_Length * 2) != devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                         s_SSICounterInfo.\r
+                                         b_SSIProfile)\r
+                      {\r
+                      b_Length ++;\r
+                      }\r
+\r
+                   b_Schift = b_Length - devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                         s_SSICounterInfo.\r
+                                         b_PositionTurnLength;\r
+\r
+\r
+                   pul_Position [b_SSICpt] = dw_CounterValue >> b_Schift;\r
+                   pul_Position [b_SSICpt] = pul_Position [b_SSICpt] & ((dw_And1) - 1);\r
+\r
+                   pul_TurnCpt [b_SSICpt] = dw_CounterValue >> b_Length;\r
+                   pul_TurnCpt [b_SSICpt] = pul_TurnCpt [b_SSICpt] & ((dw_And2) - 1);\r
+                   }\r
+                break;\r
+\r
+                default :\r
+                        printk("Read Type Inputs Wrong\n");\r
+\r
+                } // switch  ending\r
+\r
+                }\r
+             else\r
+                {\r
+                /***********************/\r
+                /* SSI not initialised */\r
+                /***********************/\r
+\r                DPRINTK("SSI not initialised\n");
+                i_ReturnValue = -4;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /**********************************/\r
+             /* The module is not a SSI module */\r
+             /**********************************/\r
+\r             DPRINTK("The module is not a SSI module\n");
+             i_ReturnValue = -3;\r 
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");    
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_   i_APCI1710_ReadSSI1DigitalInput                |\r
+|                                       (BYTE_     b_BoardHandle,            |\r
+|                                        BYTE_     b_ModulNbr,               |\r
+|                                        BYTE_     b_InputChannel,           |\r
+|                                        PBYTE_   pb_ChannelStatus)          |\r
++----------------------------------------------------------------------------+\r
+| Task              :\r
+                                       (0) Set the digital output from selected SSI moule         |\r
+|                     (b_ModuleNbr) ON\r
+                    (1) Set the digital output from selected SSI moule         |\r
+|                     (b_ModuleNbr) OFF        \r
+                                       (2)Read the status from selected SSI digital input        |\r
+|                     (b_InputChannel)  \r
+                    (3)Read the status from all SSI digital inputs from       |\r
+|                     selected SSI module (b_ModulNbr)                   |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|\r
+|                     BYTE_ b_ModulNbr    CR_AREF        : Module number to         |\r
+|                                                   configure (0 to 3)       |\r
+|                     BYTE_ b_InputChannel CR_CHAN       : Selection from digital   |\r
+|                        data[0] which IOTYPE                           input ( 0 to 2)          |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_  pb_ChannelStatus    : Digital input channel    |\r
+|                                 data[0]                  status                   |\r
+|                                                   0 : Channle is not active|\r
+|                                                   1 : Channle is active    |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a SSI module                      |\r
+|                    -4: The selected SSI digital input is wrong             |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+\r
+INT    i_APCI1710_InsnBitsSSIDigitalIO(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,\r
+lsampl_t *data)\r
+       {\r
+       INT     i_ReturnValue = 0;\r
+       DWORD   dw_StatusReg;\r
+       BYTE    b_ModulNbr;\r
+       BYTE    b_InputChannel;\r
+       PBYTE   pb_ChannelStatus;
+        PBYTE   pb_InputStatus;\r
+       BYTE    b_IOType;\r
+       i_ReturnValue = insn->n;\r
+        b_ModulNbr    = (BYTE) CR_AREF(insn->chanspec);\r
+        b_IOType      = (BYTE) data[0];\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if SSI counter */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_SSI_COUNTER)\r
+             {\r
+           switch(b_IOType)\r
+                  {\r
+                  case    APCI1710_SSI_SET_CHANNELON :\r
+                                       /*****************************/\r
+                                       /* Set the digital output ON */\r
+                                       /*****************************/\r
+\r
+                                       
+                   outl(1,devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr));\r
+                              break ;\r
+\r
+                  case    APCI1710_SSI_SET_CHANNELOFF :\r
+                                       /******************************/\r
+                                       /* Set the digital output OFF */\r
+                                       /******************************/\r
+\r
+                               
+                                  outl(0,devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr));\r
+                              break ;\r
+                  \r
+               \r
+\r
+                  case APCI1710_SSI_READ_1CHANNEL:\r
+                                  /******************************************/\r
+                                  /* Test the digital imnput channel number */\r
+                                  /******************************************/\r
+\r
+                                       b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);\r
+                                       pb_ChannelStatus = (PBYTE) &data[0];\r
+\r
+                                       if ((b_InputChannel >= 0) && (b_InputChannel <= 2))\r
+                                       {\r
+                                       /**************************/\r
+                                       /* Read all digital input */\r
+                                       /**************************/\r
+       \r
+                                       \r
+                                       dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+                                       *pb_ChannelStatus = (BYTE) (((~dw_StatusReg) >> (4 + b_InputChannel)) & 1);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                       /********************************/\r
+                                       /* Selected digital input error */\r
+                                       /********************************/\r
+\r                           DPRINTK("Selected digital input error\n");
+                                       i_ReturnValue = -4;\r
+                                       }\r
+                                       break;\r
+\r
+                       case APCI1710_SSI_READ_ALLCHANNEL:\r
+                                       /**************************/\r
+                                       /* Read all digital input */\r
+                                       /**************************/\r
+                                       pb_InputStatus = (PBYTE) &data[0];\r
+\r
+                               \r
+                                       dw_StatusReg      = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+                                       *pb_InputStatus = (BYTE) (((~dw_StatusReg) >> 4) & 7);\r
+                                       break;\r
+\r
+                       default :\r
+                                       printk("IO type wrong\n");\r
+
+                } //switch end\r
+             }\r
+          else\r
+             {\r
+             /**********************************/\r
+             /* The module is not a SSI module */\r
+             /**********************************/\r
+\r            DPRINTK("The module is not a SSI module\n");      
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
diff --git a/comedi/drivers/addi-data/APCI1710_Ssi.h b/comedi/drivers/addi-data/APCI1710_Ssi.h
new file mode 100644 (file)
index 0000000..918558d
--- /dev/null
@@ -0,0 +1,40 @@
+\r
+
+\r
+\r
+#define APCI1710_30MHZ           30\r
+#define APCI1710_33MHZ           33\r
+#define APCI1710_40MHZ           40\r
+
+\r
+#define APCI1710_BINARY_MODE     0x1\r
+#define APCI1710_GRAY_MODE       0x0\r
+\r
+#define APCI1710_SSI_READ1VALUE                                1\r
+#define APCI1710_SSI_READALLVALUE                      2\r
+\r
+\r
+#define APCI1710_SSI_SET_CHANNELON       0\r
+#define APCI1710_SSI_SET_CHANNELOFF            1\r
+#define APCI1710_SSI_READ_1CHANNEL             2\r
+#define APCI1710_SSI_READ_ALLCHANNEL           3\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       SSI INISIALISATION FUNCTION                          |\r
++----------------------------------------------------------------------------+\r
+*/\r
+INT   i_APCI1710_InsnConfigInitSSI(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+
+INT i_APCI1710_InsnReadSSIValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+
+\r
+INT    i_APCI1710_InsnBitsSSIDigitalIO(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,\r
+lsampl_t *data);\r
+\r
+
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Tor.c b/comedi/drivers/addi-data/APCI1710_Tor.c
new file mode 100644 (file)
index 0000000..bc06967
--- /dev/null
@@ -0,0 +1,1737 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : TOR.C           |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 14.12.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 tor counter module                          |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  | 27/01/99 | S. Weber  | 40 MHz implementation                          |\r
+  +-----------------------------------------------------------------------+\r
+  | 28/04/00 | S. Weber  | Simple,double and quadruple mode implementation|\r
+  |          |           | Extern clock implementation                    |\r
+  +-----------------------------------------------------------------------+\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+#include "APCI1710_Tor.h"\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_     i_APCI1710_InitTorCounter                    |\r
+|                                       (BYTE_     b_BoardHandle,            |\r
+|                                        BYTE_     b_ModulNbr,               |\r
+|                                        BYTE_     b_TorCounter,             |\r
+|                                        BYTE_     b_PCIInputClock,          |\r
+|                                        BYTE_     b_TimingUnit,             |\r
+|                                        ULONG_   ul_TimingInterval,         |\r
+|                                        PULONG_ pul_RealTimingInterval)     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Configure the selected tor counter (b_TorCounter)      |\r
+|                     from selected module (b_ModulNbr).                     |\r
+|                     The ul_TimingInterval and ul_TimingUnit determine the  |\r
+|                     timing base for the measurement.                       |\r
+|                     The pul_RealTimingInterval return the real timing      |\r
+|                     value. You must calling this function be for you call  |\r
+|                     any other function witch access of the tor counter.    |\r
+|                                                                            |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  :    |\r
+|                     \r
+               CR_AREF BYTE_   b_ModulNbr       : Module number to configure  |\r
+|                                                (0 to 3)                    |\r
+|           data[0] BYTE_   b_TorCounter     : Tor counter selection       |\r
+|                                                (0 or 1).                   |\r
+|           data[1] BYTE_   b_PCIInputClock  : Selection from PCI bus clock|\r
+|                                                - APCI1710_30MHZ :          |\r
+|                                                  The PC have a PCI bus     |\r
+|                                                  clock from 30 MHz         |\r
+|                                                - APCI1710_33MHZ :          |\r
+|                                                  The PC have a PCI bus     |\r
+|                                                  clock from 33 MHz         |\r
+|                                                - APCI1710_40MHZ            |\r
+|                                                  The APCI-1710 have a      |\r
+|                                                  integrated 40Mhz          |\r
+|                                                  quartz.                   |\r
+|                                                - APCI1710_GATE_INPUT       |\r
+|                                                  Used the gate input for   |\r
+|                                                 the base clock. If you    |\r
+|                                                 have selected this option,|\r
+|                                                 than it is not possibl to |\r
+|                                                 used the gate input for   |\r
+|                                                 enabled the acquisition   |\r
+|           data[2] BYTE_   b_TimingUnit    : Base timing unit (0 to 4)    |\r
+|                                                 0 : ns                     |\r
+|                                                 1 : µs                     |\r
+|                                                 2 : ms                     |\r
+|                                                 3 : s                      |\r
+|                                                 4 : mn                     |\r
+|           data[3]          ULONG_ ul_TimingInterval : Base timing value.          |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PULONG_  pul_RealTimingInterval : Real  base timing    |\r
+|                     data[0]                                  value.               |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a tor counter module             |\r
+|                     -4: Tor counter selection is wrong                     |\r
+|                     -5: The selected PCI input clock is wrong              |\r
+|                     -6: Timing unit selection is wrong                     |\r
+|                     -7: Base timing selection is wrong                     |\r
+|                     -8: You can not used the 40MHz clock selection wich    |\r
+|                         this board                                         |\r
+|                     -9: You can not used the 40MHz clock selection wich    |\r
+|                         this TOR version                                   |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+
+\r
+INT   i_APCI1710_InsnConfigInitTorCounter(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       ULONG ul_TimerValue;\r
+       DWORD dw_Command;\r
+       double d_RealTimingInterval;\r
+       BYTE     b_ModulNbr;\r
+       BYTE     b_TorCounter;\r
+       BYTE     b_PCIInputClock;\r
+       BYTE     b_TimingUnit;\r
+       ULONG    ul_TimingInterval;\r
+       ULONG   ul_RealTimingInterval;\r
+\r
+       i_ReturnValue                   =   insn->n;\r
+       b_ModulNbr                              =   (BYTE)  CR_AREF(insn->chanspec);\r
+\r
+       b_TorCounter                    =       (BYTE)  data[0];\r
+       b_PCIInputClock                 =       (BYTE)  data[1];\r
+       b_TimingUnit                    =       (BYTE)  data[2];\r
+       ul_TimingInterval               =       (ULONG) data[3];\r
+       printk("INPUT clock %d\n",b_PCIInputClock);
+       \r
+               /**************************/\r
+               /* Test the module number */\r
+               /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+               /***********************/\r
+               /* Test if tor counter */\r
+               /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER)\r
+             {\r
+             /**********************************/\r
+             /* Test the tor counter selection */\r
+             /**********************************/\r
+\r
+             if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+                {\r
+                /**************************/\r
+                /* Test the PCI bus clock */\r
+                /**************************/\r
+\r
+                if ((b_PCIInputClock == APCI1710_30MHZ) ||\r
+                    (b_PCIInputClock == APCI1710_33MHZ) ||\r
+                    (b_PCIInputClock == APCI1710_40MHZ) ||\r
+                    (b_PCIInputClock == APCI1710_GATE_INPUT))\r
+                   {\r
+                   /************************/\r
+                   /* Test the timing unit */\r
+                   /************************/\r
+\r
+                   if (((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) || (b_PCIInputClock == APCI1710_GATE_INPUT))\r
+                      {\r
+                      /**********************************/\r
+                      /* Test the base timing selection */\r
+                      /**********************************/\r
+\r
+                      if(((b_PCIInputClock == APCI1710_30MHZ)   && (b_TimingUnit == 0) && (ul_TimingInterval >= 133) && (ul_TimingInterval <= 0xFFFFFFFFUL)) ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ)      && (b_TimingUnit == 1) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 571230650UL))  ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ)      && (b_TimingUnit == 2) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 571230UL))     ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ)      && (b_TimingUnit == 3) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 571UL))        ||\r
+                          ((b_PCIInputClock == APCI1710_30MHZ)      && (b_TimingUnit == 4) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 9UL))          ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ)      && (b_TimingUnit == 0) && (ul_TimingInterval >= 121) && (ul_TimingInterval <= 0xFFFFFFFFUL)) ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ)      && (b_TimingUnit == 1) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 519691043UL))  ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ)      && (b_TimingUnit == 2) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 519691UL))     ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ)      && (b_TimingUnit == 3) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 520UL))        ||\r
+                          ((b_PCIInputClock == APCI1710_33MHZ)      && (b_TimingUnit == 4) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 8UL))          ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ)      && (b_TimingUnit == 0) && (ul_TimingInterval >= 100) && (ul_TimingInterval <= 0xFFFFFFFFUL)) ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ)      && (b_TimingUnit == 1) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 429496729UL))  ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ)      && (b_TimingUnit == 2) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 429496UL))     ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ)      && (b_TimingUnit == 3) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 429UL))        ||\r
+                          ((b_PCIInputClock == APCI1710_40MHZ)      && (b_TimingUnit == 4) && (ul_TimingInterval >= 1)   && (ul_TimingInterval <= 7UL))          ||\r
+                          ((b_PCIInputClock == APCI1710_GATE_INPUT) && (ul_TimingInterval >= 2)))\r
+                         {\r
+                               /**************************/\r
+                               /* Test the board version */\r
+                               /**************************/\r
+\r
+                         if ((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.\r
+                                                                     b_BoardVersion > 0) ||\r
+                             (b_PCIInputClock != APCI1710_40MHZ))\r
+                            {\r
+                            /************************/\r
+                            /* Test the TOR version */\r
+                            /************************/\r
+\r
+                            if ((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.\r
+                                                                         dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3131) ||\r
+                                (b_PCIInputClock == APCI1710_GATE_INPUT) && ((devpriv->s_BoardInfos.\r
+                                                                              dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3132) ||\r
+                                (b_PCIInputClock == APCI1710_30MHZ) ||\r
+                                (b_PCIInputClock == APCI1710_33MHZ))\r
+                               {\r
+                               /*********************************/\r
+                               /* Test if not extern clock used */\r
+                               /*********************************/\r
+\r
+                               if (b_PCIInputClock != APCI1710_GATE_INPUT)\r
+                                  {\r
+                                  /****************************************/\r
+                                  /* Calculate the timer 0 division fator */\r
+                                  /****************************************/\r
+\r
+                                  switch (b_TimingUnit)\r
+                                     {\r
+                                     /******/\r
+                                     /* ns */\r
+                                     /******/\r
+\r
+                                     case 0:\r
+                                          \r
+                                             /******************/\r
+                                             /* Timer 0 factor */\r
+                                             /******************/\r
+\r
+                                             ul_TimerValue = (ULONG) (ul_TimingInterval * (0.00025 * b_PCIInputClock));\r
+\r
+                                             /*******************/\r
+                                             /* Round the value */\r
+                                             /*******************/\r
+\r
+                                             if ((double) ((double) ul_TimingInterval * (0.00025 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                                {\r
+                                                ul_TimerValue = ul_TimerValue + 1;\r
+                                                }\r
+\r
+                                             /*****************************/\r
+                                             /* Calculate the real timing */\r
+                                             /*****************************/\r
+\r
+                                             ul_RealTimingInterval = (ULONG) (ul_TimerValue / (0.00025 * (double) b_PCIInputClock));\r
+                                             d_RealTimingInterval = (double) ul_TimerValue / (0.00025 * (double) b_PCIInputClock);\r
+\r
+                                             if ((double) ((double) ul_TimerValue / (0.00025 * (double) b_PCIInputClock)) >= (double) ((double) ul_RealTimingInterval + 0.5))\r
+                                                {\r
+                                                ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                                }\r
+\r
+                                             ul_TimingInterval = ul_TimingInterval - 1;\r
+                                             ul_TimerValue     = ul_TimerValue - 2;\r
+\r
+                                             if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                                {\r
+                                                ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 1.007752288);\r
+                                                }\r
+                                          \r
+\r
+                                          break;\r
+\r
+                                     /******/\r
+                                     /* æs */\r
+                                     /******/\r
+\r
+                                     case 1:\r
+                                          \r
+                                             /******************/\r
+                                             /* Timer 0 factor */\r
+                                             /******************/\r
+\r
+                                             ul_TimerValue = (ULONG) (ul_TimingInterval * (0.25 * b_PCIInputClock));\r
+\r
+                                             /*******************/\r
+                                             /* Round the value */\r
+                                             /*******************/\r
+\r
+                                             if ((double) ((double) ul_TimingInterval * (0.25 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                                {\r
+                                                ul_TimerValue = ul_TimerValue + 1;\r
+                                                }\r
+\r
+                                             /*****************************/\r
+                                             /* Calculate the real timing */\r
+                                             /*****************************/\r
+\r
+                                             ul_RealTimingInterval = (ULONG) (ul_TimerValue / (0.25 * (double) b_PCIInputClock));\r
+                                             d_RealTimingInterval = (double) ul_TimerValue / ((double) 0.25 * (double) b_PCIInputClock);\r
+\r
+                                            if ((double) ((double) ul_TimerValue / (0.25 * (double) b_PCIInputClock)) >= (double) ((double) ul_RealTimingInterval + 0.5))\r
+                                                {\r
+                                                ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                                }\r
+\r
+                                             ul_TimingInterval = ul_TimingInterval - 1;\r
+                                             ul_TimerValue     = ul_TimerValue - 2;\r
+\r
+                                             if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                                {\r
+                                                ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 1.007752288);\r
+                                                }\r
+                                          \r
+\r
+                                          break;\r
+\r
+                                     /******/\r
+                                     /* ms */\r
+                                     /******/\r
+\r
+                                     case 2:\r
+                                          \r
+                                             /******************/\r
+                                             /* Timer 0 factor */\r
+                                             /******************/\r
+\r
+                                             ul_TimerValue = ul_TimingInterval * (250.0 * b_PCIInputClock);\r
+\r
+                                             /*******************/\r
+                                             /* Round the value */\r
+                                             /*******************/\r
+\r
+                                             if ((double) ((double) ul_TimingInterval * (250.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                                {\r
+                                                ul_TimerValue = ul_TimerValue + 1;\r
+                                                }\r
+\r
+                                             /*****************************/\r
+                                             /* Calculate the real timing */\r
+                                             /*****************************/\r
+\r
+                                             ul_RealTimingInterval = (ULONG) (ul_TimerValue / (250.0 * (double) b_PCIInputClock));\r
+                                             d_RealTimingInterval = (double) ul_TimerValue / (250.0 * (double) b_PCIInputClock);\r
+\r
+                                             if ((double) ((double) ul_TimerValue / (250.0 * (double) b_PCIInputClock)) >= (double) ((double) ul_RealTimingInterval + 0.5))\r
+                                                {\r
+                                                ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                                }\r
+\r
+                                             ul_TimingInterval = ul_TimingInterval - 1;\r
+                                             ul_TimerValue     = ul_TimerValue - 2;\r
+\r
+                                             if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                                {\r
+                                                ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 1.007752288);\r
+                                                }\r
+                                          \r
+\r
+                                          break;\r
+\r
+                                     /*****/\r
+                                     /* s */\r
+                                     /*****/\r
+\r
+                                     case 3:\r
+                                          \r
+                                             /******************/\r
+                                             /* Timer 0 factor */\r
+                                             /******************/\r
+\r
+                                             ul_TimerValue = (ULONG) (ul_TimingInterval * (250000.0 * b_PCIInputClock));\r
+\r
+                                             /*******************/\r
+                                             /* Round the value */\r
+                                             /*******************/\r
+\r
+                                             if ((double) ((double) ul_TimingInterval * (250000.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                                {\r
+                                                ul_TimerValue = ul_TimerValue + 1;\r
+                                                }\r
+\r
+                                             /*****************************/\r
+                                             /* Calculate the real timing */\r
+                                             /*****************************/\r
+\r
+                                             ul_RealTimingInterval = (ULONG) (ul_TimerValue / (250000.0 * (double) b_PCIInputClock));\r
+                                             d_RealTimingInterval = (double) ul_TimerValue / (250000.0 * (double) b_PCIInputClock);\r
+\r
+                                             if ((double) ((double) ul_TimerValue / (250000.0 * (double) b_PCIInputClock)) >= (double) ((double) ul_RealTimingInterval + 0.5))\r
+                                                {\r
+                                                ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                                }\r
+\r
+                                             ul_TimingInterval = ul_TimingInterval - 1;\r
+                                             ul_TimerValue     = ul_TimerValue - 2;\r
+\r
+                                             if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                                {\r
+                                                ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 1.007752288);\r
+                                                }\r
+                                          \r
+\r
+                                          break;\r
+\r
+                                     /******/\r
+                                     /* mn */\r
+                                     /******/\r
+\r
+                                     case 4:\r
+                                          \r
+                                             /******************/\r
+                                             /* Timer 0 factor */\r
+                                             /******************/\r
+\r
+                                             ul_TimerValue = (ULONG) ((ul_TimingInterval * 60) * (250000.0 * b_PCIInputClock));\r
+\r
+                                             /*******************/\r
+                                             /* Round the value */\r
+                                             /*******************/\r
+\r
+                                             if ((double) ((double) (ul_TimingInterval * 60.0) * (250000.0 * (double) b_PCIInputClock)) >= ((double) ((double) ul_TimerValue + 0.5)))\r
+                                                {\r
+                                                ul_TimerValue = ul_TimerValue + 1;\r
+                                                }\r
+\r
+                                             /*****************************/\r
+                                             /* Calculate the real timing */\r
+                                             /*****************************/\r
+\r
+                                             ul_RealTimingInterval = (ULONG) (ul_TimerValue / (250000.0 * (double) b_PCIInputClock)) / 60;\r
+                                             d_RealTimingInterval = ((double) ul_TimerValue / (250000.0 * (double) b_PCIInputClock)) / 60.0;\r
+\r
+                                             if ((double) (((double) ul_TimerValue / (250000.0 * (double) b_PCIInputClock)) / 60.0) >= (double) ((double) ul_RealTimingInterval + 0.5))\r
+                                                {\r
+                                                ul_RealTimingInterval = ul_RealTimingInterval + 1;\r
+                                                }\r
+\r
+                                             ul_TimingInterval = ul_TimingInterval - 1;\r
+                                             ul_TimerValue     = ul_TimerValue - 2;\r
+\r
+                                             if (b_PCIInputClock != APCI1710_40MHZ)\r
+                                                {\r
+                                                ul_TimerValue     = (ULONG) ((double) (ul_TimerValue) * 1.007752288);\r
+                                                }\r
+                                          \r
+                                          break;\r
+                                     }\r
+                                  } // if (b_PCIInputClock != APCI1710_GATE_INPUT)\r
+                               else\r
+                                  {\r
+                                  /*************************************************************/\r
+                                  /* 2 Clock used for the overflow and the reload from counter */\r
+                                  /*************************************************************/\r
+\r
+                                  ul_TimerValue = ul_TimingInterval - 2;\r
+                                  } // if (b_PCIInputClock != APCI1710_GATE_INPUT)\r
+\r
+                               /****************************/\r
+                               /* Save the PCI input clock */\r
+                               /****************************/\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_TorCounterModuleInfo.\r
+                               b_PCIInputClock = b_PCIInputClock;\r
+\r
+                               /************************/\r
+                               /* Save the timing unit */\r
+                               /************************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_TorCounterModuleInfo.\r
+                               s_TorCounterInfo [b_TorCounter].\r
+                               b_TimingUnit = b_TimingUnit;\r
+\r
+                               /************************/\r
+                               /* Save the base timing */\r
+                               /************************/\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_TorCounterModuleInfo.\r
+                               s_TorCounterInfo [b_TorCounter].\r
+                               d_TimingInterval = d_RealTimingInterval;\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_TorCounterModuleInfo.\r
+                               s_TorCounterInfo [b_TorCounter].\r
+                               ul_RealTimingInterval = ul_RealTimingInterval;\r
+\r
+                               /*******************/\r
+                               /* Get the command */\r
+                               /*******************/\r
+\r
+                               
+                               dw_Command = inl(devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                               dw_Command = (dw_Command >> 4) & 0xF;\r
+\r
+                               /******************/\r
+                               /* Test if 40 MHz */\r
+                               /******************/\r
+\r
+                               if (b_PCIInputClock == APCI1710_40MHZ)\r
+                                  {\r
+                                  /****************************/\r
+                                  /* Set the 40 MHz selection */\r
+                                  /****************************/\r
+\r
+                                  dw_Command = dw_Command | 0x10;\r
+                                  }\r
+\r
+                               /*****************************/\r
+                               /* Test if extern clock used */\r
+                               /*****************************/\r
+\r
+                               if (b_PCIInputClock == APCI1710_GATE_INPUT)\r
+                                  {\r
+                                  /****************************/\r
+                                  /* Set the 40 MHz selection */\r
+                                  /****************************/\r
+\r
+                                  dw_Command = dw_Command | 0x20;\r
+                                  }\r
+\r
+                               /*************************/\r
+                               /* Write the new command */\r
+                               /*************************/\r
+\r
+                       \r
+                               outl(dw_Command,devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
\r
+                               /*******************/\r
+                               /* Disable the tor */\r
+                               /*******************/\r
+                               \r
+                               outl(0,devpriv->s_BoardInfos.\r
+                                       ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+                               /*************************/\r
+                               /* Set the timer 1 value */\r
+                               /*************************/\r
+\r
+                       \r
+                               outl(ul_TimerValue,devpriv->s_BoardInfos.ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                               /*********************/\r
+                               /* Tor counter init. */\r
+                               /*********************/\r
+\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                               s_TorCounterModuleInfo.\r
+                               s_TorCounterInfo [b_TorCounter].\r
+                               b_TorCounterInit = 1;\r
+                               }\r
+                            else\r
+                               {\r
+                               /***********************************************/\r
+                               /* TOR version error for 40MHz clock selection */\r
+                               /***********************************************/\r
+\r                       DPRINTK("TOR version error for 40MHz clock selection\n");
+                               i_ReturnValue = -9;\r
+                               }\r
+                            }\r
+                         else\r
+                            {\r
+                            /**************************************************************/\r
+                            /* You can not used the 40MHz clock selection wich this board */\r
+                            /**************************************************************/\r
+\r                               DPRINTK("You can not used the 40MHz clock selection wich this board\n");
+                            i_ReturnValue = -8;\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         /**********************************/\r
+                         /* Base timing selection is wrong */\r
+                         /**********************************/\r
+\r                        DPRINTK("Base timing selection is wrong\n");
+                         i_ReturnValue = -7;\r
+                         }\r
+                      } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))\r
+                   else\r
+                      {\r
+                      /**********************************/\r
+                      /* Timing unit selection is wrong */\r
+                      /**********************************/\r
+\r                         DPRINTK("Timing unit selection is wrong\n");          
+                      i_ReturnValue = -6;\r
+                      } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))\r
+                   } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))\r
+                else\r
+                   {\r
+                   /*****************************************/\r
+                   /* The selected PCI input clock is wrong */\r
+                   /*****************************************/\r
+\r                      DPRINTK("The selected PCI input clock is wrong\n");
+                   i_ReturnValue = -5;\r
+                   } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))\r
+                } // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)\r
+             else\r
+                {\r
+                /**********************************/\r
+                /* Tor Counter selection is wrong */\r
+                /**********************************/\r
+\r               DPRINTK("Tor Counter selection is wrong\n");
+                i_ReturnValue = -4;\r
+                } // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a tor counter module */\r
+             /******************************************/\r
+\r            DPRINTK("The module is not a tor counter module\n");              
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+    data[0] = (UINT) ul_RealTimingInterval;\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_EnableTorCounter                      |\r
+|                                               (BYTE_ b_BoardHandle,        |\r
+|                                                BYTE_ b_ModulNbr,           |\r
+|                                               BYTE_ b_TorCounter,         |\r
+|                                               BYTE_ b_InputMode,          |\r
+|                                               BYTE_ b_ExternGate,         |\r
+|                                                BYTE_ b_CycleMode,          |\r
+|                                                BYTE_ b_InterruptEnable)    |\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable the tor counter (b_TorCounter) from selected    |\r
+|                    module (b_ModulNbr). You must calling the              |\r
+|                     "i_APCI1710_InitTorCounter" function be for you call   |\r
+|                    this function.                                         |\r
+|                     If you enable the tor counter interrupt, the           |\r
+|                     tor counter generate a interrupt after the timing cycle|\r
+|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |\r
+|                     Interrupt mask description chapter from this manual.   |\r
+|                     The b_CycleMode parameter determine if you will        |\r
+|                     measured a single or more cycle.                       |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |\r
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |\r
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1). |\r
+|                    BYTE_ b_InputMode    : Input signal level selection    |\r
+|                                              0 : Tor count each low level |\r
+|                                              1 : Tor count each high level|\r
+|                    BYTE_ b_ExternGate   : Extern gate action selection    |\r
+|                                              0 : Extern gate signal not   |\r
+|                                                  used                     |\r
+|                                              1 : Extern gate signal used. |\r
+|                                                  If you selected the      |\r
+|                                                  single mode, each high   |\r
+|                                                  level signal start the   |\r
+|                                                  counter.                 |\r
+|                                                  If you selected the      |\r
+|                                                  continuous mode, the     |\r
+|                                                  first high level signal  |\r
+|                                                  start the tor counter    |\r
+|                                                                           |\r
+|                                            APCI1710_TOR_QUADRUPLE _MODE : |\r
+|                                            In the quadruple mode, the edge|\r
+|                                            analysis circuit generates a   |\r
+|                                            counting pulse from each edge  |\r
+|                                            of 2 signals which are phase   |\r
+|                                            shifted in relation to each    |\r
+|                                            other.                         |\r
+|                                            The gate input is used for the |\r
+|                                            signal B                       |\r
+|                                                                           |\r
+|                                            APCI1710_TOR_DOUBLE_MODE:      |\r
+|                                            Functions in the same way as   |\r
+|                                            the quadruple mode, except that|\r
+|                                            only two of the four edges are |\r
+|                                            analysed per period.           |\r
+|                                            The gate input is used for the |\r
+|                                            signal B                       |\r
+|                                                                           |\r
+|                                            APCI1710_TOR_SIMPLE_MODE:      |\r
+|                                            Functions in the same way as   |\r
+|                                            the quadruple mode, except that|\r
+|                                            only one of the four edges is  |\r
+|                                            analysed per period.           |\r
+|                                            The gate input is used for the |\r
+|                                            signal B                       |\r
+|                                                                           |\r
+|                     BYTE_ b_CycleMode    : Selected the tor counter        |\r
+|                                            acquisition mode                |\r
+|                     BYTE_ b_InterruptEnable : Enable or disable the        |\r
+|                                               tor counter interrupt.       |\r
+|                                               APCI1710_ENABLE:             |\r
+|                                               Enable the tor counter       |\r
+|                                               interrupt                    |\r
+|                                               APCI1710_DISABLE:            |\r
+|                                               Disable the tor counter      |\r
+|                                               interrupt                    |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a tor counter module             |\r
+|                     -4: Tor counter selection is wrong                     |\r
+|                     -5: Tor counter not initialised see function           |\r
+|                         "i_APCI1710_InitTorCounter"                        |\r
+|                     -6: Tor input signal selection is wrong                |\r
+|                     -7: Extern gate signal mode is wrong                   |\r
+|                     -8: Tor counter acquisition mode cycle is wrong        |\r
+|                     -9: Interrupt parameter is wrong                       |\r
+|                     -10:Interrupt function not initialised.                |\r
+|                         See function "i_APCI1710_SetBoardIntRoutineX"      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_DisableTorCounter                     |\r
+|                                               (BYTE_  b_BoardHandle,       |\r
+|                                                BYTE_  b_ModulNbr,          |\r
+|                                               BYTE_  b_TorCounter)        |\r
++----------------------------------------------------------------------------+\r
+| Task              : Disable the tor counter (b_TorCounter) from selected   |\r
+|                    module (b_ModulNbr). If you disable the tor counter    |\r
+|                    after a start cycle occur and you restart the tor      |\r
+|                    counter witch the " i_APCI1710_EnableTorCounter"       |\r
+|                    function, the status register is cleared               |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |\r
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |\r
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1). |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a tor counter module             |\r
+|                     -4: Tor counter selection is wrong                     |\r
+|                     -5: Tor counter not initialised see function           |\r
+|                         "i_APCI1710_InitTorCounter"                        |\r
+|                     -6: Tor counter not enabled see function               |\r
+|                         "i_APCI1710_EnableTorCounter"                      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+
+INT  i_APCI1710_InsnWriteEnableDisableTorCounter (comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_Status;\r
+       DWORD dw_DummyRead;\r
+       DWORD dw_ConfigReg;\r
+       BYTE b_ModulNbr,b_Action;\r
+       BYTE b_TorCounter;\r
+       BYTE b_InputMode;\r
+       BYTE b_ExternGate;\r
+       BYTE b_CycleMode;\r
+       BYTE b_InterruptEnable;\r
+\r
+       b_ModulNbr                      =(BYTE) CR_AREF(insn->chanspec);\r
+       b_Action                        =(BYTE) data[0]; // enable or disable\r
+       b_TorCounter            =(BYTE) data[1];\r
+       b_InputMode                     =(BYTE) data[2] ;\r
+       b_ExternGate            =(BYTE) data[3] ;\r
+       b_CycleMode                     =(BYTE) data[4] ;\r
+       b_InterruptEnable       =(BYTE) data[5] ;\r
+       i_ReturnValue           = insn->n;      ;\r
+       devpriv->tsk_Current=current; // Save the current process task structure\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if tor counter */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER)\r
+             {\r
+             /**********************************/\r
+             /* Test the tor counter selection */\r
+             /**********************************/\r
+\r
+             if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+                {\r
+          switch(b_Action)// Enable or Disable\r
+                 {\r
+                 case APCI1710_ENABLE :\r
+                /***********************************/\r
+                /* Test if tor counter initialised */\r
+                /***********************************/\r
+\r
+               
+\r
+               dw_Status =inl(devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                if (dw_Status & 0x10)\r
+                   {\r
+                   /******************************/\r
+                   /* Test the input signal mode */\r
+                   /******************************/\r
+\r
+                   if (b_InputMode == 0                           ||\r
+                       b_InputMode == 1                                 ||\r
+                       b_InputMode == APCI1710_TOR_SIMPLE_MODE    ||\r
+                       b_InputMode == APCI1710_TOR_DOUBLE_MODE    ||\r
+                       b_InputMode == APCI1710_TOR_QUADRUPLE_MODE)\r
+                      {\r
+                      /************************************/\r
+                      /* Test the extern gate signal mode */\r
+                      /************************************/\r
+\r
+                     if (b_ExternGate == 0 || b_ExternGate == 1 || b_InputMode > 1)\r
+                         {\r
+                         /*********************************/\r
+                         /* Test the cycle mode parameter */\r
+                         /*********************************/\r
+\r
+                         if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))\r
+                            {\r
+                            /***************************/\r
+                            /* Test the interrupt flag */\r
+                            /***************************/\r
+\r
+                            if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))\r
+                               {\r
+\r
+                               
+                               
+                                  /***************************/\r
+                                  /* Save the interrupt mode */\r
+                                  /***************************/\r
+\r
+                                  devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                  s_TorCounterModuleInfo.\r
+                                  s_TorCounterInfo [b_TorCounter].\r
+                                  b_InterruptEnable = b_InterruptEnable;\r
+\r
+                                  /*******************/\r
+                                  /* Get the command */\r
+                                  /*******************/\r
+\r
+                                 
+                                  dw_ConfigReg = inl(devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                                  dw_ConfigReg = (dw_ConfigReg >> 4) & 0x30;\r
+\r
+                                  /********************************/\r
+                                  /* Test if not direct mode used */\r
+                                  /********************************/\r
+\r
+                                  if (b_InputMode > 1)\r
+                                     {\r
+                                     /*******************************/\r
+                                     /* Extern gate can not be used */\r
+                                     /*******************************/\r
+\r
+                                     b_ExternGate = 0;\r
+\r
+                                     /*******************************************/\r
+                                     /* Enable the extern gate for the Signal B */\r
+                                     /*******************************************/\r
+\r
+                                     dw_ConfigReg = dw_ConfigReg | 0x40;\r
+\r
+                                     /***********************/\r
+                                     /* Test if simple mode */\r
+                                     /***********************/\r
+\r
+                                     if (b_InputMode == APCI1710_TOR_SIMPLE_MODE)\r
+                                        {\r
+                                        /**************************/\r
+                                        /* Enable the sinple mode */\r
+                                        /**************************/\r
+\r
+                                        dw_ConfigReg = dw_ConfigReg | 0x780;\r
+\r
+                                        } // if (b_InputMode == APCI1710_TOR_SIMPLE_MODE)\r
+\r
+                                     /***********************/\r
+                                     /* Test if double mode */\r
+                                     /***********************/\r
+\r
+                                     if (b_InputMode == APCI1710_TOR_DOUBLE_MODE)\r
+                                        {\r
+                                        /**************************/\r
+                                        /* Enable the double mode */\r
+                                        /**************************/\r
+\r
+                                        dw_ConfigReg = dw_ConfigReg | 0x180;\r
+\r
+                                        } // if (b_InputMode == APCI1710_TOR_DOUBLE_MODE)\r
+\r
+                                     b_InputMode = 0;\r
+                                     } // if (b_InputMode > 1)\r
+\r
+                                  /*******************/\r
+                                  /* Set the command */\r
+                                  /*******************/\r
+\r
+                                  dw_ConfigReg = dw_ConfigReg | b_CycleMode | (b_InterruptEnable * 2) | (b_InputMode * 4) | (b_ExternGate * 8);\r
+\r
+                                  /*****************************/\r
+                                  /* Clear the status register */\r
+                                  /*****************************/\r
+\r
+                                \r
+                                     dw_DummyRead = inl(devpriv->s_BoardInfos.\r
+                                         ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                                  /***************************************/\r
+                                  /* Clear the interrupt status register */\r
+                                  /***************************************/\r
+\r
+                               \r
+                                   dw_DummyRead=inl(devpriv->s_BoardInfos.\r
+                                         ui_Address + 12 + (16 * b_TorCounter) + (64 * b_ModulNbr));  \r
+\r
+                                  /********************/\r
+                                  /* Set the commando */\r
+                                  /********************/\r
+\r
+
+                                       outl(dw_ConfigReg,devpriv->s_BoardInfos.\r
+                                               ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                                  /****************/\r
+                                  /* Set the gate */\r
+                                  /****************/\r
+                               
+\r
+                                       outl(1,devpriv->s_BoardInfos.\r
+                                          ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+                                  
+                               } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))\r
+                            else\r
+                               {\r
+                               /********************************/\r
+                               /* Interrupt parameter is wrong */\r
+                               /********************************/\r
+\r                              DPRINTK("Interrupt parameter is wrong\n");
+                               i_ReturnValue = -9;\r
+                               } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))\r
+                            } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))\r
+                         else\r
+                            {\r
+                            /***********************************************/\r
+                            /* Tor counter acquisition mode cycle is wrong */\r
+                            /***********************************************/\r
+\r                               DPRINTK("Tor counter acquisition mode cycle is wrong\n");
+                            i_ReturnValue = -8;\r
+                            } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))\r
+                         } // if (b_ExternGate >= 0 && b_ExternGate <= 1)\r
+                      else\r
+                         {\r
+                         /***********************************/\r
+                         /* Extern gate input mode is wrong */\r
+                         /***********************************/\r
+\r                        DPRINTK("Extern gate input mode is wrong\n");
+                         i_ReturnValue = -7;\r
+                         } // if (b_ExternGate >= 0 && b_ExternGate <= 1)\r
+                      } // if (b_InputMode >= 0 && b_InputMode <= 1)\r
+                   else\r
+                      {\r
+                      /***************************************/\r
+                      /* Tor input signal selection is wrong */\r
+                      /***************************************/\r
+\r                         DPRINTK("Tor input signal selection is wrong\n");
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /*******************************/\r
+                   /* Tor counter not initialised */\r
+                   /*******************************/\r
+\r                      DPRINTK("Tor counter not initialised\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                break;\r
+\r
+        case APCI1710_DISABLE :\r
+                        /***********************************/\r
+                /* Test if tor counter initialised */\r
+                /***********************************/\r
+               
+                       dw_Status = inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                /*******************************/\r
+                /* Test if counter initialised */\r
+                /*******************************/\r
+\r
+                if (dw_Status & 0x10)\r
+                   {\r
+                   /***************************/\r
+                   /* Test if counter enabled */\r
+                   /***************************/\r
+\r
+                   if (dw_Status & 0x1)\r
+                      {\r
+                      /****************************/\r
+                      /* Clear the interrupt mode */\r
+                      /****************************/\r
+                               devpriv->s_ModuleInfo [b_ModulNbr].\r
+                      s_TorCounterModuleInfo.\r
+                      s_TorCounterInfo [b_TorCounter].\r
+                      b_InterruptEnable = APCI1710_DISABLE;\r
+\r
+\r
+                      /******************/\r
+                      /* Clear the gate */\r
+                      /******************/\r
+                       \r
+                               outl(0,devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+                      } // if (dw_Status & 0x1)\r
+                   else\r
+                      {\r
+                      /***************************/\r
+                      /* Tor counter not enabled */\r
+                      /***************************/\r
+\r                              DPRINTK("Tor counter not enabled \n");
+                      i_ReturnValue = -6;\r
+                      } // if (dw_Status & 0x1)\r
+                   } // if (dw_Status & 0x10)\r
+                else\r
+                   {\r
+                   /*******************************/\r
+                   /* Tor counter not initialised */\r
+                   /*******************************/\r
+\r                      DPRINTK("Tor counter not initialised\n");       
+                   i_ReturnValue = -5;\r
+                   } // // if (dw_Status & 0x10)\r
+                \r
+\r
+\r
+                } // switch\r
+               } // if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+             else\r
+                {\r
+                /**********************************/\r
+                /* Tor counter selection is wrong */\r
+                /**********************************/\r
+\r                DPRINTK("Tor counter selection is wrong\n");  
+                i_ReturnValue = -4;\r
+                } // if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a tor counter module */\r
+             /******************************************/\r
+\r            DPRINTK("The module is not a tor counter module \n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error \n");   
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_GetTorCounterInitialisation           |\r
+|                                               (BYTE_     b_BoardHandle,    |\r
+|                                                BYTE_     b_ModulNbr,       |\r
+|                                               BYTE_     b_TorCounter,     |\r
+|                                               PBYTE_   pb_TimingUnit,     |\r
+|                                               PULONG_ pul_TimingInterval, |\r
+|                                               PBYTE_   pb_InputMode,      |\r
+|                                               PBYTE_   pb_ExternGate,     |\r
+|                                                PBYTE_   pb_CycleMode,      |\r
+|                                               PBYTE_   pb_Enable,         |\r
+|                                                PBYTE_   pb_InterruptEnable)|\r
++----------------------------------------------------------------------------+\r
+| Task              : Enable the tor counter (b_TorCounter) from selected    |\r
+|                    module (b_ModulNbr). You must calling the              |\r
+|                     "i_APCI1710_InitTorCounter" function be for you call   |\r
+|                    this function.                                         |\r
+|                     If you enable the tor counter interrupt, the           |\r
+|                     tor counter generate a interrupt after the timing cycle|\r
+|                     See function "i_APCI1710_SetBoardIntRoutineX" and the  |\r
+|                     Interrupt mask description chapter from this manual.   |\r
+|                     The b_CycleMode parameter determine if you will        |\r
+|                     measured a single or more cycle.                       |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |\r
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |\r
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1)\r
+\r
+       b_ModulNbr                      =       CR_AREF(insn->chanspec);\r
+       b_TorCounter            =       CR_CHAN(insn->chanspec);\r
+. |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_  pb_TimingUnit    : Base timing unit (0 to 4)   |\r
+|                                                 0 : ns                     |\r
+|                                                 1 : µs                     |\r
+|                                                 2 : ms                     |\r
+|                                                 3 : s                      |\r
+|                                                 4 : mn                     |\r
+|                     PULONG_ pul_TimingInterval : Base timing value.        |\r
+|                    PBYTE_ pb_InputMode        : Input signal level        |\r
+|                                                 selection                 |\r
+|                                              0 : Tor count each low level |\r
+|                                              1 : Tor count each high level|\r
+|                    PBYTE_ pb_ExternGate      : Extern gate action         |\r
+|                                                selection                  |\r
+|                                                0 : Extern gate signal not |\r
+|                                                    used                   |\r
+|                                                1 : Extern gate signal used|\r
+|                     PBYTE_ pb_CycleMode       : Tor counter acquisition    |\r
+|                                                mode                       |\r
+|                    PBYTE_ pb_Enable          : Indicate if the tor counter|\r
+|                                                is enabled or no           |\r
+|                                                0 : Tor counter disabled   |\r
+|                                                1 : Tor counter enabled    |\r
+|                     PBYTE_ pb_InterruptEnable : Enable or disable the      |\r
+|                                                 tor counter interrupt.     |\r
+|                                                 APCI1710_ENABLE:           |\r
+|                                                 Enable the tor counter     |\r
+|                                                 interrupt                  |\r
+|                                                 APCI1710_DISABLE:          |\r
+|                                                 Disable the tor counter    |\r
+|                                                 interrupt \r
+       pb_TimingUnit           =       (PBYTE) &data[0];\r
+       pul_TimingInterval      =  (PULONG) &data[1];\r
+       pb_InputMode            =       (PBYTE) &data[2];\r
+       pb_ExternGate           =       (PBYTE) &data[3];\r
+       pb_CycleMode            =       (PBYTE) &data[4];\r
+       pb_Enable                       =       (PBYTE) &data[5];\r
+       pb_InterruptEnable      =       (PBYTE) &data[6];\r
+                 |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a tor counter module             |\r
+|                     -4: Tor counter selection is wrong                     |\r
+|                     -5: Tor counter not initialised see function           |\r
+|                         "i_APCI1710_InitTorCounter"                        |\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+\r
+INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_Status;\r
+       BYTE     b_ModulNbr;\r
+       BYTE     b_TorCounter;\r
+       PBYTE   pb_TimingUnit;\r
+       PULONG pul_TimingInterval;\r
+       PBYTE   pb_InputMode;\r
+       PBYTE   pb_ExternGate;\r
+       PBYTE   pb_CycleMode;\r
+       PBYTE   pb_Enable;\r
+       PBYTE   pb_InterruptEnable      ;\r
+       \r
+       i_ReturnValue           =       insn->n;\r
+       b_ModulNbr                      =       CR_AREF(insn->chanspec);\r
+       b_TorCounter            =       CR_CHAN(insn->chanspec);\r
+\r
+       pb_TimingUnit           =       (PBYTE) &data[0];\r
+       pul_TimingInterval      =  (PULONG) &data[1];\r
+       pb_InputMode            =       (PBYTE) &data[2];\r
+       pb_ExternGate           =       (PBYTE) &data[3];\r
+       pb_CycleMode            =       (PBYTE) &data[4];\r
+       pb_Enable                       =       (PBYTE) &data[5];\r
+       pb_InterruptEnable      =       (PBYTE) &data[6];\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if tor counter */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER)\r
+             {\r
+             /**********************************/\r
+             /* Test the tor counter selection */\r
+             /**********************************/\r
+\r
+             if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+                {\r
+          \r
+                 \r
+                /***********************************/\r
+                /* Test if tor counter initialised */\r
+                /***********************************/\r
+\r
+               
+                       dw_Status = inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+\r
+                if (dw_Status & 0x10)\r
+                   {\r
+                   *pb_Enable = dw_Status & 1;\r
+\r
+                   /********************/\r
+                   /* Get the commando */\r
+                   /********************/\r
+\r
+               
+                        dw_Status=inl(devpriv->s_BoardInfos.\r
+                          ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                   *pb_CycleMode       = (BYTE) ((dw_Status >> 4) & 1);\r
+                   *pb_InterruptEnable = (BYTE) ((dw_Status >> 5) & 1);\r
+\r
+                   /******************************************************/\r
+                   /* Test if extern gate used for clock or for signal B */\r
+                   /******************************************************/\r
+\r
+                   if (dw_Status & 0x600)\r
+                      {\r
+                      /*****************************************/\r
+                      /* Test if extern gate used for signal B */\r
+                      /*****************************************/\r
+\r
+                      if (dw_Status & 0x400)\r
+                         {\r
+                         /***********************/\r
+                         /* Test if simple mode */\r
+                         /***********************/\r
+\r
+                         if ((dw_Status & 0x7800) == 0x7800)\r
+                            {\r
+                            *pb_InputMode = APCI1710_TOR_SIMPLE_MODE;\r
+                            }\r
+\r
+                         /***********************/\r
+                         /* Test if double mode */\r
+                         /***********************/\r
+\r
+                         if ((dw_Status & 0x7800) == 0x1800)\r
+                            {\r
+                            *pb_InputMode = APCI1710_TOR_DOUBLE_MODE;\r
+                            }\r
+\r
+                         /**************************/\r
+                         /* Test if quadruple mode */\r
+                         /**************************/\r
+\r
+                         if ((dw_Status & 0x7800) == 0x0000)\r
+                            {\r
+                            *pb_InputMode = APCI1710_TOR_QUADRUPLE_MODE;\r
+                            }\r
+                         } // if (dw_Status & 0x400)\r
+                      else\r
+                         {\r
+                         *pb_InputMode = 1;\r
+                         } // // if (dw_Status & 0x400)\r
+\r
+                      /************************/\r
+                      /* Extern gate not used */\r
+                      /************************/\r
+\r
+                      *pb_ExternGate = 0;\r
+                      } // if (dw_Status & 0x600)\r
+                   else\r
+                      {\r
+                      *pb_InputMode  = (BYTE) ((dw_Status >> 6) & 1);\r
+                      *pb_ExternGate = (BYTE) ((dw_Status >> 7) & 1);\r
+                      } // if (dw_Status & 0x600)\r
+\r
+                   *pb_TimingUnit     = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                        s_TorCounterModuleInfo.\r
+                                        s_TorCounterInfo [b_TorCounter].\r
+                                        b_TimingUnit;\r
+\r
+                   *pul_TimingInterval = devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                         s_TorCounterModuleInfo.\r
+                                         s_TorCounterInfo [b_TorCounter].\r
+                                         ul_RealTimingInterval;\r
+                   }\r
+                else\r
+                   {\r
+                   /*******************************/\r
+                   /* Tor counter not initialised */\r
+                   /*******************************/\r
+\r                      DPRINTK("Tor counter not initialised\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                  \r
+                } // if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+             else\r
+                {\r
+                /**********************************/\r
+                /* Tor counter selection is wrong */\r
+                /**********************************/\r
+\r               DPRINTK("Tor counter selection is wrong \n");
+                i_ReturnValue = -4;\r
+                } // if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a tor counter module */\r
+             /******************************************/\r
+\r             DPRINTK("The module is not a tor counter module\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_ReadTorCounterValue                   |\r
+|                               (BYTE_     b_BoardHandle,                    |\r
+|                                BYTE_     b_ModulNbr,                       |\r
+|                               BYTE_     b_TorCounter,                     |\r
+|                                UINT_    ui_TimeOut,                        |\r
+|                                PBYTE_   pb_TorCounterStatus,               |\r
+|                                PULONG_ pul_TorCounterValue)                |\r
++----------------------------------------------------------------------------+\r
+| Task         case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter \r
+(b_TorCounter) status (pb_TorCounterStatus) from selected tor counter        |\r
+|                    module (b_ModulNbr). \r
+               \r
+                                case APCI1710_TOR_GETCOUNTERVALUE :\r
+  Return the tor counter (b_TorCounter) status           |\r
+|                    (pb_TorCounterStatus) and the timing value             |\r
+|                    (pul_TorCounterValue) after a conting cycle stop       |\r
+|                     from selected tor counter module (b_ModulNbr).         |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle  : Handle of board APCI-1710       |\r
+|                     BYTE_ b_ModulNbr     : Selected module number (0 to 3) |\r
+|                     BYTE_ b_TorCounter   : Tor counter selection (0 or 1).\r
+       b_ModulNbr    = CR_AREF(insn->chanspec);\r
+       b_ReadType    = (BYTE) data[0]; \r
+       b_TorCounter  = (BYTE) data[1];\r
+       ui_TimeOut        = (UINT) data[2]; |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : PBYTE_  pb_TorCounterStatus : Return the tor counter   |\r
+|                                                    status.                 |\r
+|                                               0 : Conting cycle not started|\r
+|                                                   Software gate not set.   |\r
+|                                               1 : Conting cycle started.   |\r
+|                                                   Software gate set.       |\r
+|                                               2 : Conting cycle stopped.   |\r
+|                                                   The conting cycle is     |\r
+|                                                   terminate.               |\r
+|                                               3 : A overflow occur. You    |\r
+|                                                   must change the base     |\r
+|                                                   timing witch the         |\r
+|                                                   function                 |\r
+|                                                 "i_APCI1710_InitTorCounter"|\r
+|                                              4 : Timeeout occur           |\r
+|                     PULONG  pul_TorCounterValue  : Tor counter value.  \r
+       pb_TorCounterStatus=(PBYTE) &data[0];\r
+       pul_TorCounterValue=(PULONG) &data[1];    |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :  0: No error                                           |\r
+|                     -1: The handle parameter of the board is wrong         |\r
+|                     -2: Module selection wrong                             |\r
+|                     -3: The module is not a tor counter module             |\r
+|                     -4: Tor counter selection is wrong                     |\r
+|                     -5: Tor counter not initialised see function           |\r
+|                         "i_APCI1710_InitTorCounter"                        |\r
+|                     -6: Tor counter not enabled see function               |\r
+|                         "i_APCI1710_EnableTorCounter"                      |\r
+|                     -7: Timeout parameter is wrong (0 to 65535)            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD  dw_Status;\r
+       DWORD  dw_TimeOut = 0;\r
+\r
+       BYTE    b_ModulNbr;\r
+       BYTE    b_TorCounter;\r
+       BYTE    b_ReadType;
+       UINT    ui_TimeOut;\r
+       PBYTE   pb_TorCounterStatus;\r
+       PULONG  pul_TorCounterValue;\r
+\r
+       i_ReturnValue = insn->n;\r
+       b_ModulNbr    = CR_AREF(insn->chanspec);\r
+       b_ReadType    = (BYTE) data[0]; \r
+       b_TorCounter  = (BYTE) data[1];\r
+       ui_TimeOut        = (UINT) data[2];\r
+       pb_TorCounterStatus=(PBYTE) &data[0];\r
+       pul_TorCounterValue=(PULONG) &data[1];\r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+
+
+        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;
+        } 
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /***********************/\r
+          /* Test if tor counter */\r
+          /***********************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER)\r
+             {\r
+             /**********************************/\r
+             /* Test the tor counter selection */\r
+             /**********************************/\r
+\r
+             if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+                {\r
+                /***********************************/\r
+                /* Test if tor counter initialised */\r
+                /***********************************/\r
+\r
+               \r
+
+                       dw_Status=inl(devpriv->s_BoardInfos.\r
+                       ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                /*******************************/\r
+                /* Test if counter initialised */\r
+                /*******************************/\r
+\r
+                if (dw_Status & 0x10)\r
+                   {\r
+                   /***************************/\r
+                   /* Test if counter enabled */\r
+                   /***************************/\r
+\r
+                   if (dw_Status & 0x1)\r
+                      {\r
+                  \r
+                               switch(b_ReadType)\r
+                               {\r
+
+                               case APCI1710_TOR_GETPROGRESSSTATUS:\r
+                       /*******************/\r
+                      /* Read the status */\r
+                      /*******************/\r
+               \r
+                                       dw_Status=inl(devpriv->s_BoardInfos.\r
+                              ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                      dw_Status = dw_Status & 0xF;\r
+\r
+                      /*****************/\r
+                      /* Test if start */\r
+                      /*****************/\r
+\r
+                      if (dw_Status & 1)\r
+                         {\r
+                         if (dw_Status & 2)\r
+                            {\r
+                            if (dw_Status & 4)\r
+                               {\r
+                               /************************/\r
+                               /* Tor counter owerflow */\r
+                               /************************/\r
+\r
+                               *pb_TorCounterStatus = 3;\r
+                               }\r
+                            else\r
+                               {\r
+                               /***********************/\r
+                               /* Tor counter started */\r
+                               /***********************/\r
+\r
+                               *pb_TorCounterStatus = 2;\r
+                               }\r
+                            }\r
+                         else\r
+                            {\r
+                            /***********************/\r
+                            /* Tor counter started */\r
+                            /***********************/\r
+\r
+                            *pb_TorCounterStatus = 1;\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         /***************************/\r
+                         /* Tor counter not started */\r
+                         /***************************/\r
+\r
+                         *pb_TorCounterStatus = 0;\r
+                         }\r
+                        break;\r
+\r
+                case APCI1710_TOR_GETCOUNTERVALUE :\r
+                               \r
+                      /*****************************/\r
+                      /* Test the timout parameter */\r
+                      /*****************************/\r
+\r
+                      if ((ui_TimeOut >= 0) && (ui_TimeOut <= 65535UL))\r
+                         {\r
+                         for (;;)\r
+                            {\r
+                            /*******************/\r
+                            /* Read the status */\r
+                            /*******************/\r
+                               
+                               dw_Status=inl(devpriv->s_BoardInfos.\r
+                                   ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+                            /********************/\r
+                            /* Test if overflow */\r
+                            /********************/\r
+\r
+                            if ((dw_Status & 4) == 4)\r
+                               {\r
+                               /******************/\r
+                               /* Overflow occur */\r
+                               /******************/\r
+\r
+                               *pb_TorCounterStatus = 3;\r
+\r
+                               /******************/\r
+                               /* Read the value */\r
+                               /******************/\r
+\r
+                       \r
+                               *pul_TorCounterValue=inl(devpriv->s_BoardInfos.\r
+                                      ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+                               break;\r
+                               } // if ((dw_Status & 4) == 4)\r
+                            else\r
+                               {\r
+                               /*******************************/\r
+                               /* Test if measurement stopped */\r
+                               /*******************************/\r
+\r
+                               if ((dw_Status & 2) == 2)\r
+                                  {\r
+                                  /***********************/\r
+                                  /* A stop signal occur */\r
+                                  /***********************/\r
+\r
+                                  *pb_TorCounterStatus = 2;\r
+\r
+                                  /******************/\r
+                                  /* Read the value */\r
+                                  /******************/\r
+\r\r
+                                    *pul_TorCounterValue=inl(devpriv->s_BoardInfos.\r
+                                         ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr));\r
+\r
+                                  break;\r
+                                  } // if ((dw_Status & 2) == 2)\r
+                               else\r
+                                  {\r
+                                  /*******************************/\r
+                                  /* Test if measurement started */\r
+                                  /*******************************/\r
+\r
+                                  if ((dw_Status & 1) == 1)\r
+                                     {\r
+                                     /************************/\r
+                                     /* A start signal occur */\r
+                                     /************************/\r
+\r
+                                     *pb_TorCounterStatus = 1;\r
+                                     } // if ((dw_Status & 1) == 1)\r
+                                  else\r
+                                     {\r
+                                     /***************************/\r
+                                     /* Measurement not started */\r
+                                     /***************************/\r
+\r
+                                     *pb_TorCounterStatus = 0;\r
+                                     } // if ((dw_Status & 1) == 1)\r
+                                  } // if ((dw_Status & 2) == 2)\r
+                               } // if ((dw_Status & 8) == 8)\r
+\r
+                            if (dw_TimeOut == ui_TimeOut)\r
+                               {\r
+                               /*****************/\r
+                               /* Timeout occur */\r
+                               /*****************/\r
+\r
+                               break;\r
+                               }\r
+                            else\r
+                               {\r
+                               /*************************/\r
+                               /* Increment the timeout */\r
+                               /*************************/\r
+\r
+                               dw_TimeOut = dw_TimeOut + 1;\r
+                       \r
+                               mdelay(1000);\r
+                               }\r
+                            } // for (;;)\r
+\r
+                         /*************************/\r
+                         /* Test if timeout occur */\r
+                         /*************************/\r
+\r
+                         if ((*pb_TorCounterStatus != 3) && (dw_TimeOut == ui_TimeOut) && (ui_TimeOut != 0))\r
+                            {\r
+                            /*****************/\r
+                            /* Timeout occur */\r
+                            /*****************/\r
+\r
+                            *pb_TorCounterStatus = 4;\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         /******************************/\r
+                         /* Timeout parameter is wrong */\r
+                         /******************************/\r
+\r                     DPRINTK("Timeout parameter is wrong\n");
+                         i_ReturnValue = -7;\r
+                         }\r
+                          break;\r
+
+           
+             default:\r
+                                printk("Inputs wrong\n");\r
+                       } // switch end\r
+                      } // if (dw_Status & 0x1)\r
+                   else\r
+                      {\r
+                      /***************************/\r
+                      /* Tor counter not enabled */\r
+                      /***************************/\r
+\r                         DPRINTK("Tor counter not enabled\n");
+                      i_ReturnValue = -6;\r
+                      } // if (dw_Status & 0x1)\r
+                   }\r
+                else\r
+                   {\r
+                   /*******************************/\r
+                   /* Tor counter not initialised */\r
+                   /*******************************/\r
+\r                      DPRINTK("Tor counter not initialised\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                } // if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+             else\r
+                {\r
+                /**********************************/\r
+                /* Tor counter selection is wrong */\r
+                /**********************************/\r
+\r                DPRINTK("Tor counter selection is wrong\n");
+                i_ReturnValue = -4;\r
+                } // if (b_TorCounter >= 0 && b_TorCounter <= 1)\r
+             }\r
+          else\r
+             {\r
+             /******************************************/\r
+             /* The module is not a tor counter module */\r
+             /******************************************/\r
+\r             DPRINTK("The module is not a tor counter module\n");     
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");   
+          i_ReturnValue = -2;\r
+          }\r
+\r       
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Tor.h b/comedi/drivers/addi-data/APCI1710_Tor.h
new file mode 100644 (file)
index 0000000..b29d22c
--- /dev/null
@@ -0,0 +1,56 @@
+\r
+\r
+\r\r
+   #define APCI1710_30MHZ           30\r
+   #define APCI1710_33MHZ           33\r
+   #define APCI1710_40MHZ           40\r
+
+\r
+
+   #define APCI1710_GATE_INPUT 10\r
+
+\r
+#define APCI1710_TOR_SIMPLE_MODE    2\r
+#define APCI1710_TOR_DOUBLE_MODE    3\r
+#define APCI1710_TOR_QUADRUPLE_MODE 4\r
+\r
+
+#define APCI1710_SINGLE     0\r
+#define APCI1710_CONTINUOUS 1\r
+
+\r
+#define APCI1710_TOR_GETPROGRESSSTATUS 0\r
+#define APCI1710_TOR_GETCOUNTERVALUE   1
+#define APCI1710_TOR_READINTERRUPT      2\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       TOR_COUNTER INISIALISATION FUNCTION                  |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+INT   i_APCI1710_InsnConfigInitTorCounter(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+\r
+
+\r
+\r
+\r
+\r
+INT  i_APCI1710_InsnWriteEnableDisableTorCounter (comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+
+\r
+INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       TOR_COUNTER READ FUNCTION                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+
+\r
+INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
diff --git a/comedi/drivers/addi-data/APCI1710_Ttl.c b/comedi/drivers/addi-data/APCI1710_Ttl.c
new file mode 100644 (file)
index 0000000..1307e61
--- /dev/null
@@ -0,0 +1,961 @@
+
+
+
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-----------------------------------------------------------------------+\r
+  | Project   : API APCI1710      |     Compiler   : BORLANDC/MICROSOFT C |\r
+  | Module name : TTL.C           |     Version    : 3.1     / 6.0        |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author    : S.WEBER           |     Date       : 04.06.98             |\r
+  +-----------------------------------------------------------------------+\r
+  | Description :   APCI-1710 TTL I/O module                              |\r
+  |                                                                       |\r
+  |                                                                       |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +-----------------------------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  | 13/05/98 | S. Weber  | TTL digital input / output implementation      |\r
+  |----------|-----------|------------------------------------------------|\r
+  | 08/05/00 | Guinot C  | - 0400/0228 All Function in RING 0             |\r
+  |          |           |   available                                    |\r
+  +-----------------------------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +-----------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+#include "APCI1710_Ttl.h"\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_InitTTLIODirection                    |\r
+|                               (BYTE_    b_BoardHandle,                     |\r
+|                               BYTE_    b_ModulNbr,                        |\r
+|                               BYTE_    b_PortAMode,                       |\r
+|                               BYTE_    b_PortBMode,                       |\r
+|                               BYTE_    b_PortCMode,                       |\r
+|                               BYTE_    b_PortDMode)                       |\r
++----------------------------------------------------------------------------+\r
+| Task           APCI1710_TTL_INIT (using defaults)   : Configure the TTL I/O operating mode from selected     |\r
+|                     module  (b_ModulNbr). You must calling this function be|\r
+|                     for you call any other function witch access of TTL.   |\r
+                                APCI1710_TTL_INITDIRECTION(user inputs for direction) \r
+\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|\r
+|                     BYTE_ b_ModulNbr            : Module number to         |\r
+|                                                   configure (0 to 3)  \r
+               b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);\r
+               b_InitType = (BYTE) data[0];\r
+               b_PortAMode     = (BYTE) data[1];\r
+               b_PortBMode = (BYTE) data[2];\r
+               b_PortCMode = (BYTE) data[3];\r
+               b_PortDMode     = (BYTE) data[4];|\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a TTL module                      |\r
+|                   -4: Function not available for this version             |\r
+|                   -5: Port A mode selection is wrong                      |\r
+|                   -6: Port B mode selection is wrong                      |\r
+|                   -7: Port C mode selection is wrong                      |\r
+|                   -8: Port D mode selection is wrong                      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+INT   i_APCI1710_InsnConfigInitTTLIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data) \r
+       {\r
+               INT             i_ReturnValue = 0;\r
+               BYTE    b_ModulNbr;\r
+               BYTE    b_InitType;\r
+               BYTE    b_PortAMode;\r
+               BYTE    b_PortBMode;\r
+               BYTE    b_PortCMode;\r
+               BYTE    b_PortDMode;\r
+\r
+               b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);\r
+               b_InitType = (BYTE) data[0];\r
+               i_ReturnValue = insn->n;\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+                                                                                                                                                                          \r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /**************************/\r
+          /* Test if TTL I/O module */\r
+          /**************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TTL_IO)\r
+             {\r
+            switch(b_InitType)\r
+                       {\r
+                       case APCI1710_TTL_INIT :\r
+\r
+                       devpriv->s_ModuleInfo [b_ModulNbr].\r
+             s_TTLIOInfo.b_TTLInit = 1;\r
+\r
+             /***************************/\r
+             /* Set TTL port A to input */\r
+             /***************************/\r
+\r
+             devpriv->s_ModuleInfo [b_ModulNbr].\r
+             s_TTLIOInfo.\r
+             b_PortConfiguration [0] = 0;\r
+\r
+             /***************************/\r
+             /* Set TTL port B to input */\r
+             /***************************/\r
+\r
+             devpriv->s_ModuleInfo [b_ModulNbr].\r
+             s_TTLIOInfo.\r
+             b_PortConfiguration [1] = 0;\r
+\r
+             /***************************/\r
+             /* Set TTL port C to input */\r
+             /***************************/\r
+\r
+             devpriv->s_ModuleInfo [b_ModulNbr].\r
+             s_TTLIOInfo.\r
+             b_PortConfiguration [2] = 0;\r
+\r
+             /****************************/\r
+             /* Set TTL port D to output */\r
+             /****************************/\r
+\r
+             devpriv->s_ModuleInfo [b_ModulNbr].\r
+             s_TTLIOInfo.\r
+             b_PortConfiguration [3] = 1;\r
+\r
+             /*************************/\r
+             /* Set the configuration */\r
+             /*************************/\r
+                       
+                 outl(0x8,devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr));\r
+                       break;\r
+\r
+\r
+                       case APCI1710_TTL_INITDIRECTION :\r
+\r
+                       b_PortAMode     = (BYTE) data[1];\r
+                       b_PortBMode = (BYTE) data[2];\r
+                       b_PortCMode = (BYTE) data[3];\r
+                       b_PortDMode     = (BYTE) data[4];\r
+\r
+             /********************/\r
+             /* Test the version */\r
+             /********************/\r
+\r
+             if ((devpriv->s_BoardInfos.\r
+                  dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230)\r
+                {\r
+                /************************/\r
+                /* Test the port A mode */\r
+                /************************/\r
+\r
+                if ((b_PortAMode == 0) || (b_PortAMode == 1))\r
+                   {\r
+                   /************************/\r
+                   /* Test the port B mode */\r
+                   /************************/\r
+\r
+                   if ((b_PortBMode == 0) || (b_PortBMode == 1))\r
+                      {\r
+                      /************************/\r
+                      /* Test the port C mode */\r
+                      /************************/\r
+\r
+                      if ((b_PortCMode == 0) || (b_PortCMode == 1))\r
+                         {\r
+                         /************************/\r
+                         /* Test the port D mode */\r
+                         /************************/\r
+\r
+                         if ((b_PortDMode == 0) || (b_PortDMode == 1))\r
+                            {\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_TTLIOInfo.\r
+                            b_TTLInit = 1;\r
+\r
+                            /***********************/\r
+                            /* Set TTL port A mode */\r
+                            /***********************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_TTLIOInfo.\r
+                            b_PortConfiguration [0] = b_PortAMode;\r
+\r
+                            /***********************/\r
+                            /* Set TTL port B mode */\r
+                            /***********************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_TTLIOInfo.\r
+                            b_PortConfiguration [1] = b_PortBMode;\r
+\r
+                            /***********************/\r
+                            /* Set TTL port C mode */\r
+                            /***********************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_TTLIOInfo.\r
+                            b_PortConfiguration [2] = b_PortCMode;\r
+\r
+                            /***********************/\r
+                            /* Set TTL port D mode */\r
+                            /***********************/\r
+\r
+                            devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_TTLIOInfo.\r
+                            b_PortConfiguration [3] = b_PortDMode;\r
+\r
+                            /*************************/\r
+                            /* Set the configuration */\r
+                            /*************************/\r
+\r
+                            
+                                outl((b_PortAMode << 0) |\r
+                                         (b_PortBMode << 1) |\r
+                                         (b_PortCMode << 2) |\r
+                                         (b_PortDMode << 3),devpriv->s_BoardInfos.\r
+                                    ui_Address + 20 + (64 * b_ModulNbr));\r
+                            }\r
+                         else\r
+                            {\r
+                            /**********************************/\r
+                            /* Port D mode selection is wrong */\r
+                            /**********************************/\r
+\r                        DPRINTK("Port D mode selection is wrong\n");
+                            i_ReturnValue = -8;\r
+                            }\r
+                         }\r
+                      else\r
+                         {\r
+                         /**********************************/\r
+                         /* Port C mode selection is wrong */\r
+                         /**********************************/\r
+\r                        DPRINTK("Port C mode selection is wrong\n");
+                         i_ReturnValue = -7;\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /**********************************/\r
+                      /* Port B mode selection is wrong */\r
+                      /**********************************/\r
+\r                         DPRINTK("Port B mode selection is wrong\n");
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /**********************************/\r
+                   /* Port A mode selection is wrong */\r
+                   /**********************************/\r
+\r                      DPRINTK("Port A mode selection is wrong\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*******************************************/\r
+                /* Function not available for this version */\r
+                /*******************************************/\r
+\r               DPRINTK("Function not available for this version\n");
+                i_ReturnValue = -4;\r
+                }\r
+                 break;\r
+\r                DPRINTK("\n");
+                 default:\r
+                         printk("Bad Config Type\n");\r
+                 }// switch end\r
+             }\r
+          else\r
+             {\r
+             /**********************************/\r
+             /* The module is not a TTL module */\r
+             /**********************************/\r
+\r            DPRINTK("The module is not a TTL module\n");
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r          DPRINTK("Module number error\n");
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                            INPUT FUNCTIONS                                 |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_   i_APCI1710_ReadTTLIOChannelValue               |\r
+|                                       (BYTE_     b_BoardHandle,            |\r
+|                                        BYTE_     b_ModulNbr,               |\r
+|                                        BYTE_     b_SelectedPort,           |\r
+|                                        BYTE_     b_InputChannel,           |\r
+|                                        PBYTE_   pb_ChannelStatus)          |\r
++----------------------------------------------------------------------------+\r
+| Task              : Read the status from selected TTL digital input        |\r
+|                     (b_InputChannel) \r
++----------------------------------------------------------------------------+\r
+| Task              : Read the status from digital input port                |\r
+|                     (b_SelectedPort) from selected TTL module (b_ModulNbr) |\r
++----------------------------------------------------------------------------+ \r
+
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle         : Handle of board APCI-1710|\r
+|                     BYTE_ b_ModulNbr            : Module number to         |\r
+|                                                   configure (0 to 7)       |\r
+|                     BYTE_ b_SelectedPort,       : Selection from TTL I/O   |\r
+|                                                   port (0 to 2)            |\r
+|                                                      0 : Port A selection  |\r
+|                                                      1 : Port B selection  |\r
+|                                                      2 : Port C selection  |\r
+|                                                      3 : Port D selection  |\r
+|                     BYTE_ b_InputChannel        : Selection from digital   |\r
+|                                                   input ( 0 to 2)        \r
+APCI1710_TTL_READCHANNEL  \r
+       b_ModulNbr        = CR_AREF(insn->chanspec);\r
+       b_SelectedPort= CR_RANGE(insn->chanspec);\r
+       b_InputChannel= CR_CHAN(insn->chanspec);\r
+       b_ReadType        = (BYTE) data[0];\r
+\r
+ APCI1710_TTL_READPORT|\r
+       b_ModulNbr        = CR_AREF(insn->chanspec);\r
+       b_SelectedPort= CR_RANGE(insn->chanspec);\r
+       b_ReadType        = (BYTE) data[0];\r
+\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : data[0]\r
+\r
+       PBYTE_  pb_ChannelStatus    : Digital input channel    |\r
+|                                                   status                   |\r
+|                                                   0 : Channle is not active|\r
+|                                                   1 : Channle is active    |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a TTL module                      |\r
+|                    -4: The selected TTL input port is wrong                |\r
+|                    -5: The selected TTL digital input is wrong             |\r
+|                    -6: TTL I/O not initialised                             |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+INT  i_APCI1710_InsnBitsReadTTLIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;\r
+       DWORD dw_StatusReg;\r
+       BYTE    b_ModulNbr;\r
+       BYTE    b_SelectedPort;\r
+       BYTE    b_InputChannel;\r
+       BYTE    b_ReadType;\r
+       PBYTE   pb_ChannelStatus;\r
+       PBYTE  pb_PortValue;\r
+       
+               \r
+       i_ReturnValue = insn->n;\r
+       b_ReadType        = (BYTE) data[0];\r
+       b_ModulNbr        = CR_AREF(insn->chanspec);\r
+       b_SelectedPort= CR_RANGE(insn->chanspec);\r
+       b_InputChannel= CR_CHAN(insn->chanspec);\r
+\r
+       \r
+       \r
+       \r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /**************************/\r
+          /* Test if TTL I/O module */\r
+          /**************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TTL_IO)\r
+             {\r
+                  switch(b_ReadType)\r
+                  {\r
+\r
+                  case APCI1710_TTL_READCHANNEL:\r
+                       pb_ChannelStatus = (PBYTE) &data[0];\r
+             /********************************/\r
+             /* Test the TTL I/O port number */\r
+             /********************************/\r
+\r
+             if ((((b_SelectedPort >= 0) && (b_SelectedPort <= 2)) && ((devpriv->s_BoardInfos.\r
+                                                                        dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130)) ||\r
+                 (((b_SelectedPort >= 0) && (b_SelectedPort <= 3)) && ((devpriv->s_BoardInfos.\r
+                                                                        dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230)))\r
+                {\r
+                /******************************************/\r
+                /* Test the digital imnput channel number */\r
+                /******************************************/\r
+\r
+                if ((((b_InputChannel >= 0) && (b_InputChannel <= 7)) && (b_SelectedPort < 3)) ||\r
+                    (((b_InputChannel >= 0) && (b_InputChannel <= 1)) && (b_SelectedPort == 3)))\r
+                   {\r
+                   /******************************************/\r
+                   /* Test if the TTL I/O module initialised */\r
+                   /******************************************/\r
+\r
+                   if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                       s_TTLIOInfo.\r
+                       b_TTLInit == 1)\r
+                      {\r
+                      /***********************************/\r
+                      /* Test if TTL port used for input */\r
+                      /***********************************/\r
+\r
+                      if (((devpriv->s_BoardInfos.\r
+                            dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130) ||\r
+                          (((devpriv->s_BoardInfos.\r
+                             dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230) &&\r
+                           (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                            s_TTLIOInfo.\r
+                            b_PortConfiguration [b_SelectedPort] == 0)))\r
+                         {\r
+                         /**************************/\r
+                         /* Read all digital input */\r
+                         /**************************/\r
+                       
+                               dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+\r
+                         *pb_ChannelStatus = (BYTE) ((dw_StatusReg >> (8 * b_SelectedPort)) >>
+ b_InputChannel) & 1;\r
+                         }\r
+                      else\r
+                         {\r
+                         /*******************************/\r
+                         /* Selected TTL I/O port error */\r
+                         /*******************************/\r
+\r                        DPRINTK("Selected TTL I/O port error\n");
+                         i_ReturnValue = -4;\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /***************************/\r
+                      /* TTL I/O not initialised */\r
+                      /***************************/\r
+\r                         DPRINTK("TTL I/O not initialised\n");        
+                      i_ReturnValue = -6;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /********************************/\r
+                   /* Selected digital input error */\r
+                   /********************************/\r
+\r                      DPRINTK("Selected digital input error\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*******************************/\r
+                /* Selected TTL I/O port error */\r
+                /*******************************/\r
+\r                DPRINTK("Selected TTL I/O port error\n");
+                i_ReturnValue = -4;\r
+                }\r
+                 break;\r
+\r
+                 case APCI1710_TTL_READPORT:\r
+                         pb_PortValue = (PBYTE) &data[0];\r
+                         /********************************/\r
+                         /* Test the TTL I/O port number */\r
+                         /********************************/\r
+\r
+             if ((((b_SelectedPort >= 0) && (b_SelectedPort <= 2)) && ((devpriv->s_BoardInfos.\r
+                                                                        dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130)) ||\r
+                 (((b_SelectedPort >= 0) && (b_SelectedPort <= 3)) && ((devpriv->s_BoardInfos.\r
+                                                                        dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230)))\r
+                {\r
+                /******************************************/\r
+                /* Test if the TTL I/O module initialised */\r
+                /******************************************/\r
+\r
+                if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                    s_TTLIOInfo.\r
+                    b_TTLInit == 1)\r
+                   {\r
+                   /***********************************/\r
+                   /* Test if TTL port used for input */\r
+                   /***********************************/\r
+\r
+                   if (((devpriv->s_BoardInfos.\r
+                         dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130) ||\r
+                       (((devpriv->s_BoardInfos.\r
+                          dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230) &&\r
+                        (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                         s_TTLIOInfo.\r
+                         b_PortConfiguration [b_SelectedPort] == 0)))\r
+                       {\r
+                      /**************************/\r
+                      /* Read all digital input */\r
+                      /**************************/\r
+                               
+                               dw_StatusReg=inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));\r
+\r
+                      *pb_PortValue = (BYTE) ((dw_StatusReg >> (8 * b_SelectedPort)) & 0xFF);\r
+                      }\r
+                   else\r
+                      {\r
+                      /*******************************/\r
+                      /* Selected TTL I/O port error */\r
+                      /*******************************/\r
+\r                      DPRINTK("Selected TTL I/O port error\n");
+                      i_ReturnValue = -4;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /***************************/\r
+                   /* TTL I/O not initialised */\r
+                   /***************************/\r
+\r                      DPRINTK("TTL I/O not initialised\n");
+                   i_ReturnValue = -5;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /*******************************/\r
+                /* Selected TTL I/O port error */\r
+                /*******************************/\r
+\r               DPRINTK("Selected TTL I/O port error\n");      
+                i_ReturnValue = -4;\r
+                }\r
+                 break;\r
+\r
+                 default:\r
+                          printk("Bad ReadType\n");\r
+                  \r
+                  }//End Switch\r
+             }\r
+          else\r
+             {\r
+             /**********************************/\r
+             /* The module is not a TTL module */\r
+             /**********************************/\r
+\r            DPRINTK("The module is not a TTL module\n");      
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");    
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
+
+/*
++----------------------------------------------------------------------------+
+| 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);
+       }
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                            OUTPUT FUNCTIONS                                |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function Name     : _INT_ i_APCI1710_SetTTLIOChlOn                         |\r
+|                               (BYTE_           b_BoardHandle,              |\r
+|                                BYTE_           b_ModulNbr,                 |\r
+|                                BYTE_           b_OutputChannel) \r
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)           |\r
++----------------------------------------------------------------------------+\r
+| Task              : Sets or resets  the output witch has been passed with the         |\r
+|                     parameter b_Channel. Setting an output means setting   |\r
+|                     an ouput high.                                         |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : BYTE_ b_BoardHandle   : Handle of board APCI-1710      |\r
+|                     BYTE_ b_ModulNbr      : Selected module number (0 to 3)|\r
+|                     BYTE_ b_OutputChannel : Selection from digital output  |\r
+|                                             channel (0 or 1)               |\r
+|                                                0      : PD0                |\r
+|                                                1      : PD1                |\r
+|                                               2 to 9 : PA                 |\r
+|                                              10 to 17: PB                 |\r
+|                                              18 to 25: PC                 |\r
+\r
+  b_ModulNbr      = CR_AREF(insn->chanspec);\r
+       b_OutputChannel= CR_CHAN(insn->chanspec);\r
+       ui_State           = data[0]; // ON or OFF\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : 0: No error                                            |\r
+|                    -1: The handle parameter of the board is wrong          |\r
+|                    -2: The module parameter is wrong                       |\r
+|                    -3: The module is not a TTL I/O module                  |\r
+|                    -4: The selected digital output is wrong                |\r
+|                    -5: TTL I/O not initialised see function                |\r
+|                        " i_APCI1710_InitTTLIO"\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data)\r
+       {\r
+       INT    i_ReturnValue = 0;       \r
+       DWORD dw_StatusReg   = 0;\r
+       BYTE b_ModulNbr;\r
+       BYTE b_OutputChannel;\r
+       UINT ui_State;\r
+\r
+       i_ReturnValue  = insn->n;\r
+       b_ModulNbr         = CR_AREF(insn->chanspec);\r
+       b_OutputChannel= CR_CHAN(insn->chanspec);\r
+       ui_State           = data[0]; // ON or OFF\r
+\r
+       /**************************/\r
+       /* Test the module number */\r
+       /**************************/\r
+\r
+       if (b_ModulNbr < 4)\r
+          {\r
+          /**************************/\r
+          /* Test if TTL I/O module */\r
+          /**************************/\r
+\r
+          if ((devpriv->s_BoardInfos.\r
+               dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TTL_IO)\r
+             {\r
+             /******************************************/\r
+             /* Test if the TTL I/O module initialised */\r
+             /******************************************/\r
+\r
+             if (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                 s_TTLIOInfo.\r
+                 b_TTLInit == 1)\r
+                {\r
+                /***********************************/\r
+                /* Test the TTL I/O channel number */\r
+                /***********************************/\r
+\r
+                if ((((b_OutputChannel >= 0) && (b_OutputChannel <= 1)) && ((devpriv->s_BoardInfos.\r
+                                                                             dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130)) ||\r
+                    (((b_OutputChannel >= 0) && (b_OutputChannel <= 25)) && ((devpriv->s_BoardInfos.\r
+                                                                              dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230)))\r
+                   {\r
+                   /****************************************************/\r
+                   /* Test if the selected channel is a output channel */\r
+                   /****************************************************/\r
+\r
+                   if (((b_OutputChannel >= 0) && (b_OutputChannel <= 1) && (devpriv->\r
+                       s_ModuleInfo [b_ModulNbr].\r
+                                                                             s_TTLIOInfo.\r
+                                                                             b_PortConfiguration [3] == 1)) ||\r
+                       ((b_OutputChannel >= 2) && (b_OutputChannel <= 9) && (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                                                             s_TTLIOInfo.\r
+                                                                             b_PortConfiguration [0] == 1)) ||\r
+                       ((b_OutputChannel >= 10) && (b_OutputChannel <= 17) && (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                                                               s_TTLIOInfo.\r
+                                                                               b_PortConfiguration [1] == 1)) ||\r
+                       ((b_OutputChannel >= 18) && (b_OutputChannel <= 25) && (devpriv->s_ModuleInfo [b_ModulNbr].\r
+                                                                               s_TTLIOInfo.\r
+                                                                               b_PortConfiguration [2] == 1)))\r
+                      {\r
+                      /************************/\r
+                      /* Test if PD0 selected */\r
+                      /************************/\r
+\r
+                      if (b_OutputChannel == 0)\r
+                         {\r
+
+                outl(ui_State,devpriv->s_BoardInfos.\r
+                                 ui_Address + (64 * b_ModulNbr));\r
+                         }\r
+                      else\r
+              {\r
+                         /************************/\r
+                         /* Test if PD1 selected */\r
+                         /************************/\r
+\r
+                         if (b_OutputChannel == 1)\r
+                            {\r
+\r
+                                 outl(ui_State,devpriv->s_BoardInfos.\r
+                                    ui_Address + 4 + (64 * b_ModulNbr));\r
+                            }\r
+                         else\r
+                            {\r
+                            b_OutputChannel = b_OutputChannel - 2;\r
+\r
+                            /********************/\r
+                            /* Read all channel */\r
+                            /********************/\r
+\r
+                           
+                                       dw_StatusReg =inl(devpriv->s_BoardInfos.\r
+                                   ui_Address + (64 * b_ModulNbr));\r
+                 if(ui_State) // ON\r
+                 {\r
+                            dw_StatusReg = (dw_StatusReg >> ((b_OutputChannel / 8) * 8)) & 0xFF;\r
+                            dw_StatusReg = dw_StatusReg | (1 << (b_OutputChannel % 8));\r
+                                }else    // Off\r
+                                {\r
+                 dw_StatusReg = (dw_StatusReg >> ((b_OutputChannel / 8) * 8)) & 0xFF;\r
+                            dw_StatusReg = dw_StatusReg & (0xFF - (1 << (b_OutputChannel % 8)));\r
+\r
+                                }\r
+\r
+                            /****************************/\r
+                            /* Set the new output value */\r
+                            /****************************/\r
+\r
+               \r
+                                outl(dw_StatusReg,devpriv->s_BoardInfos.\r
+                                    ui_Address + 8 + ((b_OutputChannel / 8) * 4) + (64 * b_ModulNbr));\r
+                            }\r
+                         }\r
+                      }\r
+                   else\r
+                      {\r
+                      /************************************/\r
+                      /* The selected TTL output is wrong */\r
+                      /************************************/\r
+\r                         DPRINTK(" The selected TTL output is wrong\n");      
+                      i_ReturnValue = -4;\r
+                      }\r
+                   }\r
+                else\r
+                   {\r
+                   /************************************/\r
+                   /* The selected TTL output is wrong */\r
+                   /************************************/\r
+\r                      DPRINTK("The selected TTL output is wrong\n");  
+                   i_ReturnValue = -4;\r
+                   }\r
+                }\r
+             else\r
+                {\r
+                /***************************/\r
+                /* TTL I/O not initialised */\r
+                /***************************/\r
+\r               DPRINTK("TTL I/O not initialised\n");  
+                i_ReturnValue = -5;\r
+                }\r
+             }\r
+          else\r
+             {\r
+             /**************************************/\r
+             /* The module is not a TTL I/O module */\r
+             /**************************************/\r
+\r            DPRINTK("The module is not a TTL I/O module\n");          
+             i_ReturnValue = -3;\r
+             }\r
+          }\r
+       else\r
+          {\r
+          /***********************/\r
+          /* Module number error */\r
+          /***********************/\r
+\r         DPRINTK("Module number error\n");    
+          i_ReturnValue = -2;\r
+          }\r
+\r
+       return (i_ReturnValue);\r
+       }\r
+\r
+\r
diff --git a/comedi/drivers/addi-data/APCI1710_Ttl.h b/comedi/drivers/addi-data/APCI1710_Ttl.h
new file mode 100644 (file)
index 0000000..f7ecfc0
--- /dev/null
@@ -0,0 +1,39 @@
+\r
+\r
+
+\r
+#define APCI1710_TTL_INIT                      0\r
+#define APCI1710_TTL_INITDIRECTION  1\r
+\r
+\r
+#define APCI1710_TTL_READCHANNEL       0\r
+#define APCI1710_TTL_READPORT          1\r
+
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       TTL INISIALISATION FUNCTION                          |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+\r
+       INT   i_APCI1710_InsnConfigInitTTLIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                       TTL INPUT FUNCTION                                   |\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+       INT  i_APCI1710_InsnBitsReadTTLIO(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
+       INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device *dev,comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data);
+/*\r
++----------------------------------------------------------------------------+\r
+|                            TTL OUTPUT FUNCTIONS                            |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+       INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s,\r
+       comedi_insn *insn,lsampl_t *data);\r
diff --git a/comedi/drivers/addi-data/Makefile.am b/comedi/drivers/addi-data/Makefile.am
new file mode 100644 (file)
index 0000000..799e43e
--- /dev/null
@@ -0,0 +1,8 @@
+
+AM_CFLAGS = $(COMEDI_CFLAGS) $(LINUX_CFLAGS)
+LINK = $(top_builddir)/modtool --link -o $@
+
+module_PROGRAMS = addi_common.ko
+
+addi_common_ko_SOURCES = addi_common.c
+
diff --git a/comedi/drivers/addi-data/addi_amcc_s5933.h b/comedi/drivers/addi-data/addi_amcc_s5933.h
new file mode 100644 (file)
index 0000000..76b6af2
--- /dev/null
@@ -0,0 +1,447 @@
+
+//addi_amcc_s5933.h  
+
+/*
+  +-----------------------------------------------------------------------+
+  | (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 <linux/pci.h>
+#include <linux/comedidev.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 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
+
+
+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_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;
+        int i_Count=0;
+       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           
+             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;
+                       
+#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/comedi/drivers/addi-data/addi_common.c b/comedi/drivers/addi-data/addi_common.c
new file mode 100644 (file)
index 0000000..d1ebfa7
--- /dev/null
@@ -0,0 +1,1154 @@
+
+
+
+
+/***************************************************
+      Generic Driver  For ADDI  APCI CARDs
+
+           
+       
+       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   
+
+ ******************************************************************/
+
+/*======================================================================
+                       Authors                         Email ID
+                 Santosh Raktawan              santosh.raktawan@tatainfotech.com
+                 Sarath Chandran K R   sarath.chandran@tatainfotech.com        
+========================================================================*/
+
+
+
+
+/*
+  +-----------------------------------------------------------------------+
+  | (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                                 |
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |                          |                                                                                                |
+  |          |           |                                                                                               |
+  |          |           |                                                           |
+  |          |           |                                                                                               |
+  |          |           |                                                                   |
+  +----------+-----------+------------------------------------------------+
+  |         |                   |                                                                        |
+  |          |           |                                                                                               |
+  |          |           |                                                                               |
+  +----------+-----------+------------------------------------------------+
+*/
+
+
+
+
+
+
+#include<linux/kernel.h>
+#include<linux/module.h>
+#include<linux/sched.h>
+#include<linux/mm.h>
+#include<linux/malloc.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<linux/comedidev.h>
+#include<asm/io.h>
+
+#include "addi_common.h"
+#include "addi_amcc_s5933.h"
+//#include "addi_eeprom.c"
+
+#define devpriv ((addi_private *)dev->private)
+#define this_board ((boardtype *)dev->board_ptr)
+
+
+#include "addi_eeprom.c"
+#include "hwdrv_apci3120.c"
+#include "hwdrv_apci1032.c"
+#include "hwdrv_apci1516.c"
+#include "hwdrv_apci2016.c"
+#include "hwdrv_apci2032.c"
+#include "hwdrv_apci2200.c"
+#include "hwdrv_apci1564.c"
+#include "hwdrv_apci1500.c"
+#include "hwdrv_apci3501.c"
+#include "hwdrv_apci035.c"
+#include "hwdrv_apci3200.c" 
+#include "hwdrv_APCI1710.c"
+
+static boardtype boardtypes[] =
+{
+               {"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,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
+               },
+    
+                {"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,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
+                },
+                {"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,1,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
+                },
+
+                {"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,1,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
+                },
+                {"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,1,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           
+                },
+                {"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,1,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 
+                },
+                {"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,1,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
+                },
+                {"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,1,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 
+                },
+                
+
+               {"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,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
+               },
+                {"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,1,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           
+                },
+                {"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,1,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
+               },
+                {"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,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  
+               },
+
+               {"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,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
+               }
+                
+};
+
+#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,
+               offset:         sizeof(boardtype),
+       };
+
+
+
+//This macro is defined in comedidev.h
+/*     #define COMEDI_INITCLEANUP(x)                                           \
+       int init_module(void){return comedi_driver_register(&(x));}     \
+       void cleanup_module(void){comedi_driver_unregister(&(x));}
+*/
+
+COMEDI_INITCLEANUP(driver_addi);
+
+
+
+
+/*
++----------------------------------------------------------------------------+
+| 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;
+        DWORD dw_Dummy; 
+       unsigned short io_addr[5],master,irq;//v_58
+        unsigned int iobase_a,iobase_main,iobase_addon,iobase_reserved;
+       struct pcilst_struct *card=NULL;
+       unsigned char pci_bus,pci_slot,pci_func;
+       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 ((card=ptr_select_and_alloc_pci_card(this_board->i_VendorId, this_board->i_DeviceId, it->options[0], it->options[1]))==NULL) 
+       return -EIO;
+       if ((i_pci_card_data(card,&pci_bus,&pci_slot,&pci_func,&io_addr[0],&irq,&master))<0) 
+       {
+               i_pci_card_free(card);
+               rt_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];
+       rt_printk(", b:s:f=%d:%d:%d, base0:0x%4x, base1: 0x%4x, base2: 0x%4x",pci_bus,pci_slot,pci_func,io_addr[0],io_addr[1],io_addr[2]);
+        if (check_region(iobase_main, this_board->i_IorangeBase1) < 0) 
+        {
+           rt_printk("I/O port conflict\n");
+           return -EIO;
+        }
+        //if(this_board->i_Dma)
+        if(iobase_a) 
+        {
+               if (check_region(iobase_a, this_board->i_IorangeBase0) < 0) 
+               {
+                       printk("AMCC check region failed\n"); 
+                       rt_printk("I/O port conflict\n");
+                       return -EIO;
+               }
+        }
+
+        // ##
+        if(io_addr[2])
+        {
+          if (check_region(io_addr[2], this_board->i_IorangeBase2) < 0) 
+               {
+                       printk("Base 2 check region failed\n"); 
+                       rt_printk("I/O port conflict\n");
+                       return -EIO;
+               }
+
+
+        }  
+       //##
+       dev->iobase=iobase_main;// DAQ base address...
+       request_region(dev->iobase,  this_board->i_IorangeBase1, "ADDI COMMON");
+
+       dev->board_name =this_board->pc_DriverName;
+       if((ret=alloc_private(dev,sizeof(addi_private)))<0)
+       return -ENOMEM;
+       devpriv->amcc=card;
+       devpriv->master=master; //testing 
+        devpriv->iobase=dev->iobase;
+       devpriv->i_IobaseAmcc=iobase_a;//AMCC base address...
+       devpriv->i_IobaseAddon=iobase_addon;//ADD ON base address....
+        devpriv->i_IobaseReserved=iobase_reserved; 
+
+        //if(this_board->i_Dma)
+        if(iobase_a)
+        {
+               request_region(devpriv->i_IobaseAmcc,this_board->i_IorangeBase0, "ADDI COMMON");
+        }
+        
+        //##
+       if(io_addr[2])
+        {
+               request_region(io_addr[2],this_board->i_IorangeBase2, "ADDI COMMON");
+        }
+
+        //##
+
+       if (irq>0)  
+       {
+               if (comedi_request_irq(irq, v_ADDI_Interrupt, SA_SHIRQ, "ADDI COMMON", dev)) 
+               {
+                       rt_printk(", unable to allocate IRQ %d, DISABLING IT", irq);
+                       irq=0; /* Can't use IRQ */
+               } 
+               else 
+               {
+                       rt_printk(", irq=%d", irq);
+               }    
+       } 
+       else 
+       {
+               rt_printk(", IRQ disabled");
+       }
+       rt_printk("\n%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)
+       { 
+          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);
+             }
+       i_EepromReadMainHeader(io_addr[0],this_board->pc_EepromChip,dev);
+       } 
+       if (it->options[2]>0)   \r
+         {
+            devpriv->us_UseDma=ADDI_DISABLE;
+         }
+       else
+         {
+            devpriv->us_UseDma=ADDI_ENABLE;
+         }
+       
+        if(this_board->i_Dma)
+        { 
+               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]=__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!");
+                               master=0;
+                               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 
+               {
+                       rt_printk("\nDMA DISABLED\n");
+               }
+        }
+
+
+
+ if (!strcmp(this_board->pc_DriverName,"apci1710"))
+    {
+       dev->n_subdevices = 9;
+       if((ret=alloc_subdevices(dev))<0)
+       return ret;
+        // 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;
+
+               // save base address
+       devpriv->s_BoardInfos.ui_Address=io_addr[2];
+  }       
+  else
+  {
+       dev->n_subdevices = 6;
+       if((ret=alloc_subdevices(dev))<0)
+       return ret;
+
+     // Allocate and Initialise AI Subdevice Structures
+       s = dev->subdevices + 0;
+        if(this_board->i_NbrAiChannel)
+        {
+       dev->read_subdev = s;
+       s->type = COMEDI_SUBD_AI;
+       s->subdev_flags = SDF_READABLE|SDF_RT|SDF_COMMON|SDF_GROUND|SDF_DIFF;
+       s->n_chan = this_board->i_NbrAiChannel;
+       s->maxdata = this_board->i_AiMaxdata;
+       s->len_chanlist = this_board->i_AiChannelList;
+       s->range_table = this_board->pr_AiRangelist;
+       
+        
+        
+        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_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;
+       }
+         
+        /* EEPROM */
+       s=dev->subdevices+5;
+        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;
+       }
+     }
+       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(devpriv->i_IobaseAmcc)
+                       release_region(devpriv->i_IobaseAmcc,this_board->i_IorangeBase0);
+               if (devpriv->allocated)
+                       i_pci_card_free(devpriv->amcc);
+               if (devpriv->ul_DmaBufferVirtual[0]) 
+                       free_pages(devpriv->ul_DmaBufferVirtual[0],devpriv->ui_DmaBufferPages[0]);
+               if (devpriv->ul_DmaBufferVirtual[1]) 
+                       free_pages(devpriv->ul_DmaBufferVirtual[1],devpriv->ui_DmaBufferPages[1]);
+       }
+           
+       if(dev->irq)
+       {
+               free_irq(dev->irq,dev);
+       }
+       
+       if(dev->iobase) release_region(dev->iobase,this_board->i_IorangeBase1);
+        
+        if(devpriv->i_IobaseAddon) release_region(devpriv->i_IobaseAddon,this_board->i_IorangeBase2); 
+           
+       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, struct pt_regs *regs)        |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Task              : Registerd interrupt routine                                                   |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| Input Parameters  :  int irq                                                                                          |
+|                                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :                                                                           |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+static void v_ADDI_Interrupt(int irq, void *d, struct pt_regs *regs)
+{
+comedi_device *dev = d;
+this_board->v_hwdrv_Interrupt(irq,d,regs);
+return;
+}
+// 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/comedi/drivers/addi-data/addi_common.h b/comedi/drivers/addi-data/addi_common.h
new file mode 100644 (file)
index 0000000..3747497
--- /dev/null
@@ -0,0 +1,475 @@
+/***********ADDI_COMMON.H*********************/
+
+
+
+
+
+/*
+  +-----------------------------------------------------------------------+
+  | (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                       |
+  +-------------------------------+---------------------------------------+
+  | Author    :           | Date     :                                    |
+  +-----------------------------------------------------------------------+
+  | Description : ADDI COMMON Header File                                 |
+  +-----------------------------------------------------------------------+
+  |                             UPDATE'S                                  |
+  +-----------------------------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |                          |                                                                                                |
+  |          |           |                                                                                               |
+  |          |           |                                                           |
+  |          |           |                                                                                               |
+  |          |           |                                                                   |
+  +----------+-----------+------------------------------------------------+
+  |         |                   |                                                                        |
+  |          |           |                                                                                               |
+  |          |           |                                                                               |
+  +----------+-----------+------------------------------------------------+
+*/
+
+
+
+
+//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/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 <linux/comedidev.h>
+#include "addi_amcc_s5933.h"
+#include <linux/kmod.h>
+#include <asm/uaccess.h>
+
+#define ERROR  -1
+#define SUCCESS 1
+
+// variable type definition
+
+#define VOID void
+#define UINT unsigned int
+#define ULONG unsigned long
+#define USHORT unsigned short
+#define PUSHORT unsigned short *
+#define INT int
+#define BYTE unsigned char
+#define PBYTE unsigned char *
+#define PINT int *
+#define PUINT unsigned int *
+#define CHAR char
+#define PCHAR char *
+#define PRANGE comedi_lrange   *
+#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 DWORD         unsigned long
+#define WORD          unsigned short
+
+#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"
+
+// Structures
+// structure for the boardtype
+typedef struct {
+
+               PCHAR           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
+               PRANGE      pr_AiRangelist; // rangelist for A/D        
+               PRANGE      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_Dma;            // dma present or not
+                INT         i_Timer;         //   timer subdevice present or not     
+               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, struct pt_regs *regs);
+ 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);  
+} 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;
+               struct pcilst_struct    *amcc;          // ptr too AMCC data
+               UINT                    master;         // master capable
+               BYTE                    allocated;      // we have blocked card
+               BYTE                b_ValidDriver;// driver is ok
+               BYTE                b_AiContinuous;     // we do unlimited AI  
+               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    
+                UINT                ui_AiReadData[32];    
+               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
+               ULONG               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 e 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_ExttrigEnable; //  To enable or disable external trigger
+                struct task_struct *tsk_Current;               // Pointer to the current process
+
+
+
+       // 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];
+
+       }       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 void v_ADDI_Interrupt(int irq, void *d, struct pt_regs *regs);
+static int i_ADDIDATA_InsnReadEeprom(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
+
+
+
diff --git a/comedi/drivers/addi-data/addi_eeprom.c b/comedi/drivers/addi-data/addi_eeprom.c
new file mode 100644 (file)
index 0000000..72c0d31
--- /dev/null
@@ -0,0 +1,884 @@
+
+
+/*
+  +-----------------------------------------------------------------------+
+  | (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                       |
+  +-------------------------------+---------------------------------------+
+  | Author    :                                  | Date     :                                            |
+  +-----------------------------------------------------------------------+
+  | 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        DWORD                           unsigned int
+#define PWORD                          unsigned short *
+#define PDWORD                         unsigned int  *
+
+
+
+
+#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)\r
+{\r
+       BYTE b_Counter = 0;\r
+       BYTE b_ReadByte = 0;\r
+       BYTE b_ReadLowByte = 0;\r
+       BYTE b_ReadHighByte = 0;\r
+       BYTE b_SelectedAddressLow = 0;\r
+       BYTE b_SelectedAddressHigh = 0;\r
+       WORD w_ReadWord = 0;\r
+       
+\r
+        /**************************/\r
+        /* Test the PCI chip type */\r
+        /**************************/\r
+\r
+
+        if ((!strcmp(pc_PCIChipInformation, "S5920")) || \r
+            (!strcmp(pc_PCIChipInformation, "S5933")))\r
+        {\r
+               
+          for (b_Counter=0; b_Counter<2; b_Counter++)\r
+            {\r
+              b_SelectedAddressLow  = (w_EepromStartAddress + b_Counter) % 256; //Read the low 8 bit part\r
+              b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256; //Read the high 8 bit part\r
+\r
+             /************************************/\r
+             /* Select the load low address mode */\r
+             /************************************/\r
+\r             outb(NVCMD_LOAD_LOW,w_PCIBoardEepromAddress + 0x3F);
+            
+\r             
+             /****************/\r
+             /* Wait on busy */\r
+             /****************/\r
+             v_EepromWaitBusy (w_PCIBoardEepromAddress);\r
+
+             /************************/\r
+             /* Load the low address */\r
+             /************************/\r
+\r             outb(b_SelectedAddressLow,w_PCIBoardEepromAddress + 0x3E);
+             
+\r     
+             /****************/\r
+             /* Wait on busy */\r
+             /****************/\r
+             v_EepromWaitBusy (w_PCIBoardEepromAddress);\r
+\r
+             /*************************************/\r
+             /* Select the load high address mode */\r
+             /*************************************/\r
+\r             outb(NVCMD_LOAD_HIGH,w_PCIBoardEepromAddress + 0x3F);
+            
+\r
+             /****************/\r
+             /* Wait on busy */\r
+             /****************/\r
+             v_EepromWaitBusy (w_PCIBoardEepromAddress);\r
+\r
+             /*************************/\r
+             /* Load the high address */\r
+             /*************************/\r
+\r             outb(b_SelectedAddressHigh,w_PCIBoardEepromAddress +0x3E);       
+            
+
+             /****************/\r
+             /* Wait on busy */\r
+             /****************/\r
+             v_EepromWaitBusy (w_PCIBoardEepromAddress);\r
+\r
+             /************************/\r
+             /* Select the READ mode */\r
+             /************************/\r
+\r             outb(NVCMD_BEGIN_READ,w_PCIBoardEepromAddress + 0x3F);  
+            
+
+             /****************/\r
+             /* Wait on busy */\r
+             /****************/\r\r
+             v_EepromWaitBusy (w_PCIBoardEepromAddress);\r
+\r
+             /*****************************/\r
+             /* Read data into the EEPROM */\r
+             /*****************************/\r
+              b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E);  \r
+            
+\r             
+             /****************/\r
+             /* Wait on busy */\r
+             /****************/\r
+\r
+             v_EepromWaitBusy (w_PCIBoardEepromAddress);\r
+\r
+             /*********************************/\r
+             /* Select the upper address part */\r
+             /*********************************/\r
+\r
+             if(b_Counter==0)\r
+                {\r
+                b_ReadLowByte=b_ReadByte;\r
+                } // if(b_Counter==0)\r
+             else\r
+                {\r
+                b_ReadHighByte=b_ReadByte;\r
+                } // if(b_Counter==0)\r
+           } // for (b_Counter=0; b_Counter<2; b_Counter++)\r
+\r
+          w_ReadWord=(b_ReadLowByte | (((WORD) b_ReadHighByte) * 256));\r
+        \r     
+           } // end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) \r
+        if (!strcmp(pc_PCIChipInformation, "93C76"))\r
+           {\r
+           /*************************************/\r
+           /* Read 16 bit from the EEPROM 93C76 */\r
+           /*************************************/\r
+\r         
+           v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress, &w_ReadWord);\r
+           }\r
+             
+       return (w_ReadWord);\r
+       }\r
+\r
+\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : VOID v_EepromWaitBusy                                  |\r
+|                      (WORD   w_PCIBoardEepromAddress)                         |\r
++----------------------------------------------------------------------------+\r
+| Task              : Wait the busy flag from PCI controller                 |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : WORD w_PCIBoardEepromAddress : PCI eeprom base address |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters : -                                                      |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : -                                                      |\r
++----------------------------------------------------------------------------+\r
+*/\r
+\r
+VOID   v_EepromWaitBusy(WORD   w_PCIBoardEepromAddress)\r
+       {\r
+       BYTE b_EepromBusy = 0;\r
+\r
+       do\r
+         {\r
+          /*************/\r
+          /* IMPORTANT */\r
+          /*************/\r
+\r
+          /************************************************************************/\r
+          /* An error has been written in the AMCC 5933 book at the page B-13*/\r        
+           /* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and   */
\r        /*      the operator register is AMCC_OP_REG_MCSR+3*/\r 
+          /*      WORD read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */\r   
+           /*      DWORD read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */\r        
+           /************************************************************************/\r \r 
+                  b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F);             
+          b_EepromBusy = b_EepromBusy &0x80;\r
+        }\r     while(b_EepromBusy == 0x80);\r \r
+
+       }\r
+\r
+\r
+
+/*\r
++---------------------------------------------------------------------------------+\r
+| Function   Name   : VOID v_EepromClock76(DWORD dw_Address,                      |\r
+|                                         DWORD dw_RegisterValue)                                        |\r
++---------------------------------------------------------------------------------+\r
+| Task              : This function sends the clocking sequence to the EEPROM.    |\r
++---------------------------------------------------------------------------------+\r
+| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |\r
+|                    DWORD dw_RegisterValue : PCI eeprom register value to write.|\r
++---------------------------------------------------------------------------------+\r
+| Output Parameters : -                                                           |\r
++---------------------------------------------------------------------------------+\r
+| Return Value      : -                                                           |\r
++---------------------------------------------------------------------------------+\r
+*/\r
+\r
+VOID v_EepromClock76(DWORD dw_Address,DWORD dw_RegisterValue)\r
+   {\r
+\r
+   /************************/\r
+   /* Set EEPROM clock Low */\r
+   /************************/\r
+  \routl(dw_RegisterValue & 0x6,dw_Address);
+
+   /***************/\r
+   /* Wait 0.1 ms */\r
+   /***************/\r\r
+    udelay(100);
+   \r
+   /*************************/\r
+   /* Set EEPROM clock High */\r
+   /*************************/\r
+\r  outl(dw_RegisterValue | 0x1,dw_Address);
+\r
+   /***************/\r
+   /* Wait 0.1 ms */\r
+   /***************/\r
+\r   udelay(100);
+
+   }\r
+\r
+/*\r
++---------------------------------------------------------------------------------+\r
+| Function   Name   : VOID v_EepromSendCommand76(DWORD dw_Address,                |\r
+|                                         DWORD   dw_EepromCommand,                              |\r
+|                                         BYTE    b_DataLengthInBits)                        |\r
++---------------------------------------------------------------------------------+\r
+| Task              : This function sends a Command to the EEPROM 93C76.          |\r
++---------------------------------------------------------------------------------+\r
+| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |\r
+|                    DWORD dw_EepromCommand : PCI eeprom command to write.       |\r
+|                    BYTE  b_DataLengthInBits : PCI eeprom command data length.  |\r
++---------------------------------------------------------------------------------+\r
+| Output Parameters : -                                                           |\r
++---------------------------------------------------------------------------------+\r
+| Return Value      : -                                                           |\r
++---------------------------------------------------------------------------------+\r
+*/\r
+\r
+VOID v_EepromSendCommand76(DWORD dw_Address,DWORD   dw_EepromCommand,BYTE    b_DataLengthInBits)\r
+   {\r
+   CHAR  c_BitPos = 0;\r
+   DWORD dw_RegisterValue = 0;\r
+\r
\r
+   /*****************************/\r
+   /* Enable EEPROM Chip Select */\r
+   /*****************************/\r
+   dw_RegisterValue = 0x2;\r
+\r
+   /********************************************************************/\r
+   /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */\r
+   /********************************************************************/\r
+   outl(dw_RegisterValue,dw_Address);\r
+\r
+   /***************/\r
+   /* Wait 0.1 ms */\r
+   /***************/\r
+  \rudelay(100);
+   \r
+   /*******************************************/\r
+   /* Send EEPROM command - one bit at a time */\r
+   /*******************************************/\r   \r
+   for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--)\r
+      {\r
+
+      /**********************************/\r
+      /* Check if current bit is 0 or 1 */\r
+      /**********************************/\r\r
+      if (dw_EepromCommand & (1 << c_BitPos))\r
+        {\r
+        /***********/\r
+        /* Write 1 */\r
+        /***********/\r
+\r
+        dw_RegisterValue = dw_RegisterValue | 0x4;\r
+        }\r
+      else\r
+        {\r
+        /***********/\r
+        /* Write 0 */\r
+        /***********/\r
+\r
+        dw_RegisterValue = dw_RegisterValue & 0x3;\r
+        }\r
+\r
+      /*********************/\r
+      /* Write the command */\r
+      /*********************/\r
+\r      outl(dw_RegisterValue,dw_Address);
+  
+\r
+      /***************/\r
+      /* Wait 0.1 ms */\r
+      /***************/\r
+   \r  udelay(100);
+  
+   \r
+      /****************************/\r
+      /* Trigger the EEPROM clock */\r
+      /****************************/\r
+      v_EepromClock76(dw_Address, dw_RegisterValue);\r
+
+      }\r
+\r
+   }\r
+\r
+/*\r
++---------------------------------------------------------------------------------+\r
+| Function   Name   : VOID v_EepromCs76Read(DWORD dw_Address,                     |\r
+|                                         WORD    w_offset,                                              |\r
+|                                         PWORD   pw_Value)                                              |\r
++---------------------------------------------------------------------------------+\r
+| Task              : This function read a value from the EEPROM 93C76.           |\r
++---------------------------------------------------------------------------------+\r
+| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |\r
+|                    WORD    w_offset : Offset of the adress to read             |\r
+|                    PWORD   pw_Value : PCI eeprom 16 bit read value.            |\r
++---------------------------------------------------------------------------------+\r
+| Output Parameters : -                                                           |\r
++---------------------------------------------------------------------------------+\r
+| Return Value      : -                                                           |\r
++---------------------------------------------------------------------------------+\r
+*/\r
+\r
+VOID v_EepromCs76Read(DWORD dw_Address,WORD    w_offset,\rPWORD   pw_Value)\r
+   {\r
+   CHAR   c_BitPos = 0;\r
+   DWORD  dw_RegisterValue = 0;\r
+   DWORD  dw_RegisterValueRead = 0;\r
+\r
+\r
+   /*************************************************/\r
+   /* Send EEPROM read command and offset to EEPROM */\r
+   /*************************************************/\r
+   v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2), EE76_CMD_LEN);\r
+\r
+   /*******************************/\r
+   /* Get the last register value */\r
+   /*******************************/\r
+   dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2;\r
+   \r
+   /*****************************/\r
+   /* Set the 16-bit value of 0 */\r
+   /*****************************/\r\r
+   *pw_Value = 0;\r
+\r
+   /************************/\r
+   /* Get the 16-bit value */\r
+   /************************/\r
+   for (c_BitPos = 0; c_BitPos < 16; c_BitPos++)\r
+      {\r
+
+      /****************************/\r
+      /* Trigger the EEPROM clock */\r
+      /****************************/\r\r
+      v_EepromClock76(dw_Address, dw_RegisterValue);\r
+\r
+      /**********************/\r
+      /* Get the result bit */\r
+      /**********************/\r
+\r     dw_RegisterValueRead = inl(dw_Address);
+
+      /***************/\r
+      /* Wait 0.1 ms */\r
+      /***************/\r
+   \r  udelay(100);
+     \r
+      /***************************************/\r
+      /* Get bit value and shift into result */\r
+      /***************************************/\r\r
+      if (dw_RegisterValueRead & 0x8)\r
+        {\r
+
+        /**********/\r
+        /* Read 1 */\r
+        /**********/\r\r
+        *pw_Value = (*pw_Value << 1) | 0x1;\r
+        }\r
+      else\r
+        {\r
+        /**********/\r
+        /* Read 0 */\r
+        /**********/\r
+        *pw_Value = (*pw_Value << 1);\r
+        
+       }\r
+      }\r
+\r
+   /*************************/\r
+   /* Clear all EEPROM bits */\r
+   /*************************/\r\r
+   dw_RegisterValue = 0x0;\r
+\r
+   /********************************************************************/\r
+   /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */\r
+   /********************************************************************/\r
+\r  outl(dw_RegisterValue,dw_Address);
+     
+   /***************/\r
+   /* Wait 0.1 ms */\r
+   /***************/\r
+   udelay(100);
+    
+   }\r
+\r
+
+
+       /******************************************/
+       /*      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);   
+                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/comedi/drivers/addi-data/amcc_s5933_58.h b/comedi/drivers/addi-data/amcc_s5933_58.h
new file mode 100644 (file)
index 0000000..6a67cbd
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+       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 <linux/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/comedi/drivers/addi-data/hwdrv_APCI1710.c b/comedi/drivers/addi-data/hwdrv_APCI1710.c
new file mode 100644 (file)
index 0000000..5acb77f
--- /dev/null
@@ -0,0 +1,1077 @@
+ #include "hwdrv_APCI1710.h"\r
+ #include "APCI1710_Inp_cpt.c"\r 
+ #include "APCI1710_Ssi.c"\r
+ #include "APCI1710_Tor.c"\r
+ #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"
+
+int i_APCI1710_Reset(comedi_device *dev);
+VOID v_APCI1710_Interrupt(int irq, void *d, struct pt_regs *regs) ;
+//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);  
+
+       // 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, struct pt_regs *regs)  
+{
+       comedi_device *dev = d;
+       comedi_subdevice *s = dev->subdevices + 0;      
+       BYTE   b_ModuleCpt       = 0;
+       BYTE   b_InterruptFlag   = 0;
+       BYTE   b_PWMCpt          = 0;
+       BYTE   b_ETMCpt          = 0;
+       BYTE   b_TorCounterCpt   = 0;
+       BYTE   b_PulseIncoderCpt = 0;
+       UINT  ui_16BitValue;
+       ULONG ul_InterruptLatchReg;
+       ULONG ul_LatchRegisterValue;
+       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/comedi/drivers/addi-data/hwdrv_APCI1710.h b/comedi/drivers/addi-data/hwdrv_APCI1710.h
new file mode 100644 (file)
index 0000000..9d0777c
--- /dev/null
@@ -0,0 +1,78 @@
+\r
+
+
+
+\r
+#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 */
+\r
+\r
+   #define INT           int\r
+   #define UINT          unsigned int\r
+   #define BYTE          unsigned char\r
+   #define CHAR          char\r
+   #define LONG          long\r
+   #define ULONG         unsigned long\r
+   #define VOID          void\r
+   #define PINT          int *\r
+   #define PUINT         unsigned int *\r
+   #define PBYTE         unsigned char *\r
+   #define PCHAR         char *\r
+   #define PLONG         long *\r
+   #define PULONG        unsigned long *\r
+   #define DWORD         unsigned long\r
+   #define WORD          unsigned short\r
+\r
+   #define      APCI1710_BOARD_NAME                      "apci1710"\r
+   #define      APCI1710_BOARD_VENDOR_ID         0x10E8\r
+   #define      APCI1710_BOARD_DEVICE_ID         0x818F\r
+   #define      APCI1710_ADDRESS_RANGE        256\r
+   #define      APCI1710_CONFIG_ADDRESS_RANGE 8\r
+   #define      APCI1710_INCREMENTAL_COUNTER  0x53430000UL\r
+   #define      APCI1710_SSI_COUNTER          0x53490000UL\r
+   #define      APCI1710_TTL_IO               0x544C0000UL\r
+   #define      APCI1710_DIGITAL_IO           0x44490000UL\r
+   #define      APCI1710_82X54_TIMER          0x49430000UL\r
+   #define      APCI1710_CHRONOMETER          0x43480000UL\r
+   #define      APCI1710_PULSE_ENCODER       0x495A0000UL\r
+   #define      APCI1710_TOR_COUNTER         0x544F0000UL\r
+   #define      APCI1710_PWM                 0x50570000UL\r
+   #define      APCI1710_ETM                 0x45540000UL\r
+   #define      APCI1710_CDA                 0x43440000UL\r
+   #define      APCI1710_DISABLE              0\r
+   #define      APCI1710_ENABLE               1\r
+   #define      APCI1710_SYNCHRONOUS_MODE     1\r
+   #define      APCI1710_ASYNCHRONOUS_MODE    0\r
+\r
+\r
+//MODULE INFO STRUCTURE\r
+
+\rcomedi_lrange range_apci1710_ttl={ 4, {
+               BIP_RANGE(10),
+               BIP_RANGE(5),
+               BIP_RANGE(2),
+               BIP_RANGE(1)            
+       }
+};
+\r
+\r
+\rcomedi_lrange range_apci1710_ssi={ 4, {
+               BIP_RANGE(10),
+               BIP_RANGE(5),
+               BIP_RANGE(2),
+               BIP_RANGE(1)            
+       }
+};
+
+comedi_lrange range_apci1710_inccpt={ 4, {
+               BIP_RANGE(10),
+               BIP_RANGE(5),
+               BIP_RANGE(2),
+               BIP_RANGE(1)            
+       }
+};
diff --git a/comedi/drivers/addi-data/hwdrv_apci035.c b/comedi/drivers/addi-data/hwdrv_apci035.c
new file mode 100644 (file)
index 0000000..8d08c4f
--- /dev/null
@@ -0,0 +1,600 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-------------------------------+---------------------------------------+\r
+  | Project     : 13Card Linux Driver | Compiler   : GCC                  |\r
+  | Module name : hwdrv_apci035.c|     Version    : 2.96                  |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author : Shitalkumar S Chavan |     Date       : 10.12.2001           |\r
+  +-------------------------------+---------------------------------------+\r
+  | Description :   Hardware Layer Acces For APCI-035                     |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +----------+-----------+------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +----------+-----------+------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+#include "hwdrv_apci035.h"\r
+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)\r
+ 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;
+}
+
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI035_StartStopWriteTimerWatchdog              |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               | \r
+|                      comedi_insn *insn,lsampl_t *data)                     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Start / Stop The Selected Timer , or Watchdog  |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : comedi_device *dev : Driver handle                     |\r
+|                     UINT *data         : Data Pointer contains             |\r
+|                                          configuration parameters as below |\r
+|                                                                                       |\r
+|                                        data[0] : 0 - Stop Selected Timer/Watchdog     |\r
+|                                                  1 - Start Selected Timer/Watchdog    |\r
+|                                                  2 - Trigger Selected Timer/Watchdog  |\r
+|                                                  3 - Stop All Timer/Watchdog          |\r
+|                                                  4 - Start All Timer/Watchdog         |\r
+|                                                  5 - Trigger All Timer/Watchdog       |\r
+|                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error                      | \r
+|                                                                                       |\r
++----------------------------------------------------------------------------+\r
+*/\r
+INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)\r
+{\r
+   UINT  ui_Command = 0; \r
+   INT i_Count=0;
+      if  (data[0]==1) \r
+         { \r
+         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)\r
+      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 \r
+         {\r
+         //Stop The Watchdog\r
+         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)\r
+      if(data[0]==3)//stop all Watchdogs\r
+        {
+         ui_Command=0; 
+         for(i_Count=1;i_Count<=4;i_Count++)
+            {\r
+            if(devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+              {
+               ui_Command=0x2UL;
+              }
+            else
+              {
+              ui_Command = 0x10UL; \r
+              } 
+               i_WatchdogNbr=i_Count;
+               outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32) + 0);
+             }\r
+\r         } 
+      if(data[0]==4)//start all Watchdogs\r
+        {\r
+         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);             
+             } 
+          }\r
+      if(data[0]==5)//trigger all Watchdogs\r
+        {\r
+         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; 
+              } 
+   \r          i_WatchdogNbr=i_Count;
+             outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32) + 0);
+           }
+         i_Temp=1;
+         }\r
+   return insn->n;\r
+}\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI035_ReadTimerWatchdog                        |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               | \r
+|                      comedi_insn *insn,lsampl_t *data)                     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Read The Selected Timer , Counter or Watchdog          |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : comedi_device *dev : Driver handle                     |\r
+|                     UINT *data         : Data Pointer contains             |\r
+|                                          configuration parameters as below |\r
+|                                                                            | \r
+|                                                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  data[0]            : software trigger status                                                                                            \r              data[1]            : hardware trigger status  
+|                              data[2]            : Software clear status      
+                        data[3]            : Overflow status                                                                                            \r                     data[4]            : Timer actual value   
+                       
+
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+INT i_APCI035_ReadTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)\r
+{\r
+UINT ui_Status = 0;   // Status register \r
+ i_WatchdogNbr=insn->unused[0]; 
+              /******************/
+              /* Get the status */
+              /******************/  
+      ui_Status =inl(devpriv->iobase+((i_WatchdogNbr-1)*32) + 16);\r
+      /***********************************/
+      /* 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) \r
+      {\r
+      data[4]=inl(devpriv->iobase+((i_WatchdogNbr-1)*32) + 0);
+      
+      } //  if  (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) \r
+  
+      
+   return insn->n;\r
+}\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : INT i_APCI035_ConfigAnalogInput                        |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               | \r
+|                      comedi_insn *insn,lsampl_t *data)                     |\r
++----------------------------------------------------------------------------+\r
+| Task              : Configures The Analog Input Subdevice                  |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : comedi_device *dev      : Driver handle                |\r
+|                     comedi_subdevice *s     : Subdevice Pointer            |  \r
+|                     comedi_insn *insn       : Insn Structure Pointer       |  \r
+|                     lsampl_t *data          : Data Pointer contains        |\r
+|                                          configuration parameters as below |\r
+|                     data[0]                  : Warning delay value                                                              
+|                                                                            |         \r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+INT i_APCI035_ConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) \r
+{\r
+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;\r
+} \r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI035_ReadAnalogInput                          |\r
+|                                (comedi_device *dev,comedi_subdevice *s,       | \r
+|                     comedi_insn *insn,lsampl_t *data)                      |\r
++----------------------------------------------------------------------------+\r
+| Task              : Read  value  of the selected channel                              |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : comedi_device *dev      : Driver handle                |\r
+|                     UINT ui_NoOfChannels    : No Of Channels To read       |\r
+|                     UINT *data              : Data Pointer to read status  |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
+|                                data[0]  : Digital Value Of Input              |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+INT i_APCI035_ReadAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) \r
+{ 
+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;\r
+}\r
+\r
+
+\r
+
+\r
+
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   :  int i_APCI035_Reset(comedi_device *dev)                      |\r
+|                                                                                               |\r
++----------------------------------------------------------------------------+\r
+| Task              :Resets the registers of the card                        |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  :                                                        |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      :                                                        |\r
+|                                                                                       |\r
++----------------------------------------------------------------------------+\r
+*/\r
+INT i_APCI035_Reset(comedi_device *dev)\r
+{
+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;\r
+}\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : static void v_APCI035_Interrupt                                       |\r
+|                                        (int irq , void *d, struct pt_regs *regs)      |\r
++----------------------------------------------------------------------------+\r
+| Task              : Interrupt processing Routine                           |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : int irq                 : irq number                   |\r
+|                     void *d                 : void pointer                 |\r
+|                     struct pt_regs *regs    : structure pointer            |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+static void v_APCI035_Interrupt(int irq, void *d, struct pt_regs *regs) \r
+{      \r
+   comedi_device *dev = d;\r
+   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;\r
+}\r
+\r
+
+\r
+
+
diff --git a/comedi/drivers/addi-data/hwdrv_apci035.h b/comedi/drivers/addi-data/hwdrv_apci035.h
new file mode 100644 (file)
index 0000000..853ad7f
--- /dev/null
@@ -0,0 +1,124 @@
+// Card Specific information\r
+#define APCI035_BOARD_VENDOR_ID                 0x15B8\r
+#define APCI035_ADDRESS_RANGE                   255\r
+\r
+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 \r
+\r
+#define APCI035_TCW_SYNC_ENABLEDISABLE           0\r
+#define APCI035_TCW_RELOAD_VALUE                 4\r
+#define APCI035_TCW_TIMEBASE                     8\r
+#define APCI035_TCW_PROG                         12\r
+#define APCI035_TCW_TRIG_STATUS                  16\r
+#define APCI035_TCW_IRQ                          20\r
+#define APCI035_TCW_WARN_TIMEVAL                 24\r
+#define APCI035_TCW_WARN_TIMEBASE                28\r
+\r
+#define ADDIDATA_TIMER                            0\r
+#define ADDIDATA_WATCHDOG                         1
+\r
+#define APCI035_TW1                               0\r
+#define APCI035_TW2                               32\r
+#define APCI035_TW3                               64\r
+#define APCI035_TW4                               96\r
+\r
+#define APCI035_AI_OFFSET                        0\r
+#define APCI035_TEMP                             128\r
+#define APCI035_ALR_SEQ                          4\r
+#define APCI035_START_STOP_INDEX                 8\r
+#define APCI035_ALR_START_STOP                   12\r
+#define APCI035_ALR_IRQ                          16\r
+#define APCI035_EOS                              20\r
+#define APCI035_CHAN_NO                          24\r
+#define APCI035_CHAN_VAL                         28\r
+#define APCI035_CONV_TIME_TIME_BASE              36\r
+#define APCI035_RELOAD_CONV_TIME_VAL             32\r
+#define APCI035_DELAY_TIME_TIME_BASE             44\r
+#define APCI035_RELOAD_DELAY_TIME_VAL            40\r
+#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\r
+\r
+#define ADDIDATA_UNIPOLAR                        1\r
+#define ADDIDATA_BIPOLAR                         2\r
+\r
+//ADDIDATA Enable Disable\r
+#define ADDIDATA_ENABLE                            1\r
+#define ADDIDATA_DISABLE                           0\r
+\r
+\r
+\r
+\r
+\r
+\r
+// Hardware Layer  functions for Apci035\r
+\r
+\r
+\r
+// TIMER  \r
+// timer value is passed as u seconds\r
+INT i_APCI035_ConfigTimerWatchdog (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+INT i_APCI035_ReadTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+
+
+//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\r
+static void v_APCI035_Interrupt(int irq, void *d, struct pt_regs *regs) ;\r
+\r
+//Reset functions\r
+INT i_APCI035_Reset(comedi_device *dev);       \r
+\r
+\r
+
+
+
+
+
+\r
+\r
+\r
diff --git a/comedi/drivers/addi-data/hwdrv_apci1032.c b/comedi/drivers/addi-data/hwdrv_apci1032.c
new file mode 100644 (file)
index 0000000..cef17cd
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+  +-----------------------------------------------------------------------+
+  | (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     : 13Card Linux Driver | Compiler   : GCC                  |
+  | Module name : hwdrv_apci1032.c|     Version    : 2.96                 |
+  +-------------------------------+---------------------------------------+
+  | Author : Shitalkumar S Chavan |     Date       : 31.10.2001           |
+  +-------------------------------+---------------------------------------+
+  | 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, struct pt_regs *regs)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt handler for the interruptible digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
+|                     struct pt_regs *regs    : structure pointer            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+static VOID v_APCI1032_Interrupt(int irq,void* d, struct pt_regs *regs) 
+{
+ 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/comedi/drivers/addi-data/hwdrv_apci1032.h b/comedi/drivers/addi-data/hwdrv_apci1032.h
new file mode 100644 (file)
index 0000000..8e55bf5
--- /dev/null
@@ -0,0 +1,59 @@
+/*********      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, struct pt_regs *regs) ;
+//Reset
+INT i_APCI1032_Reset(comedi_device *dev);
+
+           
\ No newline at end of file
diff --git a/comedi/drivers/addi-data/hwdrv_apci1500.c b/comedi/drivers/addi-data/hwdrv_apci1500.c
new file mode 100644 (file)
index 0000000..c4e460a
--- /dev/null
@@ -0,0 +1,2726 @@
+/*
+  +-----------------------------------------------------------------------+
+  | (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     : 13Card Linux Driver | Compiler   : GCC                  |
+  | Module name : hwdrv_apci1500.c|     Version    : 2.96                 |
+  +-------------------------------+---------------------------------------+
+  | Author : Karl Andrade         |     Date       : 13.12.2001           |
+  +-------------------------------+---------------------------------------+
+  | 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, struct pt_regs *regs)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt handler                                      |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
+|                     struct pt_regs *regs    : structure pointer            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+static VOID v_APCI1500_Interrupt(int irq,void* d, struct pt_regs *regs) 
+{
+ 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;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                 
\ No newline at end of file
diff --git a/comedi/drivers/addi-data/hwdrv_apci1500.h b/comedi/drivers/addi-data/hwdrv_apci1500.h
new file mode 100644 (file)
index 0000000..479a0ea
--- /dev/null
@@ -0,0 +1,126 @@
+/*********      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, struct pt_regs *regs);
+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) ; 
+                                                         
\ No newline at end of file
diff --git a/comedi/drivers/addi-data/hwdrv_apci1516.c b/comedi/drivers/addi-data/hwdrv_apci1516.c
new file mode 100644 (file)
index 0000000..45501fe
--- /dev/null
@@ -0,0 +1,484 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-------------------------------+---------------------------------------+\r
+  | Project     : 13Card Linux Driver | Compiler   : GCC                  |\r
+  | Module name : hwdrv_apci1516.c|     Version    : 2.96                 |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author : Shitalkumar S Chavan |     Date       : 31.10.2001           |\r
+  +-------------------------------+---------------------------------------+\r
+  | Description :   Hardware Layer Acces For APCI-1516                    |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +----------+-----------+------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +----------+-----------+------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+#include "hwdrv_apci1516.h"\r
+\r
+
+/*
++----------------------------------------------------------------------------+
+| 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;
+}
+\r
+/*
++----------------------------------------------------------------------------+
+| 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
+ 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); 
+    }//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);
+     }// 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); 
+          }//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);
+            }// 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/comedi/drivers/addi-data/hwdrv_apci1516.h b/comedi/drivers/addi-data/hwdrv_apci1516.h
new file mode 100644 (file)
index 0000000..28c6f1f
--- /dev/null
@@ -0,0 +1,51 @@
+/*********      Definitions for APCI-1516 card  *****/\r
+\r
+// Card Specific information
+#define APCI1516_BOARD_VENDOR_ID                 0x15B8
+#define APCI1516_ADDRESS_RANGE                   8
+
+
+//DIGITAL INPUT-OUTPUT DEFINE   \r
+\r
+#define APCI1516_DIGITAL_OP                    4 \r
+#define APCI1516_DIGITAL_OP_RW                         4 \r
+#define APCI1516_DIGITAL_IP                     0  \r
+\r
+\r
+
+\r
+// TIMER COUNTER WATCHDOG DEFINES  \r
+\r
+#define ADDIDATA_WATCHDOG                          2\r
+#define APCI1516_DIGITAL_OP_WATCHDOG               0\r
+#define APCI1516_WATCHDOG_ENABLEDISABLE            12\r
+#define APCI1516_WATCHDOG_RELOAD_VALUE             4\r
+#define APCI1516_WATCHDOG_STATUS                   16\r
+\r
+\r
+// Hardware Layer  functions for Apci1516\r
+\r
+\r
+//Digital Input\r
+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);\r
+\r
+
+\r
+\r
+//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) ;
+\r
+\r
+// TIMER  \r
+// timer value is passed as u seconds\r
+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); \r
+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/comedi/drivers/addi-data/hwdrv_apci1564.c b/comedi/drivers/addi-data/hwdrv_apci1564.c
new file mode 100644 (file)
index 0000000..b4a55f2
--- /dev/null
@@ -0,0 +1,930 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-------------------------------+---------------------------------------+\r
+  | Project     : 13Card Linux Driver | Compiler   : GCC                  |\r
+  | Module name : hwdrv_apci1564.c|     Version    : 2.96                 |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author : Shitalkumar S Chavan |     Date       : 31.10.2001           |\r
+  +-------------------------------+---------------------------------------+\r
+  | Description :   Hardware Layer Acces For APCI-1564                    |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +----------+-----------+------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +----------+-----------+------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+
+#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, struct pt_regs *regs)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt handler for the interruptible digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
+|                     struct pt_regs *regs    : structure pointer            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+static VOID v_APCI1564_Interrupt(int irq,void* d, struct pt_regs *regs) 
+{
+   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/comedi/drivers/addi-data/hwdrv_apci1564.h b/comedi/drivers/addi-data/hwdrv_apci1564.h
new file mode 100644 (file)
index 0000000..447223f
--- /dev/null
@@ -0,0 +1,91 @@
+/*********      Definitions for APCI-1564 card  *****/\r
+\r
+#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
+\r
+// Output defines
+#define APCI1564_DIGITAL_OP                    0x18\r
+#define APCI1564_DIGITAL_OP_RW                 0    \r
+#define APCI1564_DIGITAL_OP_INTERRUPT           4   \r
+#define APCI1564_DIGITAL_OP_IRQ                 12  
+
+\r
+//Digital Input IRQ Function Selection\r
+#define ADDIDATA_OR                             0\r
+#define ADDIDATA_AND                            1\r
+\r
+//Digital Input Interrupt Status\r
+#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS    12\r
+\r
+//Digital Output Interrupt Status\r
+#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS    8  \r
+\r
+//Digital Input Interrupt Enable Disable. \r
+#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE    0x4 \r
+#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE   0xFFFFFFFB\r
+\r
+//Digital Output Interrupt Enable Disable.\r
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1\r
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE\r
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2\r
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD\r
+\r
+//ADDIDATA Enable Disable\r
+\r
+#define ADDIDATA_ENABLE                            1\r
+#define ADDIDATA_DISABLE                           0\r
+\r
+// TIMER COUNTER WATCHDOG DEFINES  \r
+\r
+#define ADDIDATA_TIMER                             0\r
+#define ADDIDATA_COUNTER                           1\r
+#define ADDIDATA_WATCHDOG                          2\r
+#define APCI1564_DIGITAL_OP_WATCHDOG               0x28\r
+#define APCI1564_TIMER                             0x48\r
+#define APCI1564_COUNTER1                          0x0\r
+#define APCI1564_COUNTER2                          0x20\r
+#define APCI1564_COUNTER3                          0x40\r
+#define APCI1564_COUNTER4                          0x60 \r
+#define APCI1564_TCW_SYNC_ENABLEDISABLE            0\r
+#define APCI1564_TCW_RELOAD_VALUE                  4\r
+#define APCI1564_TCW_TIMEBASE                      8\r
+#define APCI1564_TCW_PROG                          12\r
+#define APCI1564_TCW_TRIG_STATUS                   16\r
+#define APCI1564_TCW_IRQ                           20\r
+#define APCI1564_TCW_WARN_TIMEVAL                  24\r
+#define APCI1564_TCW_WARN_TIMEBASE                 28\r
+
+\r
+// Hardware Layer  functions for Apci1564\r
+\r\r
+//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);  \r
+\r
+\r
+// TIMER  \r
+// timer value is passed as u seconds\r
+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, struct pt_regs *regs) ;
+
+// RESET
+INT i_APCI1564_Reset(comedi_device *dev);
diff --git a/comedi/drivers/addi-data/hwdrv_apci2016.c b/comedi/drivers/addi-data/hwdrv_apci2016.c
new file mode 100644 (file)
index 0000000..d8af116
--- /dev/null
@@ -0,0 +1,407 @@
+/*\r
+  +-----------------------------------------------------------------------+\r
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |\r
+  +-----------------------------------------------------------------------+\r
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |\r
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |\r
+  +-------------------------------+---------------------------------------+\r
+  | Project     : 13Card Linux Driver | Compiler   : GCC                  |\r
+  | Module name : hwdrv_apci2016.c|     Version    : 2.96                 |\r
+  +-------------------------------+---------------------------------------+\r
+  | Author : Shitalkumar S Chavan |     Date       : 31.10.2001           |\r
+  +-------------------------------+---------------------------------------+\r
+  | Description :   Hardware Layer Acces For APCI-2016                    |\r
+  +-----------------------------------------------------------------------+\r
+  |                             UPDATES                                   |\r
+  +----------+-----------+------------------------------------------------+\r
+  |   Date   |   Author  |          Description of updates                |\r
+  +----------+-----------+------------------------------------------------+\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  |          |           |                                                |\r
+  +----------+-----------+------------------------------------------------+\r
+*/\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+|                               Included files                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+#include "hwdrv_apci2016.h"
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               | 
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+\r
+| Task              : Configures The Digital Output Subdevice.               |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : comedi_device *dev : Driver handle                     |\r
+|                     UINT *data         : Data Pointer contains             |\r
+|                                          configuration parameters as below |\r
+|                                                                            | \r
+|                        data[0]            : 1 Digital Memory On               |      \r
+|                                                         0 Digital Memory Off              | \r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+int i_APCI2016_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) \r
+{\r
+  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;\r
+}\r
+\r
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI2016_WriteDigitalOutput                      |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+\r
+| Task              : Writes port value  To the selected port                |\r
++----------------------------------------------------------------------------+\r
+| Input Parameters  : comedi_device *dev      : Driver handle                |\r
+|                     UINT ui_NoOfChannels    : No Of Channels To Write      |\r
+|                     UINT *data              : Data Pointer to read status  |\r
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+int i_APCI2016_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)  \r
+{\r
+   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;
+}
+\r
+/*
++----------------------------------------------------------------------------+
+| 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;
+}
+
+
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI2016_ConfigWatchdog                          |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+\r
+| Task              : Configures The Watchdog                                |\r
++----------------------------------------------------------------------------+\r
+| 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  |    
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+int i_APCI2016_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) \r
+{ 
+  
+   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;
+}
+
+
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+\r
+| Task              : Start / Stop The Watchdog                              |\r
++----------------------------------------------------------------------------+\r
+| 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  |
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r
+int i_APCI2016_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)\r
+{
+
+   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;
+}
+\r 
+/*\r
++----------------------------------------------------------------------------+\r
+| Function   Name   : int i_APCI2016_ReadWatchdog                            |\r
+|                        (comedi_device *dev,comedi_subdevice *s,               |
+|                      comedi_insn *insn,lsampl_t *data)                     |
++----------------------------------------------------------------------------+\r
+| Task              : Read The Watchdog                                      |\r
++----------------------------------------------------------------------------+\r
+| 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  |
++----------------------------------------------------------------------------+\r
+| Output Parameters :  --                                                                                                       |\r
++----------------------------------------------------------------------------+\r
+| Return Value      : TRUE  : No error occur                                 |\r
+|                          : FALSE : Error occur. Return the error          |\r
+|                                                                               |\r
++----------------------------------------------------------------------------+\r
+*/\r\r
+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;
+}        
\ No newline at end of file
diff --git a/comedi/drivers/addi-data/hwdrv_apci2016.h b/comedi/drivers/addi-data/hwdrv_apci2016.h
new file mode 100644 (file)
index 0000000..2d1c8f2
--- /dev/null
@@ -0,0 +1,53 @@
+/*********      Definitions for APCI-2016 card  *****/\r
+\r
+#define APCI2016_BOARD_VENDOR_ID 0x15B8
+#define APCI2016_ADDRESS_RANGE   8
+
+\r
+//DIGITAL INPUT-OUTPUT DEFINE   \r
+\r
+#define APCI2016_DIGITAL_OP                    0x04 \r
+#define APCI2016_DIGITAL_OP_RW                         4 \r
+\r
+//ADDIDATA Enable Disable\r
+\r
+#define ADDIDATA_ENABLE                            1\r
+#define ADDIDATA_DISABLE                           0\r
+\r
+// TIMER COUNTER WATCHDOG DEFINES  \r
+\r
+#define ADDIDATA_WATCHDOG                          2\r
+#define APCI2016_DIGITAL_OP_WATCHDOG               0\r
+#define APCI2016_WATCHDOG_ENABLEDISABLE            12\r
+#define APCI2016_WATCHDOG_RELOAD_VALUE             4\r
+#define APCI2016_WATCHDOG_STATUS                   16\r
+\r
+
+// Hardware Layer  functions for Apci2016\r
+\r
+//DO\r
+int i_APCI2016_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) ;\r
+\r
+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);\r
+\r
+\r
+// TIMER  \r
+// timer value is passed as u seconds\r
+\r
+
+int i_APCI2016_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) ;\r
+\r
+int i_APCI2016_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+\r
+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, struct pt_regs *regs) ;
+
+ //VOID v_APCI2016_Interrupt(int irq, void *d, struct pt_regs *regs);
+// RESET
+INT i_APCI2016_Reset(comedi_device *dev);
diff --git a/comedi/drivers/addi-data/hwdrv_apci2032.c b/comedi/drivers/addi-data/hwdrv_apci2032.c
new file mode 100644 (file)
index 0000000..a22a1d7
--- /dev/null
@@ -0,0 +1,561 @@
+/*
+  +-----------------------------------------------------------------------+
+  | (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     : 13Card Linux Driver | Compiler   : GCC                  |
+  | Module name : hwdrv_apci2032.c|     Version    : 2.96                 |
+  +-------------------------------+---------------------------------------+
+  | Author : Shitalkumar S Chavan |     Date       : 31.10.2001           |
+  +-------------------------------+---------------------------------------+
+  | 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, struct pt_regs *regs)      |
++----------------------------------------------------------------------------+
+| Task              : Writes port value  To the selected port                |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
+|                     struct pt_regs *regs    : structure pointer            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+ void v_APCI2032_Interrupt(int irq, void *d, struct pt_regs *regs) 
+{ 
+       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/comedi/drivers/addi-data/hwdrv_apci2032.h b/comedi/drivers/addi-data/hwdrv_apci2032.h
new file mode 100644 (file)
index 0000000..0e64286
--- /dev/null
@@ -0,0 +1,62 @@
+/*********      Definitions for APCI-2032 card  *****/\r
+
+// Card Specific information
+#define APCI2032_BOARD_VENDOR_ID                 0x15B8
+#define APCI2032_ADDRESS_RANGE                   63
+
+\r
+//DIGITAL INPUT-OUTPUT DEFINE   \r
+\r
+#define APCI2032_DIGITAL_OP                    0 \r
+#define APCI2032_DIGITAL_OP_RW                         0 \r
+#define APCI2032_DIGITAL_OP_INTERRUPT           4\r
+#define APCI2032_DIGITAL_OP_IRQ                 12\r
+
+//Digital Output Interrupt Status\r
+#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS    8\r
+\r
+//Digital Output Interrupt Enable Disable.\r
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1\r
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE\r
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2\r
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD\r
+\r
+//ADDIDATA Enable Disable\r
+\r
+#define ADDIDATA_ENABLE                            1\r
+#define ADDIDATA_DISABLE                           0\r
+\r
+// TIMER COUNTER WATCHDOG DEFINES  \r
+\r
+#define ADDIDATA_WATCHDOG                          2\r
+#define APCI2032_DIGITAL_OP_WATCHDOG               16
+#define APCI2032_TCW_RELOAD_VALUE                  4\r
+#define APCI2032_TCW_TIMEBASE                      8\r
+#define APCI2032_TCW_PROG                          12\r
+#define APCI2032_TCW_TRIG_STATUS                   16\r
+#define APCI2032_TCW_IRQ                           20\r
+
+\r
+\r
+\r
+// Hardware Layer  functions for Apci2032\r
+\r
+\r
+//DO\r
+int i_APCI2032_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+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);
+\r
+// TIMER  \r
+// timer value is passed as u seconds\r
+INT i_APCI2032_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+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.....\r
+\r
+void v_APCI2032_Interrupt(int irq, void *d, struct pt_regs *regs) ;\r
+
+//Reset functions
+ int i_APCI2032_Reset(comedi_device *dev);     
diff --git a/comedi/drivers/addi-data/hwdrv_apci2200.c b/comedi/drivers/addi-data/hwdrv_apci2200.c
new file mode 100644 (file)
index 0000000..d530b0b
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+  +-----------------------------------------------------------------------+
+  | (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     : 13Card Linux Driver | Compiler   : GCC                  |
+  | Module name : hwdrv_apci2200.c|     Version    : 2.96                 |
+  +-------------------------------+---------------------------------------+
+  | Author : Karl Andrade         |     Date       : 18.12.2001           |
+  +-------------------------------+---------------------------------------+
+  | 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/comedi/drivers/addi-data/hwdrv_apci2200.h b/comedi/drivers/addi-data/hwdrv_apci2200.h
new file mode 100644 (file)
index 0000000..a71d166
--- /dev/null
@@ -0,0 +1,48 @@
+/*********      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/comedi/drivers/addi-data/hwdrv_apci3120.c b/comedi/drivers/addi-data/hwdrv_apci3120.c
new file mode 100644 (file)
index 0000000..effd7b6
--- /dev/null
@@ -0,0 +1,2441 @@
+
+
+
+/*
+  +-----------------------------------------------------------------------+
+  | (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.c  | Version  : 2.96  Redhat Linux         |
+  |                               |                    kernel-2.4.2       |
+  +-------------------------------+---------------------------------------+
+  | Author    :                          | Date     :                                    |
+  +-----------------------------------------------------------------------+
+  | 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);
+           if((us_TmpValue & 0x00B0)==0x00B0)
+              {
+                   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<<4) & 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<<4) & 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); 
+        //printk("Stopped cyclic acquisition\n");  
+       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;
+       devpriv->AiData=s->async->data;
+       devpriv->ui_AiDataLength=s->async->data_len;
+       
+       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)
+{
+        float f_DelayValue,f_ConvertValue;
+       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;
+   
+         devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE;
+       //Flush FIFO
+       inb(dev->iobase+APCI3120_RESET_FIFO);  
+       inw(dev->iobase+APCI3120_RD_STATUS);
+
+        
+        // clear software  registers
+
+           devpriv->b_TimerSelectMode=0;
+           devpriv->b_DigitalOutputRegister=0;
+           devpriv->us_OutputRegister=0;
+          devpriv->b_ModeSelectRegister=0;
+
+          /****************************/
+          /* 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);
+
+
+           /**************************/
+          /* 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);
+
+
+          devpriv->ui_AiActualScan=0;
+          devpriv->ui_AiActualScanPosition=0;
+          s->async->cur_chan=0;
+          devpriv->ui_AiBufferPtr=0;
+          devpriv->ui_DmaActualBuffer=0;
+
+
+
+
+         ui_TimerValue2 = devpriv->ui_AiNbrofScans-2; // value for timer2  minus -2 has to be done .....dunno y??   
+         ui_ConvertTiming=devpriv->ui_AiTimer0;
+  
+         if(mode==2) ui_DelayTiming =  devpriv->ui_AiTimer1; 
+
+
+          // initialise sequence ram
+
+         if (!i_APCI3120_SetupChannelList(dev, s, devpriv->ui_AiNbrofChannels, devpriv->pui_AiChannelList, 0)) 
+         return -EINVAL;
+
+        us_TmpValue=(USHORT) inw(dev->iobase+APCI3120_RD_STATUS);  
+        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;
+               }
+       }
+       
+       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<<4) & 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<<4) & 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#################
+
+       //disable the scan bit
+       devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN;
+       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<<4) & 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<<4) & 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 
+                inw(dev->iobase+0);// reset EOC bit    
+                devpriv->b_InterruptMode=APCI3120_DMA_MODE;
+
+               // disable EOC and 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
+               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); 
+               //2  No change
+               // A2P FIFO MANAGEMENT
+               // A2P fifo reset  & transfer control enable
+               outl(APCI3120_A2P_FIFO_MANAGEMENT,devpriv->i_IobaseAmcc+AMCC_OP_REG_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);
+               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);  
+
+               //6 
+               //ENABLE A2P FIFO WRITE AND ENABLE AMWEN 
+               // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+               outw(3,devpriv->i_IobaseAddon + 4);
+
+               //7
+               //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);        
+
+         }
+      
+        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 
+       
+       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);       
+        }
+       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,            | 
+|                        struct pt_regs *regs)                                                                  |
+|                                                                                                               |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| 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                                                                                        |
+|                      struct pt_regs *regs                                                             |
+|                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      : void                                                                      |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+
+ void v_APCI3120_Interrupt(int irq, void *d, struct pt_regs *regs) 
+{      
+       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;
+                        comedi_done(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))
+         {
+               
+               //DPRINTK("\n interrupt is DMA\n");
+                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,regs); // do some data transfer
+               }
+                else
+                {
+               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;
+}  
+
+
+
+
+
+
+/*
++----------------------------------------------------------------------------+
+| Function name     : void v_APCI3120_InterruptDma(int irq, void *d,         |
+|                       struct pt_regs *regs)                                                                   |
+|                                                                                                               |
++----------------------------------------------------------------------------+
+| 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, struct pt_regs *regs                            |
+|                                                                                                                               |
++----------------------------------------------------------------------------+
+| Return Value      :  void                                                                     |
+|                                                                                                                           |
++----------------------------------------------------------------------------+
+*/
+
+ void v_APCI3120_InterruptDma(int irq, void *d, struct pt_regs *regs) 
+{
+       comedi_device *dev = d;
+       comedi_subdevice *s = dev->subdevices + 0;
+       sampl_t *ptr;
+       unsigned int next_dma_buf, samplesinbuf,m;
+       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);
+       //rt_printk("\nSamples in buffer=%d \n", samplesinbuf);
+       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;
+               comedi_error_done(dev,s);
+               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 
+
+               // 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[next_dma_buf];
+               low_word=var & 0xffff;
+               var=devpriv->ul_DmaBufferHw[next_dma_buf];
+               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[next_dma_buf];
+               low_word=var & 0xffff;
+               var=devpriv->ui_DmaBufferUsesize[next_dma_buf];
+               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);        
+                 
+       }
+       
+       ptr=(sampl_t *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer];
+          
+       
+       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 (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) 
+                                       comedi_eos(dev,s);  
+                       }
+               }
+       }
+        devpriv->ui_AiActualScanPosition=m;
+       s->async->cur_chan=j;
+                
+}
+
+
+
+
+
+/*
++----------------------------------------------------------------------------+
+|                           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);
+       
+       //Testing if board have the new Quartz and calculate the time value to set in the timer
+       if((us_TmpValue & 0x00B0)==0x00B0)
+       {
+               //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<<4) & 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<<4) & 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<<4) & 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<<4) & 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);
+
+                       //Testing if board have the new Quartz and calculate the time value to set in the timer
+                       if((us_TmpValue & 0x00B0)==0x00B0)
+                       {
+                       //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<<4) & 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<<4) & 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<<4) & 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<<4) & 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;
+       
+       }
+        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)|ui_Temp;
+                   break;
+       
+           case 2 :data[0]=data[0]<<4;  
+                  break;
+           default :printk("\nThe parameter passed is in error \n");
+                    return -EINVAL;
+           }// switch(data[1])
+        outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+        ui_Temp=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);
+                   data[0]=(data[0]<<4)|ui_Temp;
+                   break;
+       
+           case 2 :
+                   data[0]=~data[0]&0x1;
+                   ui_Temp1=1;   
+                   ui_Temp1=ui_Temp1<<ui_NoOfChannel;
+                   ui_Temp1=ui_Temp1<<4; 
+                   ui_Temp=ui_Temp|ui_Temp1;
+                   data[0]=(data[0] << ui_NoOfChannel)^0xf;
+                   data[0]=data[0]<<4;
+                   data[0]=data[0]& ui_Temp;
+                   break;
+          default :printk("\nThe parameter passed is in error \n");
+                    return -EINVAL;
+           }// switch(data[1])
+               outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+        ui_Temp=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/comedi/drivers/addi-data/hwdrv_apci3120.h b/comedi/drivers/addi-data/hwdrv_apci3120.h
new file mode 100644 (file)
index 0000000..c653d71
--- /dev/null
@@ -0,0 +1,260 @@
+
+// hwdrv_apci3120.h
+
+
+/*
+  +-----------------------------------------------------------------------+
+  | (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 
+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
+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, struct pt_regs *regs) ;
+void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n);
+int i_APCI3120_InterruptHandleEos(comedi_device *dev);
+void v_APCI3120_InterruptDma(int irq, void *d, struct pt_regs *regs) ;
+
+
+
+
+// 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/comedi/drivers/addi-data/hwdrv_apci3200.c b/comedi/drivers/addi-data/hwdrv_apci3200.c
new file mode 100644 (file)
index 0000000..e099ca8
--- /dev/null
@@ -0,0 +1,2414 @@
+/*
+  +-----------------------------------------------------------------------+
+  | (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     : 13Card Linux Driver | Compiler   : GCC                  |
+  | Module name : hwdrv_apci3200.c|     Version    : 2.96                 |
+  +-------------------------------+---------------------------------------+
+  | Author : Shitalkumar S Chavan |     Date       : 10.12.2001           |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-3200                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  |          |           |                                                |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+|                               Included files                               |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci3200.h"
+INT i_CJCAvailable=1; 
+INT i_CJCPolarity=0;
+INT i_CJCGain=0;
+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
+/*
++----------------------------------------------------------------------------+
+| 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;                 
+   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)
+   
+          
+   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]; 
+   while(i_InterruptFlag==1)
+     {
+      udelay(1);
+     }
+    
+   ui_ChannelNo = CR_CHAN(insn->chanspec); // get the channel
+   i_ChannelNo=ui_ChannelNo; 
+   ui_Channel_num =ui_ChannelNo;
+ 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)
+                {
+                i_Offset=0;
+                }//if(ui_ChannelNo >=0 && ui_ChannelNo <=3) 
+              if(ui_ChannelNo >=4 && ui_ChannelNo <=7)
+                {
+                i_Offset=64;
+                }//if(ui_ChannelNo >=4 && ui_ChannelNo <=7) 
+              if(ui_ChannelNo >=8 && ui_ChannelNo <=11)
+                {
+                i_Offset=128;
+                }//if(ui_ChannelNo >=8 && ui_ChannelNo <=11) 
+              if(ui_ChannelNo >=12 && ui_ChannelNo <=15)
+                {
+                i_Offset=192;
+                }//if(ui_ChannelNo >=12 && ui_ChannelNo <=15)
+                break;
+          case 1:
+                if(data[14]==2)
+                  {
+                   if(ui_ChannelNo ==0 )
+                   {
+                   i_Offset=0;
+                   }//if(ui_ChannelNo ==0 )
+                 if(ui_ChannelNo ==1)
+                   { 
+                   i_Offset=64;
+                   }// if(ui_ChannelNo ==1)
+                 if(ui_ChannelNo ==2 )
+                   {
+                   i_Offset=128;
+                   }//if(ui_ChannelNo ==2 )
+                 if(ui_ChannelNo ==3)
+                   {
+                   i_Offset=192;
+                   }//if(ui_ChannelNo ==3) 
+                   i_ChannelNo=0;
+                   ui_ChannelNo=0;
+                   break;   
+                  }//if(data[14]==2)
+                if(ui_ChannelNo >=0 && ui_ChannelNo <=1)
+                   {
+                   i_Offset=0;
+                   }//if(ui_ChannelNo >=0 && ui_ChannelNo <=1) 
+                 if(ui_ChannelNo >=2 && ui_ChannelNo <=3)
+                   {
+                   i_ChannelNo=i_ChannelNo-2;
+                   ui_ChannelNo=ui_ChannelNo-2; 
+                   i_Offset=64;
+                   }//if(ui_ChannelNo >=2 && ui_ChannelNo <=3) 
+                 if(ui_ChannelNo >=4 && ui_ChannelNo <=5)
+                   {
+                   i_ChannelNo=i_ChannelNo-4;
+                   ui_ChannelNo=ui_ChannelNo-4; 
+                   i_Offset=128;
+                   }//if(ui_ChannelNo >=4 && ui_ChannelNo <=5) 
+                 if(ui_ChannelNo >=6 && ui_ChannelNo <=7)
+                   {
+                   i_ChannelNo=i_ChannelNo-6;
+                   ui_ChannelNo=ui_ChannelNo-6; 
+                   i_Offset=192;
+                   }//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:i_Offset=0;
+                break;
+         case 2:i_Offset=64;
+                break;
+         case 3:i_Offset=128;
+                break;
+         case 4:i_Offset=192;
+                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)
+      {
+      i_Count=0;
+      i_Sum=0;
+      }//if(i_ScanType!=1)
+    
+      
+  
+    ul_Config =  data[1] |(data[2] << 6) |(data[5]<< 7) |(data[3] << 8) |(data[4] << 9);
+                              
+                              
+                              
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);                   
+              /*********************************/
+              /* Write the channel to configure*/
+              /*********************************/
+              outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4);
+            
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); 
+              /**************************/                                                          
+              /* Reset the configuration */                                                           
+              /**************************/  
+               outl(0 , devpriv->iobase+i_Offset + 0x0);  
+            
+               while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+                  
+              /***************************/
+              /* Write the configuration */
+              /***************************/
+              outl(ul_Config , devpriv->iobase+i_Offset + 0x0);
+
+              /***************************/
+              /*Reset the calibration bit*/
+              /***************************/
+              ul_Temp = inl(devpriv->iobase+i_Offset + 12);
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+i_Offset + 12);
+              if(data[9]==1)
+                 {
+                 devpriv->tsk_Current=current;
+                 i_InterruptFlag=1;
+                 }// if(data[9]==1)
+              else
+                 {
+                  i_InterruptFlag=0;
+                 }//else  if(data[9]==1)
+              i_Initialised=1;
+              if(i_ScanType==1)
+                 {
+                 i_Sum=i_Sum+1;
+                 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 
++----------------------------------------------------------------------------+
+| 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;
+   
+   
+   if(i_Initialised==0)
+     {
+     printk("\nThe channel is not initialised\n");
+     i_APCI3200_Reset(dev);
+     return -EINVAL;
+     }//if(i_Initialised==0);
+     
+         
+   switch(insn->unused[0])
+      {
+      case 0:     
+           
+             i_APCI3200_Read1AnalogInputChannel(dev,s,insn,&ui_DummyValue);
+             ui_InterruptChannelValue[i_Count+0]=ui_DummyValue; 
+
+             if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))
+                {
+                i_APCI3200_ReadCJCValue(dev,&ui_DummyValue);
+                ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue; 
+                }//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE))
+             else
+                {
+                  ui_InterruptChannelValue[i_Count + 3]=0;
+                }//elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))  
+             if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE))    
+                {  
+                i_APCI3200_ReadCalibrationOffsetValue(dev,&ui_DummyValue);
+                ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue;  
+                i_APCI3200_ReadCalibrationGainValue(dev,&ui_DummyValue);  
+                ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue; 
+                }//if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) 
+             if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1))
+                {
+                /**********************************************************/
+                /*Test if the Calibration channel must be read for the CJC*/
+                /**********************************************************/
+                 /**********************************/
+                 /*Test if the polarity is the same*/
+                 /**********************************/                                     
+                 if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                    {
+                    i_ConvertCJCCalibration=1;
+                    }//if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                 else 
+                    {
+                    if(i_CJCGain==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)
+                   {
+                   i_APCI3200_ReadCJCCalOffset(dev,&ui_DummyValue);
+                   ui_InterruptChannelValue[i_Count+4]=ui_DummyValue;
+                   i_APCI3200_ReadCJCCalGain(dev,&ui_DummyValue);
+                   ui_InterruptChannelValue[i_Count+5]=ui_DummyValue;
+                   }//if(i_ConvertCJCCalibration==1)
+                else
+                   {
+                    ui_InterruptChannelValue[i_Count+4]=0;
+                    ui_InterruptChannelValue[i_Count+5]=0;
+                   }//elseif(i_ConvertCJCCalibration==1) 
+                }//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) 
+                if(i_ScanType!=1)
+                   {
+                   i_Count=0;
+                   }//if(i_ScanType!=1)
+                else  
+                   {
+                   i_Count=i_Count +6;
+                   }//else if(i_ScanType!=1)  
+                if((i_ScanType==1) &&(i_InterruptFlag==1))
+                   {
+                   i_Count=i_Count-6;
+                   } 
+                if(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];  
+                  
+
+                  }   
+                 break;
+         case 1 :
+                for(i=0;i<insn->n;i++)
+                  { 
+                  data[i]=ui_InterruptChannelValue[i]; 
+                  }
+
+                  i_Count=0;
+                  i_Sum=0;
+                if(i_ScanType==1)
+                  {           
+                  i_Initialised=0; 
+                  i_InterruptFlag=0; 
+                  }   
+                 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;
+     
+ ui_ChannelNo=i_ChannelNo;
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);                   
+              /*********************************/
+              /* Write the channel to configure*/
+              /*********************************/
+              outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+           
+/*******************************/
+/* Set the convert timing unit */
+/*******************************/
+while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);                             
+/**************************/
+/* Set the convert timing */
+/**************************/
+while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+outl(i_ADDIDATAConversionTime , devpriv->iobase+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)
+   { 
+   /************************/
+   /* 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);
+    outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
+   /*****************************/
+   /*Test if interrupt is enable*/
+   /*****************************/              
+if (i_InterruptFlag == ADDIDATA_DISABLE)
+   {
+    do
+       {
+        /*************************/
+        /*Read the EOC Status bit*/
+        /*************************/
+                    
+        ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+
+       } while (ui_EOC != 1);
+                
+
+        /***************************************/
+        /* Read the digital value of the input */
+        /***************************************/
+                
+
+        data[0] = inl (devpriv->iobase+i_Offset + 28);
+
+              
+    }// 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;
+    while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);                   
+              /*********************************/
+              /* Write the channel to configure*/
+              /*********************************/
+              outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+   
+              /*******************************/
+              /* Set the convert timing unit */
+              /*******************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+              /**************************/
+              /* Set the convert timing */
+              /**************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+              /*****************************/
+              /*Read the calibration offset*/
+              /*****************************/
+               ui_Temp = inl(devpriv->iobase+i_Offset + 12);
+
+              /*********************************/
+              /*Configure the Offset Conversion*/
+              /*********************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12);
+              /*******************************/
+              /*Initialise ui_CommandRegister*/
+              /*******************************/
+             
+              ui_CommandRegister = 0;
+
+              /*********************************/
+              /*Test if the interrupt is enable*/
+              /*********************************/
+
+              if (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);
+              outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
+
+              /*****************************/
+              /*Test if interrupt is enable*/
+              /*****************************/
+              
+              if (i_InterruptFlag == ADDIDATA_DISABLE)
+                 {
+            
+                 do
+                    {
+                    /*******************/
+                    /*Read the EOC flag*/
+                    /*******************/
+                    
+                    ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1;
+
+                    } while (ui_EOC != 1);
+                
+
+                 /**************************************************/
+                 /*Read the digital value of the calibration Offset*/
+                 /**************************************************/
+                 
+
+                 data[0] = inl(devpriv->iobase+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);                   
+              /*********************************/
+              /* Write the channel to configure*/
+              /*********************************/
+              outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+    
+              /***************************/
+              /*Read the calibration gain*/
+              /***************************/
+              /*******************************/
+              /* Set the convert timing unit */
+              /*******************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+              /**************************/
+              /* Set the convert timing */
+              /**************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+              /*******************************/
+              /*Configure the Gain Conversion*/
+              /*******************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(0x00040000 , devpriv->iobase+i_Offset + 12);
+             
+
+              /*******************************/
+              /*Initialise ui_CommandRegister*/
+              /*******************************/
+
+              ui_CommandRegister = 0;
+
+              /*********************************/
+              /*Test if the interrupt is enable*/
+              /*********************************/
+              
+              if (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);
+              outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
+
+              /*****************************/
+              /*Test if interrupt is enable*/
+              /*****************************/
+              
+              if (i_InterruptFlag == ADDIDATA_DISABLE)
+                 {
+               
+                 do
+                    {
+                   
+                    /*******************/
+                    /*Read the EOC flag*/
+                    /*******************/
+                    
+                    ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+
+                    } while (ui_EOC != 1);
+                 
+                 /************************************************/
+                 /*Read the digital value of the calibration Gain*/
+                 /************************************************/
+
+                 data[0] = inl(devpriv->iobase+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);
+            outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+              /**************************/
+              /* Set the convert timing */
+              /**************************/
+             while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+             outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);  
+
+              /******************************/
+              /*Configure the CJC Conversion*/
+              /******************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl( 0x00000400 , devpriv->iobase+i_Offset + 4);
+              /*******************************/
+              /*Initialise dw_CommandRegister*/
+              /*******************************/
+              ui_CommandRegister = 0;
+             /*********************************/
+             /*Test if the interrupt is enable*/
+             /*********************************/  
+             if (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);
+              outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
+         
+              /*****************************/
+              /*Test if interrupt is enable*/
+              /*****************************/
+              
+              if (i_InterruptFlag == ADDIDATA_DISABLE)
+                 {
+                 do
+                    {
+                   
+                    /*******************/
+                    /*Read the EOC flag*/
+                    /*******************/
+                    
+                    ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+
+                    } while (ui_EOC != 1);
+                 
+                 /***********************************/
+                 /*Read the digital value of the CJC*/
+                 /***********************************/
+                 
+                 data[0] = inl(devpriv->iobase+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);
+              outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+              /**************************/
+              /* Set the convert timing */
+              /**************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);               
+              /******************************/
+              /*Configure the CJC Conversion*/
+              /******************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(0x00000400 , devpriv->iobase+i_Offset + 4); 
+              /*********************************/
+              /*Configure the Offset Conversion*/
+              /*********************************/
+              while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+              outl(0x00020000, devpriv->iobase+i_Offset + 12); 
+              
+              /*******************************/
+              /*Initialise ui_CommandRegister*/
+              /*******************************/
+              ui_CommandRegister = 0;
+              /*********************************/
+              /*Test if the interrupt is enable*/
+              /*********************************/
+              
+             if (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);
+              outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8);  
+              if (i_InterruptFlag == ADDIDATA_DISABLE)
+                 {
+                 do
+                    {
+                    /*******************/
+                    /*Read the EOC flag*/
+                    /*******************/
+                    ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                    } while (ui_EOC != 1);
+                 
+                 /**************************************************/
+                 /*Read the digital value of the calibration Offset*/
+                 /**************************************************/
+                 data[0] = inl(devpriv->iobase+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);
+ outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+ /**************************/
+ /* Set the convert timing */
+ /**************************/
+  while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+   outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+ /******************************/
+ /*Configure the CJC Conversion*/
+ /******************************/
+  while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+  outl(0x00000400,devpriv->iobase+i_Offset + 4); 
+/*******************************/
+/*Configure the Gain Conversion*/
+/*******************************/
+ while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+ outl(0x00040000,devpriv->iobase+i_Offset + 12);             
+
+ /*******************************/
+ /*Initialise dw_CommandRegister*/
+ /*******************************/
+   ui_CommandRegister = 0;            
+/*********************************/
+/*Test if the interrupt is enable*/
+/*********************************/
+ if (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);
+outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8);
+if (i_InterruptFlag == ADDIDATA_DISABLE)
+    {
+      do
+         {            
+         /*******************/
+         /*Read the EOC flag*/
+         /*******************/
+          ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;      
+         } while (ui_EOC != 1);         
+       /************************************************/
+       /*Read the digital value of the calibration Gain*/
+       /************************************************/
+        data[0] = inl (devpriv->iobase+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)
+   {
+   printk("\nThe channel is not initialised\n");
+   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);
+  outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+      /*************************/
+      /*Set the time unit to ns*/
+      /*************************/
+     /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+      i_ADDIDATAConversionTimeUnit= 1;*/
+       i_Temp= i_InterruptFlag ;  
+      i_InterruptFlag = ADDIDATA_DISABLE;
+      i_APCI3200_Read1AnalogInputChannel(dev,s,insn,data); 
+       if(i_AutoCalibration == FALSE)
+         {
+          while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+          outl((0x00001000 |i_ChannelNo) , devpriv->iobase+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);
+     outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); 
+     ui_Configuration = inl(devpriv->iobase+i_Offset + 0);
+      /*************************/
+      /*Set the time unit to ns*/
+      /*************************/
+     /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+      i_ADDIDATAConversionTimeUnit= 1;*/
+       i_Temp= i_InterruptFlag ;  
+      i_InterruptFlag = ADDIDATA_DISABLE;
+      i_APCI3200_Read1AnalogInputChannel(dev,s,insn,data); 
+      if(i_AutoCalibration == FALSE)
+         {
+         while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+         outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+          data++;
+          i_APCI3200_ReadCalibrationOffsetValue(dev,data);
+          data++;     
+          i_APCI3200_ReadCalibrationGainValue(dev,data);    
+         }
+     }
+          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)
+          {
+          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];
+         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;
+                 }
+            d_SCANTimeNewUnit = (double)ui_DelayTime;
+            i_NbrOfChannel= i_LastChannel-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++;
+                       }           
+            }//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;
+ /*******************/
+ /*Read the register*/
+ /*******************/
+  ui_Configuration = inl(devpriv->iobase+i_Offset + 8);             
+/*****************************/
+/*Reset the START and IRQ bit*/
+/*****************************/
+ while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+ outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+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];
+     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; 
+            }
+       printk("\nui_ConvertTime=%u\n",ui_ConvertTime);
+       printk("\nui_ConvertTimebase=%u\n",ui_ConvertTimeBase);
+    // if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2)))
+     //   {
+     /**************************************************/
+     /*Read the old configuration of the current source*/
+     /**************************************************/   
+     ui_Configuration = inl(devpriv->iobase+i_Offset + 12);
+     /***********************************************/
+     /*Write the configuration of the current source*/
+     /***********************************************/
+     while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+    outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+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_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);
+        outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8);          
+     /***********************/
+     /*Write the Delay Value*/
+     /***********************/
+     while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+     outl(ui_DelayTime,devpriv->iobase+i_Offset + 40);                      
+      /***************************/
+      /*Write the Delay time base*/
+      /***************************/
+      while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+      outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44);                      
+      /*********************************/
+      /*Write the conversion time value*/
+      /*********************************/
+       while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32);                  
+       /********************************/
+       /*Write the conversion time base*/
+       /********************************/
+       while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36);          
+        /*******************/
+        /*Read the register*/
+        /*******************/
+         ui_Configuration = inl(devpriv->iobase+i_Offset + 4);       
+       /******************/
+       /*Set the SCAN bit*/
+       /******************/
+       while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+
+       outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4);                  
+      /*******************/
+      /*Read the register*/
+      /*******************/
+       ui_Configuration=0;       
+       ui_Configuration = inl(devpriv->iobase+i_Offset + 8);
+
+       /*******************/
+        /*Set the START bit*/
+        /*******************/
+       while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       outl((ui_Configuration | 0x00080000),devpriv->iobase+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;
+
+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;
+   }//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, struct pt_regs *regs)                              |
++----------------------------------------------------------------------------+
+| Task              : Interrupt processing Routine                           |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
+|                     struct pt_regs *regs    : structure pointer            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error                                      |
+|                                                                                               |
++----------------------------------------------------------------------------+
+*/
+ void v_APCI3200_Interrupt(int irq, void *d, struct pt_regs *regs) 
+{      
+ 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;
+ int k;
+
+switch(i_ScanType)
+   {
+    case 0: 
+    case 1: 
+          switch(i_ADDIDATAType)
+             {        
+              case 0:
+              case 1: 
+             
+             /************************************/
+             /*Read the interrupt status register*/
+             /************************************/
+             ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+             if ((ui_StatusRegister & 0x2) == 0x2)
+                {
+                i_CalibrationFlag = ((inl(devpriv->iobase+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);
+                /***********************************************/
+                /* Test if the value read is the channel value */
+                /***********************************************/
+                if (i_CalibrationFlag == 0)
+                  {
+                   ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput;
+
+                   /******************************************************/
+                   /*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;
+
+                 /******************************************************/
+                 /* 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;
+                if(i_ScanType==1)
+                   { 
+
+                   i_InterruptFlag=0;
+                   i_Count=i_Count + 6;
+                   }//if(i_ScanType==1)
+                else
+                  {
+                  i_Count=0;
+                  }//elseif(i_ScanType==1)
+                if(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)
+                    {
+
+                    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);
+                 /*************************/
+                 /*Test if interrupt occur*/
+                 /*************************/
+     
+
+                if ((ui_StatusRegister & 0x2) == 0x2)
+                  {
+           
+                  i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10);
+
+                  i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17);
+
+                /*************************/
+                /*Read the channel number*/
+                /*************************/
+           
+                   ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+
+           
+                   /************************************/
+                   /*Read the digital temperature value*/
+                   /************************************/
+                   ui_DigitalTemperature = inl(devpriv->iobase+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;
+
+                    /*********************************/
+                    /*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;
+
+              
+                /******************************************************/
+                /*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;
+
+                 /****************************************************/
+                 /*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;
+
+                   /**********************************************************/
+                   /*Test if the Calibration channel must be read for the CJC*/
+                   /**********************************************************/
+              
+                    /*Test if the polarity is the same*/
+                    /**********************************/                                     
+                    if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                       {
+                       i_ConvertCJCCalibration=1;
+                       }//if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                    else 
+                       {
+                       if(i_CJCGain==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;
+
+                     }//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; 
+
+                  /****************************************************************/
+                  /*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;  
+
+                  if(i_ScanType==1)
+                     { 
+
+                     i_InterruptFlag=0;
+                     i_Count=i_Count + 6;
+                     }//if(i_ScanType==1)
+                  else
+                     {
+                     i_Count=0;
+                     }//elseif(i_ScanType==1)
+                  if(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)
+                      {
+                      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;
+       UINT ui_ChannelNumber = 0;
+       UINT *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
+       
+           /************************************/
+           /*Read the interrupt status register*/
+           /************************************/
+           ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+           /*************************/
+           /*Test if interrupt occur*/
+           /*************************/
+        
+          if ((ui_StatusRegister & 0x2) == 0x2)
+            {
+           /*************************/
+           /*Read the channel number*/
+           /*************************/
+            ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+
+           /*************************************/
+           /*Read the digital Analog Input value*/
+           /*************************************/
+
+           data[i_Count] = inl(devpriv->iobase+i_Offset + 28);
+//           printk("\ndata[%d]=%x\n",i_Count,data[i_Count]);
+            if((i_Count == (i_LastChannel-i_FirstChannel+3)))
+             {
+               i_Count=-1; 
+             async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
+             async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
+             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);
+              }
+            }  
+           i_Count++;
+            }
+        i_InterruptFlag=0;
+       return 0;
+}  
+
+
+       
diff --git a/comedi/drivers/addi-data/hwdrv_apci3200.h b/comedi/drivers/addi-data/hwdrv_apci3200.h
new file mode 100644 (file)
index 0000000..8b12313
--- /dev/null
@@ -0,0 +1,109 @@
+// Card Specific information\r
+#define APCI3200_BOARD_VENDOR_ID                 0x15B8\r
+//#define APCI3200_ADDRESS_RANGE                   264\r
+
+
+
+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 
+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)
+       }
+};
+
+//Analog Input related Defines\r
+#define APCI3200_AI_OFFSET_GAIN                  0\r
+#define APCI3200_AI_SC_TEST                      4\r
+#define APCI3200_AI_IRQ                          8\r
+#define APCI3200_AI_AUTOCAL                      12\r
+#define APCI3200_RELOAD_CONV_TIME_VAL            32\r
+#define APCI3200_CONV_TIME_TIME_BASE             36\r
+#define APCI3200_RELOAD_DELAY_TIME_VAL           40\r
+#define APCI3200_DELAY_TIME_TIME_BASE            44\r
+#define APCI3200_AI_MODULE1                      0\r
+#define APCI3200_AI_MODULE2                      64\r
+#define APCI3200_AI_MODULE3                      128\r
+#define APCI3200_AI_MODULE4                      192\r
+#define TRUE                                     1
+#define FALSE                                    0
+#define APCI3200_AI_EOSIRQ                       16\r
+#define APCI3200_AI_EOS                          20\r
+#define APCI3200_AI_CHAN_ID                      24\r
+#define APCI3200_AI_CHAN_VAL                     28\r
+#define ANALOG_INPUT                             0\r
+#define TEMPERATURE                              1\r
+#define RESISTANCE                               2\r
+\r
+#define ENABLE_EXT_TRIG                          1\r
+#define ENABLE_EXT_GATE                          2\r
+#define ENABLE_EXT_TRIG_GATE                     3\r
+\r
+\r
+#define APCI3200_MAXVOLT                         2.5\r
+#define ADDIDATA_GREATER_THAN_TEST               0\r
+#define ADDIDATA_LESS_THAN_TEST                  1\r
+\r
+#define ADDIDATA_UNIPOLAR                        1\r
+#define ADDIDATA_BIPOLAR                         2\r
+\r
+//ADDIDATA Enable Disable\r
+#define ADDIDATA_ENABLE                            1\r
+#define ADDIDATA_DISABLE                           0\r
+
+typedef struct
+   {
+   ULONG ul_NumberOfValue;
+   ULONG *pul_ResistanceValue;
+   ULONG *pul_TemperatureValue;
+   }str_ADDIDATA_RTDStruct,*pstr_ADDIDATA_RTDStruct;
+\r
+\r
+// Hardware Layer  functions for Apci3200\r
+\r
+//AI\r
+
+INT i_APCI3200_ConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+INT i_APCI3200_ReadAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);\r
+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\r
+void v_APCI3200_Interrupt(int irq, void *d, struct pt_regs *regs) ;\r
+int i_APCI3200_InterruptHandleEos(comedi_device *dev);\r
+//Reset functions\r
+INT i_APCI3200_Reset(comedi_device *dev);      \r
+
+
+int i_APCI3200_ReadCJCCalOffset(comedi_device *dev,lsampl_t *data);\r
+int i_APCI3200_ReadCJCValue(comedi_device *dev,lsampl_t *data);\r
+int i_APCI3200_ReadCalibrationGainValue(comedi_device *dev,UINT *data);\r
+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);\r
diff --git a/comedi/drivers/addi-data/hwdrv_apci3501.c b/comedi/drivers/addi-data/hwdrv_apci3501.c
new file mode 100644 (file)
index 0000000..a585029
--- /dev/null
@@ -0,0 +1,706 @@
+/*
+  +-----------------------------------------------------------------------+
+  | (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     : 13Card Linux Driver | Compiler   : GCC                  |
+  | Module name : hwdrv_apci3501.c|     Version    : 2.96                 |
+  +-------------------------------+---------------------------------------+
+  | Author : Shitalkumar S Chavan |     Date       : 10.12.2001           |
+  +-------------------------------+---------------------------------------+
+  | 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, struct pt_regs *regs)      |
++----------------------------------------------------------------------------+
+| Task              : Interrupt processing Routine                           |
++----------------------------------------------------------------------------+
+| Input Parameters  : int irq                 : irq number                   |
+|                     void *d                 : void pointer                 |
+|                     struct pt_regs *regs    : structure pointer            |
++----------------------------------------------------------------------------+
+| Output Parameters :  --                                                                                                       |
++----------------------------------------------------------------------------+
+| Return Value      : TRUE  : No error occur                                 |
+|                          : FALSE : Error occur. Return the error          |
+|                                                                               |
++----------------------------------------------------------------------------+
+*/
+ void v_APCI3501_Interrupt(int irq, void *d, struct pt_regs *regs) 
+{
+    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/comedi/drivers/addi-data/hwdrv_apci3501.h b/comedi/drivers/addi-data/hwdrv_apci3501.h
new file mode 100644 (file)
index 0000000..957abae
--- /dev/null
@@ -0,0 +1,71 @@
+// 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, struct pt_regs *regs) ;
+
+//Reset functions
+ int i_APCI3501_Reset(comedi_device *dev);     
+
+
+
+
+
+