]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
Merge branch 'omap-pool'
[linux-2.6-omap-h63xx.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci3200.c
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
new file mode 100644 (file)
index 0000000..1ff66be
--- /dev/null
@@ -0,0 +1,3642 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+
+        ADDI-DATA GmbH
+        Dieselstrasse 3
+        D-77833 Ottersweier
+        Tel: +19(0)7223/9493-0
+        Fax: +49(0)7223/9493-92
+        http://www.addi-data-com
+        info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+  +-----------------------------------------------------------------------+
+  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
+  +-----------------------------------------------------------------------+
+  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
+  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
+  +-------------------------------+---------------------------------------+
+  | Project     : APCI-3200       | Compiler   : GCC                      |
+  | Module name : hwdrv_apci3200.c| Version    : 2.96                     |
+  +-------------------------------+---------------------------------------+
+  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
+  +-------------------------------+---------------------------------------+
+  | Description :   Hardware Layer Acces For APCI-3200                    |
+  +-----------------------------------------------------------------------+
+  |                             UPDATES                                   |
+  +----------+-----------+------------------------------------------------+
+  |   Date   |   Author  |          Description of updates                |
+  +----------+-----------+------------------------------------------------+
+  | 02.07.04 | J. Krauth | Modification from the driver in order to       |
+  |          |           | correct some errors when using several boards. |
+  |          |           |                                                |
+  |          |           |                                                |
+  +----------+-----------+------------------------------------------------+
+  | 26.10.04 | J. Krauth | - Update for COMEDI 0.7.68                     |
+  |          |           | - Read eeprom value                            |
+  |          |           | - Append APCI-3300                             |
+  +----------+-----------+------------------------------------------------+
+*/
+
+/*
+  +----------------------------------------------------------------------------+
+  |                               Included files                               |
+  +----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci3200.h"
+//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+#include "addi_amcc_S5920.h"
+//#define PRINT_INFO
+
+//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+//BEGIN JK 06.07.04: Management of sevrals boards
+/*
+  INT i_CJCAvailable=1;
+  INT i_CJCPolarity=0;
+  INT i_CJCGain=2;//changed from 0 to 2
+  INT i_InterruptFlag=0;
+  INT i_ADDIDATAPolarity;
+  INT i_ADDIDATAGain;
+  INT i_AutoCalibration=0;   //: auto calibration
+  INT i_ADDIDATAConversionTime;
+  INT i_ADDIDATAConversionTimeUnit;
+  INT i_ADDIDATAType;
+  INT i_ChannelNo;
+  INT i_ChannelCount=0;
+  INT i_ScanType;
+  INT i_FirstChannel;
+  INT i_LastChannel;
+  INT i_Sum=0;
+  INT i_Offset;
+  UINT ui_Channel_num=0;
+  static int i_Count=0;
+  INT i_Initialised=0;
+  UINT ui_InterruptChannelValue[96]; //Buffer
+*/
+str_BoardInfos s_BoardInfos[100];      // 100 will be the max number of boards to be used
+//END JK 06.07.04: Management of sevrals boards
+
+//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+/*+----------------------------------------------------------------------------+*/
+/*| Function   Name   : INT i_AddiHeaderRW_ReadEeprom                          |*/
+/*|                               (INT    i_NbOfWordsToRead,                   |*/
+/*|                                DWORD dw_PCIBoardEepromAddress,             |*/
+/*|                                WORD   w_EepromStartAddress,                |*/
+/*|                                PWORD pw_DataRead)                          |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Task              : Read word from the 5920 eeprom.                        |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Input Parameters  : INT    i_NbOfWordsToRead : Nbr. of word to read        |*/
+/*|                     DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+/*|                     WORD   w_EepromStartAddress : Eeprom strat address     |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Output Parameters : PWORD pw_DataRead : Read data                          |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Return Value      : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+
+INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+       DWORD dw_PCIBoardEepromAddress,
+       WORD w_EepromStartAddress, PWORD pw_DataRead)
+{
+       DWORD dw_eeprom_busy = 0;
+       INT i_Counter = 0;
+       INT i_WordCounter;
+       INT i;
+       BYTE pb_ReadByte[1];
+       BYTE b_ReadLowByte = 0;
+       BYTE b_ReadHighByte = 0;
+       BYTE b_SelectedAddressLow = 0;
+       BYTE b_SelectedAddressHigh = 0;
+       WORD w_ReadWord = 0;
+
+       for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+               i_WordCounter++) {
+               do {
+                       dw_eeprom_busy =
+                               inl(dw_PCIBoardEepromAddress +
+                               AMCC_OP_REG_MCSR);
+                       dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+               }
+               while (dw_eeprom_busy == EEPROM_BUSY);
+
+               for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+                       b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256;        //Read the low 8 bit part
+                       b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256;       //Read the high 8 bit part
+
+                       //Select the load low address mode
+                       outb(NVCMD_LOAD_LOW,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Load the low address
+                       outb(b_SelectedAddressLow,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the load high address mode
+                       outb(NVCMD_LOAD_HIGH,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Load the high address
+                       outb(b_SelectedAddressHigh,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the READ mode
+                       outb(NVCMD_BEGIN_READ,
+                               dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+                               3);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Read data into the EEPROM
+                       *pb_ReadByte =
+                               inb(dw_PCIBoardEepromAddress +
+                               AMCC_OP_REG_MCSR + 2);
+
+                       //Wait on busy
+                       do {
+                               dw_eeprom_busy =
+                                       inl(dw_PCIBoardEepromAddress +
+                                       AMCC_OP_REG_MCSR);
+                               dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+                       }
+                       while (dw_eeprom_busy == EEPROM_BUSY);
+
+                       //Select the upper address part
+                       if (i_Counter == 0) {
+                               b_ReadLowByte = pb_ReadByte[0];
+                       } else {
+                               b_ReadHighByte = pb_ReadByte[0];
+                       }
+
+                       //Sleep
+                       for (i = 0; i < 10000; i++) ;
+
+               }
+               w_ReadWord =
+                       (b_ReadLowByte | (((unsigned short)b_ReadHighByte) *
+                               256));
+
+               pw_DataRead[i_WordCounter] = w_ReadWord;
+
+               w_EepromStartAddress += 2;      // to read the next word
+
+       }                       // for (...) i_NbOfWordsToRead
+       return (0);
+}
+
+/*+----------------------------------------------------------------------------+*/
+/*| Function   Name   : void v_GetAPCI3200EepromCalibrationValue (void)        |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Task              : Read calibration value from the APCI-3200 eeprom.      |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Input Parameters  : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Output Parameters : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Return Value      : -                                                      |*/
+/*+----------------------------------------------------------------------------+*/
+
+void v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress,
+       str_BoardInfos * BoardInformations)
+{
+       WORD w_AnalogInputMainHeaderAddress;
+       WORD w_AnalogInputComponentAddress;
+       WORD w_NumberOfModuls = 0;
+       WORD w_CurrentSources[2];
+       WORD w_ModulCounter = 0;
+       WORD w_FirstHeaderSize = 0;
+       WORD w_NumberOfInputs = 0;
+       WORD w_CJCFlag = 0;
+       WORD w_NumberOfGainValue = 0;
+       WORD w_SingleHeaderAddress = 0;
+       WORD w_SingleHeaderSize = 0;
+       WORD w_Input = 0;
+       WORD w_GainFactorAddress = 0;
+       WORD w_GainFactorValue[2];
+       WORD w_GainIndex = 0;
+       WORD w_GainValue = 0;
+
+  /*****************************************/
+  /** Get the Analog input header address **/
+  /*****************************************/
+       i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+               dw_PCIBoardEepromAddress, 0x116,        //w_EepromStartAddress: Analog input header address
+               &w_AnalogInputMainHeaderAddress);
+
+  /*******************************************/
+  /** Compute the real analog input address **/
+  /*******************************************/
+       w_AnalogInputMainHeaderAddress = w_AnalogInputMainHeaderAddress + 0x100;
+
+  /******************************/
+  /** Get the number of moduls **/
+  /******************************/
+       i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+               dw_PCIBoardEepromAddress, w_AnalogInputMainHeaderAddress + 0x02,        //w_EepromStartAddress: Number of conponment
+               &w_NumberOfModuls);
+
+       for (w_ModulCounter = 0; w_ModulCounter < w_NumberOfModuls;
+               w_ModulCounter++) {
+      /***********************************/
+      /** Compute the component address **/
+      /***********************************/
+               w_AnalogInputComponentAddress =
+                       w_AnalogInputMainHeaderAddress +
+                       (w_FirstHeaderSize * w_ModulCounter) + 0x04;
+
+      /****************************/
+      /** Read first header size **/
+      /****************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress,        // Address of the first header
+                       &w_FirstHeaderSize);
+
+               w_FirstHeaderSize = w_FirstHeaderSize >> 4;
+
+      /***************************/
+      /** Read number of inputs **/
+      /***************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x06, // Number of inputs for the first modul
+                       &w_NumberOfInputs);
+
+               w_NumberOfInputs = w_NumberOfInputs >> 4;
+
+      /***********************/
+      /** Read the CJC flag **/
+      /***********************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x08, // CJC flag
+                       &w_CJCFlag);
+
+               w_CJCFlag = (w_CJCFlag >> 3) & 0x1;     // Get only the CJC flag
+
+      /*******************************/
+      /** Read number of gain value **/
+      /*******************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x44, // Number of gain value
+                       &w_NumberOfGainValue);
+
+               w_NumberOfGainValue = w_NumberOfGainValue & 0xFF;
+
+      /***********************************/
+      /** Compute single header address **/
+      /***********************************/
+               w_SingleHeaderAddress =
+                       w_AnalogInputComponentAddress + 0x46 +
+                       (((w_NumberOfGainValue / 16) + 1) * 2) +
+                       (6 * w_NumberOfGainValue) +
+                       (4 * (((w_NumberOfGainValue / 16) + 1) * 2));
+
+      /********************************************/
+      /** Read current sources value for input 1 **/
+      /********************************************/
+               i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress, w_SingleHeaderAddress,        //w_EepromStartAddress: Single header address
+                       &w_SingleHeaderSize);
+
+               w_SingleHeaderSize = w_SingleHeaderSize >> 4;
+
+      /*************************************/
+      /** Read gain factor for the module **/
+      /*************************************/
+               w_GainFactorAddress = w_AnalogInputComponentAddress;
+
+               for (w_GainIndex = 0; w_GainIndex < w_NumberOfGainValue;
+                       w_GainIndex++) {
+         /************************************/
+         /** Read gain value for the module **/
+         /************************************/
+                       i_AddiHeaderRW_ReadEeprom(1,    //i_NbOfWordsToRead
+                               dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + (2 * (1 + (w_NumberOfGainValue / 16))) + (0x02 * w_GainIndex),   // Gain value
+                               &w_GainValue);
+
+                       BoardInformations->s_Module[w_ModulCounter].
+                               w_GainValue[w_GainIndex] = w_GainValue;
+
+#             ifdef PRINT_INFO
+                       printk("\n Gain value = %d",
+                               BoardInformations->s_Module[w_ModulCounter].
+                               w_GainValue[w_GainIndex]);
+#             endif
+
+         /*************************************/
+         /** Read gain factor for the module **/
+         /*************************************/
+                       i_AddiHeaderRW_ReadEeprom(2,    //i_NbOfWordsToRead
+                               dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + ((2 * w_NumberOfGainValue) + (2 * (1 + (w_NumberOfGainValue / 16)))) + (0x04 * w_GainIndex),     // Gain factor
+                               w_GainFactorValue);
+
+                       BoardInformations->s_Module[w_ModulCounter].
+                               ul_GainFactor[w_GainIndex] =
+                               (w_GainFactorValue[1] << 16) +
+                               w_GainFactorValue[0];
+
+#             ifdef PRINT_INFO
+                       printk("\n w_GainFactorValue [%d] = %lu", w_GainIndex,
+                               BoardInformations->s_Module[w_ModulCounter].
+                               ul_GainFactor[w_GainIndex]);
+#             endif
+               }
+
+      /***************************************************************/
+      /** Read current source value for each channels of the module **/
+      /***************************************************************/
+               for (w_Input = 0; w_Input < w_NumberOfInputs; w_Input++) {
+         /********************************************/
+         /** Read current sources value for input 1 **/
+         /********************************************/
+                       i_AddiHeaderRW_ReadEeprom(2,    //i_NbOfWordsToRead
+                               dw_PCIBoardEepromAddress,
+                               (w_Input * w_SingleHeaderSize) +
+                               w_SingleHeaderAddress + 0x0C, w_CurrentSources);
+
+         /************************************/
+         /** Save the current sources value **/
+         /************************************/
+                       BoardInformations->s_Module[w_ModulCounter].
+                               ul_CurrentSource[w_Input] =
+                               (w_CurrentSources[0] +
+                               ((w_CurrentSources[1] & 0xFFF) << 16));
+
+#             ifdef PRINT_INFO
+                       printk("\n Current sources [%d] = %lu", w_Input,
+                               BoardInformations->s_Module[w_ModulCounter].
+                               ul_CurrentSource[w_Input]);
+#             endif
+               }
+
+      /***************************************/
+      /** Read the CJC current source value **/
+      /***************************************/
+               i_AddiHeaderRW_ReadEeprom(2,    //i_NbOfWordsToRead
+                       dw_PCIBoardEepromAddress,
+                       (w_Input * w_SingleHeaderSize) + w_SingleHeaderAddress +
+                       0x0C, w_CurrentSources);
+
+      /************************************/
+      /** Save the current sources value **/
+      /************************************/
+               BoardInformations->s_Module[w_ModulCounter].
+                       ul_CurrentSourceCJC =
+                       (w_CurrentSources[0] +
+                       ((w_CurrentSources[1] & 0xFFF) << 16));
+
+#          ifdef PRINT_INFO
+               printk("\n Current sources CJC = %lu",
+                       BoardInformations->s_Module[w_ModulCounter].
+                       ul_CurrentSourceCJC);
+#          endif
+       }
+}
+
+INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev,
+       unsigned int ui_Channel_num, unsigned int * CJCCurrentSource,
+       unsigned int * ChannelCurrentSource, unsigned int * ChannelGainFactor)
+{
+       int i_DiffChannel = 0;
+       int i_Module = 0;
+
+#ifdef PRINT_INFO
+       printk("\n Channel = %u", ui_Channel_num);
+#endif
+
+       //Test if single or differential mode
+       if (s_BoardInfos[dev->minor].i_ConnectionType == 1) {
+               //if diff
+
+               if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1))
+                       i_DiffChannel = ui_Channel_num, i_Module = 0;
+               else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3))
+                       i_DiffChannel = ui_Channel_num - 2, i_Module = 1;
+               else if ((ui_Channel_num >= 4) && (ui_Channel_num <= 5))
+                       i_DiffChannel = ui_Channel_num - 4, i_Module = 2;
+               else if ((ui_Channel_num >= 6) && (ui_Channel_num <= 7))
+                       i_DiffChannel = ui_Channel_num - 6, i_Module = 3;
+
+       } else {
+               // if single
+               if ((ui_Channel_num == 0) || (ui_Channel_num == 1))
+                       i_DiffChannel = 0, i_Module = 0;
+               else if ((ui_Channel_num == 2) || (ui_Channel_num == 3))
+                       i_DiffChannel = 1, i_Module = 0;
+               else if ((ui_Channel_num == 4) || (ui_Channel_num == 5))
+                       i_DiffChannel = 0, i_Module = 1;
+               else if ((ui_Channel_num == 6) || (ui_Channel_num == 7))
+                       i_DiffChannel = 1, i_Module = 1;
+               else if ((ui_Channel_num == 8) || (ui_Channel_num == 9))
+                       i_DiffChannel = 0, i_Module = 2;
+               else if ((ui_Channel_num == 10) || (ui_Channel_num == 11))
+                       i_DiffChannel = 1, i_Module = 2;
+               else if ((ui_Channel_num == 12) || (ui_Channel_num == 13))
+                       i_DiffChannel = 0, i_Module = 3;
+               else if ((ui_Channel_num == 14) || (ui_Channel_num == 15))
+                       i_DiffChannel = 1, i_Module = 3;
+       }
+
+       //Test if thermocouple or RTD mode
+       *CJCCurrentSource =
+               s_BoardInfos[dev->minor].s_Module[i_Module].ul_CurrentSourceCJC;
+#ifdef PRINT_INFO
+       printk("\n CJCCurrentSource = %lu", *CJCCurrentSource);
+#endif
+
+       *ChannelCurrentSource =
+               s_BoardInfos[dev->minor].s_Module[i_Module].
+               ul_CurrentSource[i_DiffChannel];
+#ifdef PRINT_INFO
+       printk("\n ChannelCurrentSource = %lu", *ChannelCurrentSource);
+#endif
+       //      }
+       //   }
+
+       //Channle gain factor
+       *ChannelGainFactor =
+               s_BoardInfos[dev->minor].s_Module[i_Module].
+               ul_GainFactor[s_BoardInfos[dev->minor].i_ADDIDATAGain];
+#ifdef PRINT_INFO
+       printk("\n ChannelGainFactor = %lu", *ChannelGainFactor);
+#endif
+       //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+       return (0);
+}
+
+//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadDigitalInput                       |
+  |                      (struct comedi_device *dev,struct comedi_subdevice *s,               |
+  |                      struct comedi_insn *insn,unsigned int *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel or port           |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, struct comedi_subdevice * s,
+       struct comedi_insn * insn, unsigned int * 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                     |
+  |                      (struct comedi_device *dev,struct comedi_subdevice *s,                                 |
+  |                      struct comedi_insn *insn,unsigned int *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Configures The Digital Output Subdevice.               |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, struct comedi_subdevice * s,
+       struct comedi_insn * insn, unsigned int * 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                      |
+  |                      (struct comedi_device *dev,struct comedi_subdevice *s,                                 |
+  |                      struct comedi_insn *insn,unsigned int *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : writes To the digital Output Subdevice                 |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+  |                     unsigned int *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(struct comedi_device * dev, struct comedi_subdevice * s,
+       struct comedi_insn * insn, unsigned int * 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                       |
+  |                      (struct comedi_device *dev,struct comedi_subdevice *s,               |
+  |                      struct comedi_insn *insn,unsigned int *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel or port           |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, struct comedi_subdevice * s,
+       struct comedi_insn * insn, unsigned int * 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                       |
+  |                      (struct comedi_device *dev,struct comedi_subdevice *s,               |
+  |                      struct comedi_insn *insn,unsigned int *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Configures The Analog Input Subdevice                  |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+  |                     unsigned int *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(struct comedi_device * dev, struct comedi_subdevice * s,
+       struct comedi_insn * insn, unsigned int * data)
+{
+
+       UINT ul_Config = 0, ul_Temp = 0;
+       UINT ui_ChannelNo = 0;
+       UINT ui_Dummy = 0;
+       INT i_err = 0;
+
+       //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+#ifdef PRINT_INFO
+       INT i = 0, i2 = 0;
+#endif
+       //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       // Initialize the structure
+       if (s_BoardInfos[dev->minor].b_StructInitialized != 1) {
+               s_BoardInfos[dev->minor].i_CJCAvailable = 1;
+               s_BoardInfos[dev->minor].i_CJCPolarity = 0;
+               s_BoardInfos[dev->minor].i_CJCGain = 2; //changed from 0 to 2
+               s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+               s_BoardInfos[dev->minor].i_AutoCalibration = 0; //: auto calibration
+               s_BoardInfos[dev->minor].i_ChannelCount = 0;
+               s_BoardInfos[dev->minor].i_Sum = 0;
+               s_BoardInfos[dev->minor].ui_Channel_num = 0;
+               s_BoardInfos[dev->minor].i_Count = 0;
+               s_BoardInfos[dev->minor].i_Initialised = 0;
+               s_BoardInfos[dev->minor].b_StructInitialized = 1;
+
+               //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               s_BoardInfos[dev->minor].i_ConnectionType = 0;
+               //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+               //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               memset(s_BoardInfos[dev->minor].s_Module, 0,
+                       sizeof(s_BoardInfos[dev->minor].s_Module[MAX_MODULE]));
+
+               v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc,
+                       &s_BoardInfos[dev->minor]);
+
+#ifdef PRINT_INFO
+               for (i = 0; i < MAX_MODULE; i++) {
+                       printk("\n s_Module[%i].ul_CurrentSourceCJC = %lu", i,
+                               s_BoardInfos[dev->minor].s_Module[i].
+                               ul_CurrentSourceCJC);
+
+                       for (i2 = 0; i2 < 5; i2++) {
+                               printk("\n s_Module[%i].ul_CurrentSource [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_CurrentSource[i2]);
+                       }
+
+                       for (i2 = 0; i2 < 8; i2++) {
+                               printk("\n s_Module[%i].ul_GainFactor [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_GainFactor[i2]);
+                       }
+
+                       for (i2 = 0; i2 < 8; i2++) {
+                               printk("\n s_Module[%i].w_GainValue [%i] = %u",
+                                       i, i2,
+                                       s_BoardInfos[dev->minor].s_Module[i].
+                                       w_GainValue[i2]);
+                       }
+               }
+#endif
+               //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+       }
+
+       if (data[0] != 0 && data[0] != 1 && data[0] != 2) {
+               printk("\nThe selection of acquisition type is in error\n");
+               i_err++;
+       }                       //if(data[0]!=0 && data[0]!=1 && data[0]!=2)
+       if (data[0] == 1) {
+               if (data[14] != 0 && data[14] != 1 && data[14] != 2
+                       && data[14] != 4) {
+                       printk("\n Error in selection of RTD connection type\n");
+                       i_err++;
+               }               //if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4)
+       }                       //if(data[0]==1 )
+       if (data[1] < 0 || data[1] > 7) {
+               printk("\nThe selection of gain is in error\n");
+               i_err++;
+       }                       // if(data[1]<0 || data[1]>7)
+       if (data[2] != 0 && data[2] != 1) {
+               printk("\nThe selection of polarity is in error\n");
+               i_err++;
+       }                       //if(data[2]!=0 &&  data[2]!=1)
+       if (data[3] != 0) {
+               printk("\nThe selection of offset range  is in error\n");
+               i_err++;
+       }                       // if(data[3]!=0)
+       if (data[4] != 0 && data[4] != 1) {
+               printk("\nThe selection of coupling is in error\n");
+               i_err++;
+       }                       //if(data[4]!=0 &&  data[4]!=1)
+       if (data[5] != 0 && data[5] != 1) {
+               printk("\nThe selection of single/differential mode is in error\n");
+               i_err++;
+       }                       //if(data[5]!=0 &&  data[5]!=1)
+       if (data[8] != 0 && data[8] != 1 && data[2] != 2) {
+               printk("\nError in selection of functionality\n");
+       }                       //if(data[8]!=0 && data[8]!=1 && data[2]!=2)
+       if (data[12] == 0 || data[12] == 1) {
+               if (data[6] != 20 && data[6] != 40 && data[6] != 80
+                       && data[6] != 160) {
+                       printk("\nThe selection of conversion time reload value is in error\n");
+                       i_err++;
+               }               // if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 )
+               if (data[7] != 2) {
+                       printk("\nThe selection of conversion time unit  is in error\n");
+                       i_err++;
+               }               // if(data[7]!=2)
+       }
+       if (data[9] != 0 && data[9] != 1) {
+               printk("\nThe selection of interrupt enable is in error\n");
+               i_err++;
+       }                       //if(data[9]!=0 &&  data[9]!=1)
+       if (data[11] < 0 || data[11] > 4) {
+               printk("\nThe selection of module is in error\n");
+               i_err++;
+       }                       //if(data[11] <0 ||  data[11]>1)
+       if (data[12] < 0 || data[12] > 3) {
+               printk("\nThe selection of singlechannel/scan selection is in error\n");
+               i_err++;
+       }                       //if(data[12] < 0 ||  data[12]> 3)
+       if (data[13] < 0 || data[13] > 16) {
+               printk("\nThe selection of number of channels is in error\n");
+               i_err++;
+       }                       // if(data[13] <0 ||data[13] >15)
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       /*
+          i_ChannelCount=data[13];
+          i_ScanType=data[12];
+          i_ADDIDATAPolarity = data[2];
+          i_ADDIDATAGain=data[1];
+          i_ADDIDATAConversionTime=data[6];
+          i_ADDIDATAConversionTimeUnit=data[7];
+          i_ADDIDATAType=data[0];
+        */
+
+       // Save acquisition configuration for the actual board
+       s_BoardInfos[dev->minor].i_ChannelCount = data[13];
+       s_BoardInfos[dev->minor].i_ScanType = data[12];
+       s_BoardInfos[dev->minor].i_ADDIDATAPolarity = data[2];
+       s_BoardInfos[dev->minor].i_ADDIDATAGain = data[1];
+       s_BoardInfos[dev->minor].i_ADDIDATAConversionTime = data[6];
+       s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit = data[7];
+       s_BoardInfos[dev->minor].i_ADDIDATAType = data[0];
+       //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       s_BoardInfos[dev->minor].i_ConnectionType = data[5];
+       //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       //END JK 06.07.04: Management of sevrals boards
+
+       //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int)); // 7 is the maximal number of channels
+       //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+       //BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards
+       //while(i_InterruptFlag==1)
+       while (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
+#ifndef MSXBOX
+               udelay(1);
+#else
+               // In the case where the driver is compiled for the MSX-Box
+               // we used a printk to have a little delay because udelay
+               // seems to be broken under the MSX-Box.
+               // This solution hat to be studied.
+               printk("");
+#endif
+       }
+       //END JK 02.07.04 : This while can't be do, it block the process when using severals boards
+
+       ui_ChannelNo = CR_CHAN(insn->chanspec); // get the channel
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //i_ChannelNo=ui_ChannelNo;
+       //ui_Channel_num =ui_ChannelNo;
+
+       s_BoardInfos[dev->minor].i_ChannelNo = ui_ChannelNo;
+       s_BoardInfos[dev->minor].ui_Channel_num = ui_ChannelNo;
+
+       //END JK 06.07.04: Management of sevrals boards
+
+       if (data[5] == 0) {
+               if (ui_ChannelNo < 0 || ui_ChannelNo > 15) {
+                       printk("\nThe Selection of the channel is in error\n");
+                       i_err++;
+               }               // if(ui_ChannelNo<0 || ui_ChannelNo>15)
+       }                       //if(data[5]==0)
+       else {
+               if (data[14] == 2) {
+                       if (ui_ChannelNo < 0 || ui_ChannelNo > 3) {
+                               printk("\nThe Selection of the channel is in error\n");
+                               i_err++;
+                       }       // if(ui_ChannelNo<0 || ui_ChannelNo>3)
+               }               //if(data[14]==2)
+               else {
+                       if (ui_ChannelNo < 0 || ui_ChannelNo > 7) {
+                               printk("\nThe Selection of the channel is in error\n");
+                               i_err++;
+                       }       // if(ui_ChannelNo<0 || ui_ChannelNo>7)
+               }               //elseif(data[14]==2)
+       }                       //elseif(data[5]==0)
+       if (data[12] == 0 || data[12] == 1) {
+               switch (data[5]) {
+               case 0:
+                       if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=0;
+                               s_BoardInfos[dev->minor].i_Offset = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=0 && ui_ChannelNo <=3)
+                       if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=64;
+                               s_BoardInfos[dev->minor].i_Offset = 64;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=4 && ui_ChannelNo <=7)
+                       if (ui_ChannelNo >= 8 && ui_ChannelNo <= 11) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=128;
+                               s_BoardInfos[dev->minor].i_Offset = 128;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=8 && ui_ChannelNo <=11)
+                       if (ui_ChannelNo >= 12 && ui_ChannelNo <= 15) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=192;
+                               s_BoardInfos[dev->minor].i_Offset = 192;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=12 && ui_ChannelNo <=15)
+                       break;
+               case 1:
+                       if (data[14] == 2) {
+                               if (ui_ChannelNo == 0) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=0;
+                                       s_BoardInfos[dev->minor].i_Offset = 0;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       //if(ui_ChannelNo ==0 )
+                               if (ui_ChannelNo == 1) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=0;
+                                       s_BoardInfos[dev->minor].i_Offset = 64;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       // if(ui_ChannelNo ==1)
+                               if (ui_ChannelNo == 2) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=128;
+                                       s_BoardInfos[dev->minor].i_Offset = 128;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       //if(ui_ChannelNo ==2 )
+                               if (ui_ChannelNo == 3) {
+                                       //BEGIN JK 06.07.04: Management of sevrals boards
+                                       //i_Offset=192;
+                                       s_BoardInfos[dev->minor].i_Offset = 192;
+                                       //END JK 06.07.04: Management of sevrals boards
+                               }       //if(ui_ChannelNo ==3)
+
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=0;
+                               s_BoardInfos[dev->minor].i_ChannelNo = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = 0;
+                               break;
+                       }       //if(data[14]==2)
+                       if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_Offset=0;
+                               s_BoardInfos[dev->minor].i_Offset = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(ui_ChannelNo >=0 && ui_ChannelNo <=1)
+                       if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=i_ChannelNo-2;
+                               //i_Offset=64;
+                               s_BoardInfos[dev->minor].i_ChannelNo =
+                                       s_BoardInfos[dev->minor].i_ChannelNo -
+                                       2;
+                               s_BoardInfos[dev->minor].i_Offset = 64;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = ui_ChannelNo - 2;
+                       }       //if(ui_ChannelNo >=2 && ui_ChannelNo <=3)
+                       if (ui_ChannelNo >= 4 && ui_ChannelNo <= 5) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=i_ChannelNo-4;
+                               //i_Offset=128;
+                               s_BoardInfos[dev->minor].i_ChannelNo =
+                                       s_BoardInfos[dev->minor].i_ChannelNo -
+                                       4;
+                               s_BoardInfos[dev->minor].i_Offset = 128;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = ui_ChannelNo - 4;
+                       }       //if(ui_ChannelNo >=4 && ui_ChannelNo <=5)
+                       if (ui_ChannelNo >= 6 && ui_ChannelNo <= 7) {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //i_ChannelNo=i_ChannelNo-6;
+                               //i_Offset=192;
+                               s_BoardInfos[dev->minor].i_ChannelNo =
+                                       s_BoardInfos[dev->minor].i_ChannelNo -
+                                       6;
+                               s_BoardInfos[dev->minor].i_Offset = 192;
+                               //END JK 06.07.04: Management of sevrals boards
+                               ui_ChannelNo = ui_ChannelNo - 6;
+                       }       //if(ui_ChannelNo >=6 && ui_ChannelNo <=7)
+                       break;
+
+               default:
+                       printk("\n This selection of polarity does not exist\n");
+                       i_err++;
+               }               //switch(data[2])
+       }                       //if(data[12]==0 || data[12]==1)
+       else {
+               switch (data[11]) {
+               case 1:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=0;
+                       s_BoardInfos[dev->minor].i_Offset = 0;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               case 2:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=64;
+                       s_BoardInfos[dev->minor].i_Offset = 64;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               case 3:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=128;
+                       s_BoardInfos[dev->minor].i_Offset = 128;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               case 4:
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //i_Offset=192;
+                       s_BoardInfos[dev->minor].i_Offset = 192;
+                       //END JK 06.07.04: Management of sevrals boards
+                       break;
+               default:
+                       printk("\nError in module selection\n");
+                       i_err++;
+               }               // switch(data[11])
+       }                       // elseif(data[12]==0 || data[12]==1)
+       if (i_err) {
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }
+       //if(i_ScanType!=1)
+       if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_Count=0;
+               //i_Sum=0;
+               s_BoardInfos[dev->minor].i_Count = 0;
+               s_BoardInfos[dev->minor].i_Sum = 0;
+               //END JK 06.07.04: Management of sevrals boards
+       }                       //if(i_ScanType!=1)
+
+       ul_Config =
+               data[1] | (data[2] << 6) | (data[5] << 7) | (data[3] << 8) |
+               (data[4] << 9);
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4);
+       outl(0 | ui_ChannelNo,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+  /**************************/
+       /* Reset the configuration */
+  /**************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl(0 , devpriv->iobase+i_Offset + 0x0);
+       outl(0, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+
+  /***************************/
+       /* Write the configuration */
+  /***************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl(ul_Config , devpriv->iobase+i_Offset + 0x0);
+       outl(ul_Config,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+       //END JK 06.07.04: Management of sevrals boards
+
+  /***************************/
+       /*Reset the calibration bit */
+  /***************************/
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //ul_Temp = inl(devpriv->iobase+i_Offset + 12);
+       ul_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12);
+       outl((ul_Temp & 0xFFF9FFFF),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+       //END JK 06.07.04: Management of sevrals boards
+
+       if (data[9] == 1) {
+               devpriv->tsk_Current = current;
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_InterruptFlag=1;
+               s_BoardInfos[dev->minor].i_InterruptFlag = 1;
+               //END JK 06.07.04: Management of sevrals boards
+       }                       // if(data[9]==1)
+       else {
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_InterruptFlag=0;
+               s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+               //END JK 06.07.04: Management of sevrals boards
+       }                       //else  if(data[9]==1)
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //i_Initialised=1;
+       s_BoardInfos[dev->minor].i_Initialised = 1;
+       //END JK 06.07.04: Management of sevrals boards
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //if(i_ScanType==1)
+       if (s_BoardInfos[dev->minor].i_ScanType == 1)
+               //END JK 06.07.04: Management of sevrals boards
+       {
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //i_Sum=i_Sum+1;
+               s_BoardInfos[dev->minor].i_Sum =
+                       s_BoardInfos[dev->minor].i_Sum + 1;
+               //END JK 06.07.04: Management of sevrals boards
+
+               insn->unused[0] = 0;
+               i_APCI3200_ReadAnalogInput(dev, s, insn, &ui_Dummy);
+       }
+
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadAnalogInput                         |
+  |                              (struct comedi_device *dev,struct comedi_subdevice *s,       |
+  |                     struct comedi_insn *insn,unsigned int *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel                            |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+  |                     UINT ui_NoOfChannels    : No Of Channels To read       |
+  |                     UINT *data              : Data Pointer to read status  |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  |                            data[0]  : Digital Value Of Input             |
+  |                            data[1]  : Calibration Offset Value           |
+  |                            data[2]  : Calibration Gain Value
+  |                            data[3]  : CJC value
+  |                            data[4]  : CJC offset value
+  |                            data[5]  : CJC gain value
+  | Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+  |                            data[6] : CJC current source from eeprom
+  |                            data[7] : Channel current source from eeprom
+  |                            data[8] : Channle gain factor from eeprom
+  | End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+       struct comedi_insn * insn, unsigned int * data)
+{
+       UINT ui_DummyValue = 0;
+       int i_ConvertCJCCalibration;
+       int i = 0;
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //if(i_Initialised==0)
+       if (s_BoardInfos[dev->minor].i_Initialised == 0)
+               //END JK 06.07.04: Management of sevrals boards
+       {
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //if(i_Initialised==0);
+
+#ifdef PRINT_INFO
+       printk("\n insn->unused[0] = %i", insn->unused[0]);
+#endif
+
+       switch (insn->unused[0]) {
+       case 0:
+
+               i_APCI3200_Read1AnalogInputChannel(dev, s, insn,
+                       &ui_DummyValue);
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //ui_InterruptChannelValue[i_Count+0]=ui_DummyValue;
+               s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                       i_Count + 0] = ui_DummyValue;
+               //END JK 06.07.04: Management of sevrals boards
+
+               //Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               i_APCI3200_GetChannelCalibrationValue(dev,
+                       s_BoardInfos[dev->minor].ui_Channel_num,
+                       &s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                               i_Count + 6],
+                       &s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                               i_Count + 7],
+                       &s_BoardInfos[dev->minor].
+                       ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+                               i_Count + 8]);
+
+#ifdef PRINT_INFO
+               printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+6] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 6]);
+
+               printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+7] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 7]);
+
+               printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]);
+#endif
+
+               //End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))
+               if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+                       && (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+                       //END JK 06.07.04: Management of sevrals boards
+               {
+                       i_APCI3200_ReadCJCValue(dev, &ui_DummyValue);
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 3] = ui_DummyValue;
+                       //END JK 06.07.04: Management of sevrals boards
+               }               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE))
+               else {
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 3]=0;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 3] = 0;
+                       //END JK 06.07.04: Management of sevrals boards
+               }               //elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1))
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE))
+               if ((s_BoardInfos[dev->minor].i_AutoCalibration == FALSE)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE))
+                       //END JK 06.07.04: Management of sevrals boards
+               {
+                       i_APCI3200_ReadCalibrationOffsetValue(dev,
+                               &ui_DummyValue);
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 1] = ui_DummyValue;
+                       //END JK 06.07.04: Management of sevrals boards
+                       i_APCI3200_ReadCalibrationGainValue(dev,
+                               &ui_DummyValue);
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue;
+                       s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[s_BoardInfos[dev->
+                                       minor].i_Count + 2] = ui_DummyValue;
+                       //END JK 06.07.04: Management of sevrals boards
+               }               //if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE))
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1))
+               if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+                       && (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+                       //END JK 06.07.04: Management of sevrals boards
+               {
+         /**********************************************************/
+                       /*Test if the Calibration channel must be read for the CJC */
+         /**********************************************************/
+         /**********************************/
+                       /*Test if the polarity is the same */
+         /**********************************/
+                       //BEGIN JK 06.07.04: Management of sevrals boards
+                       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                       if (s_BoardInfos[dev->minor].i_CJCPolarity !=
+                               s_BoardInfos[dev->minor].i_ADDIDATAPolarity)
+                               //END JK 06.07.04: Management of sevrals boards
+                       {
+                               i_ConvertCJCCalibration = 1;
+                       }       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                       else {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //if(i_CJCGain==i_ADDIDATAGain)
+                               if (s_BoardInfos[dev->minor].i_CJCGain ==
+                                       s_BoardInfos[dev->minor].i_ADDIDATAGain)
+                                       //END JK 06.07.04: Management of sevrals boards
+                               {
+                                       i_ConvertCJCCalibration = 0;
+                               }       //if(i_CJCGain==i_ADDIDATAGain)
+                               else {
+                                       i_ConvertCJCCalibration = 1;
+                               }       //elseif(i_CJCGain==i_ADDIDATAGain)
+                       }       //elseif(i_CJCPolarity!=i_ADDIDATAPolarity)
+                       if (i_ConvertCJCCalibration == 1) {
+                               i_APCI3200_ReadCJCCalOffset(dev,
+                                       &ui_DummyValue);
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //ui_InterruptChannelValue[i_Count+4]=ui_DummyValue;
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 4] =
+                                       ui_DummyValue;
+                               //END JK 06.07.04: Management of sevrals boards
+
+                               i_APCI3200_ReadCJCCalGain(dev, &ui_DummyValue);
+
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //ui_InterruptChannelValue[i_Count+5]=ui_DummyValue;
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 5] =
+                                       ui_DummyValue;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //if(i_ConvertCJCCalibration==1)
+                       else {
+                               //BEGIN JK 06.07.04: Management of sevrals boards
+                               //ui_InterruptChannelValue[i_Count+4]=0;
+                               //ui_InterruptChannelValue[i_Count+5]=0;
+
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 4] = 0;
+                               s_BoardInfos[dev->minor].
+                                       ui_InterruptChannelValue[s_BoardInfos
+                                       [dev->minor].i_Count + 5] = 0;
+                               //END JK 06.07.04: Management of sevrals boards
+                       }       //elseif(i_ConvertCJCCalibration==1)
+               }               //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE))
+
+               //BEGIN JK 06.07.04: Management of sevrals boards
+               //if(i_ScanType!=1)
+               if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+                       //i_Count=0;
+                       s_BoardInfos[dev->minor].i_Count = 0;
+               }               //if(i_ScanType!=1)
+               else {
+                       //i_Count=i_Count +6;
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6;
+                       s_BoardInfos[dev->minor].i_Count =
+                               s_BoardInfos[dev->minor].i_Count + 9;
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               }               //else if(i_ScanType!=1)
+
+               //if((i_ScanType==1) &&(i_InterruptFlag==1))
+               if ((s_BoardInfos[dev->minor].i_ScanType == 1)
+                       && (s_BoardInfos[dev->minor].i_InterruptFlag == 1)) {
+                       //i_Count=i_Count-6;
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6;
+                       s_BoardInfos[dev->minor].i_Count =
+                               s_BoardInfos[dev->minor].i_Count - 9;
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               }
+               //if(i_ScanType==0)
+               if (s_BoardInfos[dev->minor].i_ScanType == 0) {
+                       /*
+                          data[0]= ui_InterruptChannelValue[0];
+                          data[1]= ui_InterruptChannelValue[1];
+                          data[2]= ui_InterruptChannelValue[2];
+                          data[3]= ui_InterruptChannelValue[3];
+                          data[4]= ui_InterruptChannelValue[4];
+                          data[5]= ui_InterruptChannelValue[5];
+                        */
+#ifdef PRINT_INFO
+                       printk("\n data[0]= s_BoardInfos [dev->minor].ui_InterruptChannelValue[0];");
+#endif
+                       data[0] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[0];
+                       data[1] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[1];
+                       data[2] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[2];
+                       data[3] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[3];
+                       data[4] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[4];
+                       data[5] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[5];
+
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       //printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]);
+                       i_APCI3200_GetChannelCalibrationValue(dev,
+                               s_BoardInfos[dev->minor].ui_Channel_num,
+                               &data[6], &data[7], &data[8]);
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+               }
+               break;
+       case 1:
+
+               for (i = 0; i < insn->n; i++) {
+                       //data[i]=ui_InterruptChannelValue[i];
+                       data[i] =
+                               s_BoardInfos[dev->minor].
+                               ui_InterruptChannelValue[i];
+               }
+
+               //i_Count=0;
+               //i_Sum=0;
+               //if(i_ScanType==1)
+               s_BoardInfos[dev->minor].i_Count = 0;
+               s_BoardInfos[dev->minor].i_Sum = 0;
+               if (s_BoardInfos[dev->minor].i_ScanType == 1) {
+                       //i_Initialised=0;
+                       //i_InterruptFlag=0;
+                       s_BoardInfos[dev->minor].i_Initialised = 0;
+                       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+                       //END JK 06.07.04: Management of sevrals boards
+               }
+               break;
+       default:
+               printk("\nThe parameters passed are in error\n");
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //switch(insn->unused[0])
+
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_Read1AnalogInputChannel                 |
+  |                              (struct comedi_device *dev,struct comedi_subdevice *s,       |
+  |                     struct comedi_insn *insn,unsigned int *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read  value  of the selected channel                            |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev,
+       struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+       UINT ui_EOC = 0;
+       UINT ui_ChannelNo = 0;
+       UINT ui_CommandRegister = 0;
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //ui_ChannelNo=i_ChannelNo;
+       ui_ChannelNo = s_BoardInfos[dev->minor].i_ChannelNo;
+
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //Begin JK 20.10.2004: Bad channel value is used when using differential mode
+       //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+       //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+       outl(0 | s_BoardInfos[dev->minor].i_ChannelNo,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+       //End JK 20.10.2004: Bad channel value is used when using differential mode
+
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+
+  /**************************************************************************/
+       /* Set the start end stop index to the selected channel and set the start */
+  /**************************************************************************/
+
+       ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000;
+
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /************************/
+               /* Enable the interrupt */
+      /************************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+       }                       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+
+  /******************************/
+       /* Write the command register */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+         /*************************/
+                       /*Read the EOC Status bit */
+         /*************************/
+
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /***************************************/
+               /* Read the digital value of the input */
+      /***************************************/
+
+               //data[0] = inl (devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+               //END JK 06.07.04: Management of sevrals boards
+
+       }                       // if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCalibrationOffsetValue              |
+  |                              (struct comedi_device *dev,struct comedi_subdevice *s,       |
+  |                     struct comedi_insn *insn,unsigned int *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read calibration offset  value  of the selected channel|
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, UINT * data)
+{
+       UINT ui_Temp = 0, ui_EOC = 0;
+       UINT ui_CommandRegister = 0;
+
+       //BEGIN JK 06.07.04: Management of sevrals boards
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //Begin JK 20.10.2004: This seems not necessary !
+       //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+       //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+       //End JK 20.10.2004: This seems not necessary !
+
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /*****************************/
+       /*Read the calibration offset */
+  /*****************************/
+       //ui_Temp = inl(devpriv->iobase+i_Offset + 12);
+       ui_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+
+  /*********************************/
+       /*Configure the Offset Conversion */
+  /*********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12);
+       outl((ui_Temp | 0x00020000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+  /*******************************/
+       /*Initialise ui_CommandRegister */
+  /*******************************/
+
+       ui_CommandRegister = 0;
+
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+
+       }                       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+
+               do {
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+
+                       //ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /**************************************************/
+               /*Read the digital value of the calibration Offset */
+      /**************************************************/
+
+               //data[0] = inl(devpriv->iobase+i_Offset+ 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCalibrationGainValue                |
+  |                              (struct comedi_device *dev,struct comedi_subdevice *s,       |
+  |                     struct comedi_insn *insn,unsigned int *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read calibration gain  value  of the selected channel  |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, UINT * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+  /*********************************/
+       /* Write the channel to configure */
+  /*********************************/
+       //Begin JK 20.10.2004: This seems not necessary !
+       //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4);
+       //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4);
+       //End JK 20.10.2004: This seems not necessary !
+
+  /***************************/
+       /*Read the calibration gain */
+  /***************************/
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /*******************************/
+       /*Configure the Gain Conversion */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00040000 , devpriv->iobase+i_Offset + 12);
+       outl(0x00040000,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+
+  /*******************************/
+       /*Initialise ui_CommandRegister */
+  /*******************************/
+
+       ui_CommandRegister = 0;
+
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+
+       }                       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+
+               do {
+
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /************************************************/
+               /*Read the digital value of the calibration Gain */
+      /************************************************/
+
+               //data[0] = inl(devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCJCValue                            |
+  |                              (struct comedi_device *dev,struct comedi_subdevice *s,       |
+  |                     struct comedi_insn *insn,unsigned int *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read CJC  value  of the selected channel               |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, unsigned int * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+
+  /******************************/
+       /*Set the converting time unit */
+  /******************************/
+
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+
+  /******************************/
+       /*Configure the CJC Conversion */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl( 0x00000400 , devpriv->iobase+i_Offset + 4);
+       outl(0x00000400,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************************/
+       /*Initialise dw_CommandRegister */
+  /*******************************/
+       ui_CommandRegister = 0;
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+       }
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*****************************/
+       /*Test if interrupt is enable */
+  /*****************************/
+
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+
+               } while (ui_EOC != 1);
+
+      /***********************************/
+               /*Read the digital value of the CJC */
+      /***********************************/
+
+               //data[0] = inl(devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCJCCalOffset                        |
+  |                              (struct comedi_device *dev,struct comedi_subdevice *s,       |
+  |                     struct comedi_insn *insn,unsigned int *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read CJC calibration offset  value  of the selected channel
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, unsigned int * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+  /*******************************************/
+       /*Read calibration offset value for the CJC */
+  /*******************************************/
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /******************************/
+       /*Configure the CJC Conversion */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00000400 , devpriv->iobase+i_Offset + 4);
+       outl(0x00000400,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*********************************/
+       /*Configure the Offset Conversion */
+  /*********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00020000, devpriv->iobase+i_Offset + 12);
+       outl(0x00020000,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+  /*******************************/
+       /*Initialise ui_CommandRegister */
+  /*******************************/
+       ui_CommandRegister = 0;
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+
+       }
+
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+               } while (ui_EOC != 1);
+
+      /**************************************************/
+               /*Read the digital value of the calibration Offset */
+      /**************************************************/
+               //data[0] = inl(devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_ReadCJCGainValue                        |
+  |                              (struct comedi_device *dev,struct comedi_subdevice *s,       |
+  |                     struct comedi_insn *insn,unsigned int *data)                      |
+  +----------------------------------------------------------------------------+
+  | Task              : Read CJC calibration gain value
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct 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(struct comedi_device * dev, unsigned int * data)
+{
+       UINT ui_EOC = 0;
+       INT ui_CommandRegister = 0;
+  /*******************************/
+       /* Set the convert timing unit */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+       /* Set the convert timing */
+  /**************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32);
+       outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /******************************/
+       /*Configure the CJC Conversion */
+  /******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00000400,devpriv->iobase+i_Offset + 4);
+       outl(0x00000400,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************************/
+       /*Configure the Gain Conversion */
+  /*******************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(0x00040000,devpriv->iobase+i_Offset + 12);
+       outl(0x00040000,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+
+  /*******************************/
+       /*Initialise dw_CommandRegister */
+  /*******************************/
+       ui_CommandRegister = 0;
+  /*********************************/
+       /*Test if the interrupt is enable */
+  /*********************************/
+       //if (i_InterruptFlag == ADDIDATA_ENABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /**********************/
+               /*Enable the interrupt */
+      /**********************/
+               ui_CommandRegister = ui_CommandRegister | 0x00100000;
+       }
+  /**********************/
+       /*Start the conversion */
+  /**********************/
+       ui_CommandRegister = ui_CommandRegister | 0x00080000;
+  /***************************/
+       /*Write the command regiter */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8);
+       outl(ui_CommandRegister,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+               do {
+         /*******************/
+                       /*Read the EOC flag */
+         /*******************/
+                       //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1;
+                       ui_EOC = inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+               } while (ui_EOC != 1);
+      /************************************************/
+               /*Read the digital value of the calibration Gain */
+      /************************************************/
+               //data[0] = inl (devpriv->iobase+i_Offset + 28);
+               data[0] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+       }                       //if (i_InterruptFlag == ADDIDATA_DISABLE)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_InsnBits_AnalogInput_Test               |
+  |                      (struct comedi_device *dev,struct comedi_subdevice *s,               |
+  |                      struct comedi_insn *insn,unsigned int *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              : Tests the Selected Anlog Input Channel                 |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+  |                     unsigned int *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(struct comedi_device * dev,
+       struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+       UINT ui_Configuration = 0;
+       INT i_Temp;             //,i_TimeUnit;
+       //if(i_Initialised==0)
+
+       if (s_BoardInfos[dev->minor].i_Initialised == 0) {
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //if(i_Initialised==0);
+       if (data[0] != 0 && data[0] != 1) {
+               printk("\nError in selection of functionality\n");
+               i_APCI3200_Reset(dev);
+               return -EINVAL;
+       }                       //if(data[0]!=0 && data[0]!=1)
+
+       if (data[0] == 1)       //Perform Short Circuit TEST
+       {
+      /**************************/
+               /*Set the short-cicuit bit */
+      /**************************/
+               //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+               while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                               i_Offset + 12) >> 19) & 1) !=
+                       1) ;
+               //outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+               outl((0x00001000 | s_BoardInfos[dev->minor].i_ChannelNo),
+                       devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                       4);
+      /*************************/
+               /*Set the time unit to ns */
+      /*************************/
+               /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+                  i_ADDIDATAConversionTimeUnit= 1; */
+               //i_Temp= i_InterruptFlag ;
+               i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
+               //i_InterruptFlag = ADDIDATA_DISABLE;
+               s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+               i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
+               //if(i_AutoCalibration == FALSE)
+               if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
+                       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+                       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                                       i_Offset +
+                                                       12) >> 19) & 1) != 1) ;
+
+                       //outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+                       outl((0x00001000 | s_BoardInfos[dev->minor].
+                                       i_ChannelNo),
+                               devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 4);
+                       data++;
+                       i_APCI3200_ReadCalibrationOffsetValue(dev, data);
+                       data++;
+                       i_APCI3200_ReadCalibrationGainValue(dev, data);
+               }
+       } else {
+               //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+               while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                               i_Offset + 12) >> 19) & 1) !=
+                       1) ;
+               //outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+               outl((0x00000800 | s_BoardInfos[dev->minor].i_ChannelNo),
+                       devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                       4);
+               //ui_Configuration = inl(devpriv->iobase+i_Offset + 0);
+               ui_Configuration =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 0);
+      /*************************/
+               /*Set the time unit to ns */
+      /*************************/
+               /* i_TimeUnit= i_ADDIDATAConversionTimeUnit;
+                  i_ADDIDATAConversionTimeUnit= 1; */
+               //i_Temp= i_InterruptFlag ;
+               i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag;
+               //i_InterruptFlag = ADDIDATA_DISABLE;
+               s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE;
+               i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data);
+               //if(i_AutoCalibration == FALSE)
+               if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) {
+                       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+                       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].
+                                                       i_Offset +
+                                                       12) >> 19) & 1) != 1) ;
+                       //outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4);
+                       outl((0x00000800 | s_BoardInfos[dev->minor].
+                                       i_ChannelNo),
+                               devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 4);
+                       data++;
+                       i_APCI3200_ReadCalibrationOffsetValue(dev, data);
+                       data++;
+                       i_APCI3200_ReadCalibrationGainValue(dev, data);
+               }
+       }
+       //i_InterruptFlag=i_Temp ;
+       s_BoardInfos[dev->minor].i_InterruptFlag = i_Temp;
+       //printk("\ni_InterruptFlag=%d\n",i_InterruptFlag);
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : int i_APCI3200_InsnWriteReleaseAnalogInput             |
+  |                      (struct comedi_device *dev,struct comedi_subdevice *s,               |
+  |                      struct comedi_insn *insn,unsigned int *data)                     |
+  +----------------------------------------------------------------------------+
+  | Task              :  Resets the channels                                                      |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
+  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
+  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
+  |                     unsigned int *data          : Data Pointer
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error          |
+  |                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+
+INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev,
+       struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+       i_APCI3200_Reset(dev);
+       return insn->n;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     :int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev|
+  |                    ,struct comedi_subdevice *s,struct comedi_cmd *cmd)                              |
+  |                                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              : Test validity for a command for cyclic anlog input     |
+  |                       acquisition                                                                           |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev                                                                       |
+  |                     struct comedi_subdevice *s                                                                      |
+  |                     struct comedi_cmd *cmd                                                          |
+  |                                                                                                                     |
+  |
+  |                                                                                                                     |
+  |                                                                                                                     |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Return Value      :0                                                                    |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+       struct comedi_cmd * cmd)
+{
+
+       int err = 0;
+       int tmp;                // divisor1,divisor2;
+       UINT ui_ConvertTime = 0;
+       UINT ui_ConvertTimeBase = 0;
+       UINT ui_DelayTime = 0;
+       UINT ui_DelayTimeBase = 0;
+       INT i_Triggermode = 0;
+       INT i_TriggerEdge = 0;
+       INT i_NbrOfChannel = 0;
+       INT i_Cpt = 0;
+       double d_ConversionTimeForAllChannels = 0.0;
+       double d_SCANTimeNewUnit = 0.0;
+       // step 1: make sure trigger sources are trivially valid
+
+       tmp = cmd->start_src;
+       cmd->start_src &= TRIG_NOW | TRIG_EXT;
+       if (!cmd->start_src || tmp != cmd->start_src)
+               err++;
+       tmp = cmd->scan_begin_src;
+       cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
+       if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+               err++;
+       tmp = cmd->convert_src;
+       cmd->convert_src &= TRIG_TIMER;
+       if (!cmd->convert_src || tmp != cmd->convert_src)
+               err++;
+       tmp = cmd->scan_end_src;
+       cmd->scan_end_src &= TRIG_COUNT;
+       if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+               err++;
+       tmp = cmd->stop_src;
+       cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+       if (!cmd->stop_src || tmp != cmd->stop_src)
+               err++;
+       //if(i_InterruptFlag==0)
+       if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) {
+               err++;
+               //          printk("\nThe interrupt should be enabled\n");
+       }
+       if (err) {
+               i_APCI3200_Reset(dev);
+               return 1;
+       }
+
+       if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
+               err++;
+       }
+       if (cmd->start_src == TRIG_EXT) {
+               i_TriggerEdge = cmd->start_arg & 0xFFFF;
+               i_Triggermode = cmd->start_arg >> 16;
+               if (i_TriggerEdge < 1 || i_TriggerEdge > 3) {
+                       err++;
+                       printk("\nThe trigger edge selection is in error\n");
+               }
+               if (i_Triggermode != 2) {
+                       err++;
+                       printk("\nThe trigger mode selection is in error\n");
+               }
+       }
+
+       if (cmd->scan_begin_src != TRIG_TIMER &&
+               cmd->scan_begin_src != TRIG_FOLLOW)
+               err++;
+
+       if (cmd->convert_src != TRIG_TIMER)
+               err++;
+
+       if (cmd->scan_end_src != TRIG_COUNT) {
+               cmd->scan_end_src = TRIG_COUNT;
+               err++;
+       }
+
+       if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
+               err++;
+
+       if (err) {
+               i_APCI3200_Reset(dev);
+               return 2;
+       }
+       //i_FirstChannel=cmd->chanlist[0];
+       s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
+       //i_LastChannel=cmd->chanlist[1];
+       s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
+
+       if (cmd->convert_src == TRIG_TIMER) {
+               ui_ConvertTime = cmd->convert_arg & 0xFFFF;
+               ui_ConvertTimeBase = cmd->convert_arg >> 16;
+               if (ui_ConvertTime != 20 && ui_ConvertTime != 40
+                       && ui_ConvertTime != 80 && ui_ConvertTime != 160)
+               {
+                       printk("\nThe selection of conversion time reload value is in error\n");
+                       err++;
+               }               // if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 )
+               if (ui_ConvertTimeBase != 2) {
+                       printk("\nThe selection of conversion time unit  is in error\n");
+                       err++;
+               }               //if(ui_ConvertTimeBase!=2)
+       } else {
+               ui_ConvertTime = 0;
+               ui_ConvertTimeBase = 0;
+       }
+       if (cmd->scan_begin_src == TRIG_FOLLOW) {
+               ui_DelayTime = 0;
+               ui_DelayTimeBase = 0;
+       }                       //if(cmd->scan_begin_src==TRIG_FOLLOW)
+       else {
+               ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
+               ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
+               if (ui_DelayTimeBase != 2 && ui_DelayTimeBase != 3) {
+                       err++;
+                       printk("\nThe Delay time base selection is in error\n");
+               }
+               if (ui_DelayTime < 1 && ui_DelayTime > 1023) {
+                       err++;
+                       printk("\nThe Delay time value is in error\n");
+               }
+               if (err) {
+                       i_APCI3200_Reset(dev);
+                       return 3;
+               }
+               fpu_begin();
+               d_SCANTimeNewUnit = (double)ui_DelayTime;
+               //i_NbrOfChannel= i_LastChannel-i_FirstChannel + 4;
+               i_NbrOfChannel =
+                       s_BoardInfos[dev->minor].i_LastChannel -
+                       s_BoardInfos[dev->minor].i_FirstChannel + 4;
+      /**********************************************************/
+               /*calculate the total conversion time for all the channels */
+      /**********************************************************/
+               d_ConversionTimeForAllChannels =
+                       (double)((double)ui_ConvertTime /
+                       (double)i_NbrOfChannel);
+
+      /*******************************/
+               /*Convert the frequence in time */
+      /*******************************/
+               d_ConversionTimeForAllChannels =
+                       (double)1.0 / d_ConversionTimeForAllChannels;
+               ui_ConvertTimeBase = 3;
+      /***********************************/
+               /*Test if the time unit is the same */
+      /***********************************/
+
+               if (ui_DelayTimeBase <= ui_ConvertTimeBase) {
+
+                       for (i_Cpt = 0;
+                               i_Cpt < (ui_ConvertTimeBase - ui_DelayTimeBase);
+                               i_Cpt++) {
+
+                               d_ConversionTimeForAllChannels =
+                                       d_ConversionTimeForAllChannels * 1000;
+                               d_ConversionTimeForAllChannels =
+                                       d_ConversionTimeForAllChannels + 1;
+                       }
+               } else {
+                       for (i_Cpt = 0;
+                               i_Cpt < (ui_DelayTimeBase - ui_ConvertTimeBase);
+                               i_Cpt++) {
+                               d_SCANTimeNewUnit = d_SCANTimeNewUnit * 1000;
+
+                       }
+               }
+
+               if (d_ConversionTimeForAllChannels >= d_SCANTimeNewUnit) {
+
+                       printk("\nSCAN Delay value cannot be used\n");
+         /*********************************/
+                       /*SCAN Delay value cannot be used */
+         /*********************************/
+                       err++;
+               }
+               fpu_end();
+       }                       //else if(cmd->scan_begin_src==TRIG_FOLLOW)
+
+       if (err) {
+               i_APCI3200_Reset(dev);
+               return 4;
+       }
+
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     :int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev,|
+  |                                                                                         struct comedi_subdevice *s)|
+  |                                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              : Stop the  acquisition                                                       |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev                                                                       |
+  |                     struct comedi_subdevice *s                                                                      |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Return Value      :0                                                                    |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
+{
+       UINT ui_Configuration = 0;
+       //i_InterruptFlag=0;
+       //i_Initialised=0;
+       //i_Count=0;
+       //i_Sum=0;
+       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+       s_BoardInfos[dev->minor].i_Initialised = 0;
+       s_BoardInfos[dev->minor].i_Count = 0;
+       s_BoardInfos[dev->minor].i_Sum = 0;
+
+  /*******************/
+       /*Read the register */
+  /*******************/
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 8);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+  /*****************************/
+       /*Reset the START and IRQ bit */
+  /*****************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+i_Offset + 8);
+       outl((ui_Configuration & 0xFFE7FFFF),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     : int i_APCI3200_CommandAnalogInput(struct comedi_device *dev,  |
+  |                                                                                            struct comedi_subdevice *s) |
+  |                                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              : Does asynchronous acquisition                          |
+  |                     Determines the mode 1 or 2.                                                 |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev                                                                       |
+  |                     struct comedi_subdevice *s                                                                      |
+  |                                                                                                                                     |
+  |                                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Return Value      :                                                                         |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
+{
+       struct comedi_cmd *cmd = &s->async->cmd;
+       UINT ui_Configuration = 0;
+       //INT  i_CurrentSource = 0;
+       UINT ui_Trigger = 0;
+       UINT ui_TriggerEdge = 0;
+       UINT ui_Triggermode = 0;
+       UINT ui_ScanMode = 0;
+       UINT ui_ConvertTime = 0;
+       UINT ui_ConvertTimeBase = 0;
+       UINT ui_DelayTime = 0;
+       UINT ui_DelayTimeBase = 0;
+       UINT ui_DelayMode = 0;
+       //i_FirstChannel=cmd->chanlist[0];
+       //i_LastChannel=cmd->chanlist[1];
+       s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
+       s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1];
+       if (cmd->start_src == TRIG_EXT) {
+               ui_Trigger = 1;
+               ui_TriggerEdge = cmd->start_arg & 0xFFFF;
+               ui_Triggermode = cmd->start_arg >> 16;
+       }                       //if(cmd->start_src==TRIG_EXT)
+       else {
+               ui_Trigger = 0;
+       }                       //elseif(cmd->start_src==TRIG_EXT)
+
+       if (cmd->stop_src == TRIG_COUNT) {
+               ui_ScanMode = 0;
+       }                       // if (cmd->stop_src==TRIG_COUNT)
+       else {
+               ui_ScanMode = 2;
+       }                       //else if (cmd->stop_src==TRIG_COUNT)
+
+       if (cmd->scan_begin_src == TRIG_FOLLOW) {
+               ui_DelayTime = 0;
+               ui_DelayTimeBase = 0;
+               ui_DelayMode = 0;
+       }                       //if(cmd->scan_begin_src==TRIG_FOLLOW)
+       else {
+               ui_DelayTime = cmd->scan_begin_arg & 0xFFFF;
+               ui_DelayTimeBase = cmd->scan_begin_arg >> 16;
+               ui_DelayMode = 1;
+       }                       //else if(cmd->scan_begin_src==TRIG_FOLLOW)
+       //        printk("\nui_DelayTime=%u\n",ui_DelayTime);
+       //        printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase);
+       if (cmd->convert_src == TRIG_TIMER) {
+               ui_ConvertTime = cmd->convert_arg & 0xFFFF;
+               ui_ConvertTimeBase = cmd->convert_arg >> 16;
+       } else {
+               ui_ConvertTime = 0;
+               ui_ConvertTimeBase = 0;
+       }
+
+       // if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2)))
+       //   {
+  /**************************************************/
+       /*Read the old configuration of the current source */
+  /**************************************************/
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 12);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+  /***********************************************/
+       /*Write the configuration of the current source */
+  /***********************************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+i_Offset +12);
+       outl((ui_Configuration & 0xFFC00000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+       // }
+       ui_Configuration = 0;
+       //     printk("\nfirstchannel=%u\n",i_FirstChannel);
+       //     printk("\nlastchannel=%u\n",i_LastChannel);
+       //     printk("\nui_Trigger=%u\n",ui_Trigger);
+       //     printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge);
+       //     printk("\nui_Triggermode=%u\n",ui_Triggermode);
+       //      printk("\nui_DelayMode=%u\n",ui_DelayMode);
+       //     printk("\nui_ScanMode=%u\n",ui_ScanMode);
+
+       //ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 |
+       ui_Configuration =
+               s_BoardInfos[dev->minor].i_FirstChannel | (s_BoardInfos[dev->
+                       minor].
+               i_LastChannel << 8) | 0x00100000 | (ui_Trigger << 24) |
+               (ui_TriggerEdge << 25) | (ui_Triggermode << 27) | (ui_DelayMode
+               << 18) | (ui_ScanMode << 16);
+
+  /*************************/
+       /*Write the Configuration */
+  /*************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8);
+       outl(ui_Configuration,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x8);
+  /***********************/
+       /*Write the Delay Value */
+  /***********************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_DelayTime,devpriv->iobase+i_Offset + 40);
+       outl(ui_DelayTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 40);
+  /***************************/
+       /*Write the Delay time base */
+  /***************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44);
+       outl(ui_DelayTimeBase,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 44);
+  /*********************************/
+       /*Write the conversion time value */
+  /*********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32);
+       outl(ui_ConvertTime,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+
+  /********************************/
+       /*Write the conversion time base */
+  /********************************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36);
+       outl(ui_ConvertTimeBase,
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /*******************/
+       /*Read the register */
+  /*******************/
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 4);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /******************/
+       /*Set the SCAN bit */
+  /******************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+
+       //outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4);
+       outl(((ui_Configuration & 0x1E0FF) | 0x00002000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************/
+       /*Read the register */
+  /*******************/
+       ui_Configuration = 0;
+       //ui_Configuration = inl(devpriv->iobase+i_Offset + 8);
+       ui_Configuration =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*******************/
+       /*Set the START bit */
+  /*******************/
+       //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1);
+       while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+                                       12) >> 19) & 1) != 1) ;
+       //outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8);
+       outl((ui_Configuration | 0x00080000),
+               devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   :  int i_APCI3200_Reset(struct comedi_device *dev)                            |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Task              :Resets the registers of the card                        |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  :                                                        |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      :                                                        |
+  |                                                                                     |
+  +----------------------------------------------------------------------------+
+*/
+
+int i_APCI3200_Reset(struct comedi_device * dev)
+{
+       INT i_Temp;
+       DWORD dw_Dummy;
+       //i_InterruptFlag=0;
+       //i_Initialised==0;
+       //i_Count=0;
+       //i_Sum=0;
+
+       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+       s_BoardInfos[dev->minor].i_Initialised = 0;
+       s_BoardInfos[dev->minor].i_Count = 0;
+       s_BoardInfos[dev->minor].i_Sum = 0;
+       s_BoardInfos[dev->minor].b_StructInitialized = 0;
+
+       outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
+
+       // Enable the interrupt for the controler
+       dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
+       outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
+       outl(0, devpriv->i_IobaseAddon);        //Resets the output
+  /***************/
+       /*Empty the buffer */
+  /**************/
+       for (i_Temp = 0; i_Temp <= 95; i_Temp++) {
+               //ui_InterruptChannelValue[i_Temp]=0;
+               s_BoardInfos[dev->minor].ui_InterruptChannelValue[i_Temp] = 0;
+       }                       //for(i_Temp=0;i_Temp<=95;i_Temp++)
+  /*****************************/
+       /*Reset the START and IRQ bit */
+  /*****************************/
+       for (i_Temp = 0; i_Temp <= 192;) {
+               while (((inl(devpriv->iobase + i_Temp + 12) >> 19) & 1) != 1) ;
+               outl(0, devpriv->iobase + i_Temp + 8);
+               i_Temp = i_Temp + 64;
+       }                       //for(i_Temp=0;i_Temp<=192;i_Temp+64)
+       return 0;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function   Name   : static void v_APCI3200_Interrupt                                            |
+  |                                      (int irq , void *d)                            |
+  +----------------------------------------------------------------------------+
+  | Task              : Interrupt processing Routine                           |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : int irq                 : irq number                   |
+  |                     void *d                 : void pointer                 |
+  +----------------------------------------------------------------------------+
+  | Output Parameters :        --                                                                                                       |
+  +----------------------------------------------------------------------------+
+  | Return Value      : TRUE  : No error occur                                 |
+  |                        : FALSE : Error occur. Return the error                                      |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+*/
+void v_APCI3200_Interrupt(int irq, void *d)
+{
+       struct comedi_device *dev = d;
+       UINT ui_StatusRegister = 0;
+       UINT ui_ChannelNumber = 0;
+       INT i_CalibrationFlag = 0;
+       INT i_CJCFlag = 0;
+       UINT ui_DummyValue = 0;
+       UINT ui_DigitalTemperature = 0;
+       UINT ui_DigitalInput = 0;
+       int i_ConvertCJCCalibration;
+
+       //BEGIN JK TEST
+       int i_ReturnValue = 0;
+       //END JK TEST
+
+       //printk ("\n i_ScanType = %i i_ADDIDATAType = %i", s_BoardInfos [dev->minor].i_ScanType, s_BoardInfos [dev->minor].i_ADDIDATAType);
+
+       //switch(i_ScanType)
+       switch (s_BoardInfos[dev->minor].i_ScanType) {
+       case 0:
+       case 1:
+               //switch(i_ADDIDATAType)
+               switch (s_BoardInfos[dev->minor].i_ADDIDATAType) {
+               case 0:
+               case 1:
+
+         /************************************/
+                       /*Read the interrupt status register */
+         /************************************/
+                       //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+                       ui_StatusRegister =
+                               inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 16);
+                       if ((ui_StatusRegister & 0x2) == 0x2) {
+                               //i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17);
+                               i_CalibrationFlag =
+                                       ((inl(devpriv->iobase +
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_Offset +
+                                                       12) & 0x00060000) >>
+                                       17);
+             /*************************/
+                               /*Read the channel number */
+             /*************************/
+                               //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+
+             /*************************************/
+                               /*Read the digital analog input value */
+             /*************************************/
+                               //ui_DigitalInput = inl(devpriv->iobase+i_Offset + 28);
+                               ui_DigitalInput =
+                                       inl(devpriv->iobase +
+                                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+             /***********************************************/
+                               /* Test if the value read is the channel value */
+             /***********************************************/
+                               if (i_CalibrationFlag == 0) {
+                                       //ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 0] = ui_DigitalInput;
+
+                                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                       /*
+                                          printk("\n 1 - i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos %i", ui_ChannelNumber);
+                                          i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos [dev->minor].ui_Channel_num,
+                                          &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 6],
+                                          &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 7],
+                                          &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 8]);
+                                        */
+                                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+                 /******************************************************/
+                                       /*Start the conversion of the calibration offset value */
+                 /******************************************************/
+                                       i_APCI3200_ReadCalibrationOffsetValue
+                                               (dev, &ui_DummyValue);
+                               }       //if (i_CalibrationFlag == 0)
+             /**********************************************************/
+                               /* Test if the value read is the calibration offset value */
+             /**********************************************************/
+
+                               if (i_CalibrationFlag == 1) {
+
+                 /******************/
+                                       /* Save the value */
+                 /******************/
+
+                                       //ui_InterruptChannelValue[i_Count + 1] = ui_DigitalInput;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 1] = ui_DigitalInput;
+
+                 /******************************************************/
+                                       /* Start the conversion of the calibration gain value */
+                 /******************************************************/
+                                       i_APCI3200_ReadCalibrationGainValue(dev,
+                                               &ui_DummyValue);
+                               }       //if (i_CalibrationFlag == 1)
+             /******************************************************/
+                               /*Test if the value read is the calibration gain value */
+             /******************************************************/
+
+                               if (i_CalibrationFlag == 2) {
+
+                 /****************/
+                                       /*Save the value */
+                 /****************/
+                                       //ui_InterruptChannelValue[i_Count + 2] = ui_DigitalInput;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 2] = ui_DigitalInput;
+                                       //if(i_ScanType==1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType == 1) {
+
+                                               //i_InterruptFlag=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_InterruptFlag = 0;
+                                               //i_Count=i_Count + 6;
+                                               //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                               //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count =
+                                                       s_BoardInfos[dev->
+                                                       minor].i_Count + 9;
+                                               //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                       }       //if(i_ScanType==1)
+                                       else {
+                                               //i_Count=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count = 0;
+                                       }       //elseif(i_ScanType==1)
+                                       //if(i_ScanType!=1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType != 1) {
+                                               i_ReturnValue = send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+                                       }       //if(i_ScanType!=1)
+                                       else {
+                                               //if(i_ChannelCount==i_Sum)
+                                               if (s_BoardInfos[dev->minor].
+                                                       i_ChannelCount ==
+                                                       s_BoardInfos[dev->
+                                                               minor].i_Sum) {
+                                                       send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+                                               }
+                                       }       //if(i_ScanType!=1)
+                               }       //if (i_CalibrationFlag == 2)
+                       }       // if ((ui_StatusRegister & 0x2) == 0x2)
+
+                       break;
+
+               case 2:
+         /************************************/
+                       /*Read the interrupt status register */
+         /************************************/
+
+                       //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+                       ui_StatusRegister =
+                               inl(devpriv->iobase +
+                               s_BoardInfos[dev->minor].i_Offset + 16);
+         /*************************/
+                       /*Test if interrupt occur */
+         /*************************/
+
+                       if ((ui_StatusRegister & 0x2) == 0x2) {
+
+                               //i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10);
+                               i_CJCFlag =
+                                       ((inl(devpriv->iobase +
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_Offset +
+                                                       4) & 0x00000400) >> 10);
+
+                               //i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17);
+                               i_CalibrationFlag =
+                                       ((inl(devpriv->iobase +
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_Offset +
+                                                       12) & 0x00060000) >>
+                                       17);
+
+             /*************************/
+                               /*Read the channel number */
+             /*************************/
+
+                               //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+                               ui_ChannelNumber =
+                                       inl(devpriv->iobase +
+                                       s_BoardInfos[dev->minor].i_Offset + 24);
+                               //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                               s_BoardInfos[dev->minor].ui_Channel_num =
+                                       ui_ChannelNumber;
+                               //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+             /************************************/
+                               /*Read the digital temperature value */
+             /************************************/
+                               //ui_DigitalTemperature = inl(devpriv->iobase+i_Offset + 28);
+                               ui_DigitalTemperature =
+                                       inl(devpriv->iobase +
+                                       s_BoardInfos[dev->minor].i_Offset + 28);
+
+             /*********************************************/
+                               /*Test if the value read is the channel value */
+             /*********************************************/
+
+                               if ((i_CalibrationFlag == 0)
+                                       && (i_CJCFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 0]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 0] =
+                                               ui_DigitalTemperature;
+
+                 /*********************************/
+                                       /*Start the conversion of the CJC */
+                 /*********************************/
+                                       i_APCI3200_ReadCJCValue(dev,
+                                               &ui_DummyValue);
+
+                               }       //if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0))
+
+                /*****************************************/
+                               /*Test if the value read is the CJC value */
+                /*****************************************/
+
+                               if ((i_CJCFlag == 1)
+                                       && (i_CalibrationFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 3]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 3] =
+                                               ui_DigitalTemperature;
+
+                 /******************************************************/
+                                       /*Start the conversion of the calibration offset value */
+                 /******************************************************/
+                                       i_APCI3200_ReadCalibrationOffsetValue
+                                               (dev, &ui_DummyValue);
+                               }       // if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0))
+
+                /********************************************************/
+                               /*Test if the value read is the calibration offset value */
+                /********************************************************/
+
+                               if ((i_CalibrationFlag == 1)
+                                       && (i_CJCFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 1]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 1] =
+                                               ui_DigitalTemperature;
+
+                 /****************************************************/
+                                       /*Start the conversion of the calibration gain value */
+                 /****************************************************/
+                                       i_APCI3200_ReadCalibrationGainValue(dev,
+                                               &ui_DummyValue);
+
+                               }       //if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0))
+
+             /******************************************************/
+                               /*Test if the value read is the calibration gain value */
+             /******************************************************/
+
+                               if ((i_CalibrationFlag == 2)
+                                       && (i_CJCFlag == 0)) {
+                                       //ui_InterruptChannelValue[i_Count + 2]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 2] =
+                                               ui_DigitalTemperature;
+
+                 /**********************************************************/
+                                       /*Test if the Calibration channel must be read for the CJC */
+                 /**********************************************************/
+
+                                       /*Test if the polarity is the same */
+                 /**********************************/
+                                       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_CJCPolarity !=
+                                               s_BoardInfos[dev->minor].
+                                               i_ADDIDATAPolarity) {
+                                               i_ConvertCJCCalibration = 1;
+                                       }       //if(i_CJCPolarity!=i_ADDIDATAPolarity)
+                                       else {
+                                               //if(i_CJCGain==i_ADDIDATAGain)
+                                               if (s_BoardInfos[dev->minor].
+                                                       i_CJCGain ==
+                                                       s_BoardInfos[dev->
+                                                               minor].
+                                                       i_ADDIDATAGain) {
+                                                       i_ConvertCJCCalibration
+                                                               = 0;
+                                               }       //if(i_CJCGain==i_ADDIDATAGain)
+                                               else {
+                                                       i_ConvertCJCCalibration
+                                                               = 1;
+                                               }       //elseif(i_CJCGain==i_ADDIDATAGain)
+                                       }       //elseif(i_CJCPolarity!=i_ADDIDATAPolarity)
+                                       if (i_ConvertCJCCalibration == 1) {
+                     /****************************************************************/
+                                               /*Start the conversion of the calibration gain value for the CJC */
+                     /****************************************************************/
+                                               i_APCI3200_ReadCJCCalOffset(dev,
+                                                       &ui_DummyValue);
+
+                                       }       //if(i_ConvertCJCCalibration==1)
+                                       else {
+                                               //ui_InterruptChannelValue[i_Count + 4]=0;
+                                               //ui_InterruptChannelValue[i_Count + 5]=0;
+                                               s_BoardInfos[dev->minor].
+                                                       ui_InterruptChannelValue
+                                                       [s_BoardInfos[dev->
+                                                               minor].i_Count +
+                                                       4] = 0;
+                                               s_BoardInfos[dev->minor].
+                                                       ui_InterruptChannelValue
+                                                       [s_BoardInfos[dev->
+                                                               minor].i_Count +
+                                                       5] = 0;
+                                       }       //elseif(i_ConvertCJCCalibration==1)
+                               }       //else if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0))
+
+                /********************************************************************/
+                               /*Test if the value read is the calibration offset value for the CJC */
+                /********************************************************************/
+
+                               if ((i_CalibrationFlag == 1)
+                                       && (i_CJCFlag == 1)) {
+                                       //ui_InterruptChannelValue[i_Count + 4]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 4] =
+                                               ui_DigitalTemperature;
+
+                 /****************************************************************/
+                                       /*Start the conversion of the calibration gain value for the CJC */
+                 /****************************************************************/
+                                       i_APCI3200_ReadCJCCalGain(dev,
+                                               &ui_DummyValue);
+
+                               }       //if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1))
+
+             /******************************************************************/
+                               /*Test if the value read is the calibration gain value for the CJC */
+             /******************************************************************/
+
+                               if ((i_CalibrationFlag == 2)
+                                       && (i_CJCFlag == 1)) {
+                                       //ui_InterruptChannelValue[i_Count + 5]=ui_DigitalTemperature;
+                                       s_BoardInfos[dev->minor].
+                                               ui_InterruptChannelValue
+                                               [s_BoardInfos[dev->minor].
+                                               i_Count + 5] =
+                                               ui_DigitalTemperature;
+
+                                       //if(i_ScanType==1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType == 1) {
+
+                                               //i_InterruptFlag=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_InterruptFlag = 0;
+                                               //i_Count=i_Count + 6;
+                                               //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                               //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count =
+                                                       s_BoardInfos[dev->
+                                                       minor].i_Count + 9;
+                                               //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                                       }       //if(i_ScanType==1)
+                                       else {
+                                               //i_Count=0;
+                                               s_BoardInfos[dev->minor].
+                                                       i_Count = 0;
+                                       }       //elseif(i_ScanType==1)
+
+                                       //if(i_ScanType!=1)
+                                       if (s_BoardInfos[dev->minor].
+                                               i_ScanType != 1) {
+                                               send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+                                       }       //if(i_ScanType!=1)
+                                       else {
+                                               //if(i_ChannelCount==i_Sum)
+                                               if (s_BoardInfos[dev->minor].
+                                                       i_ChannelCount ==
+                                                       s_BoardInfos[dev->
+                                                               minor].i_Sum) {
+                                                       send_sig(SIGIO, devpriv->tsk_Current, 0);       // send signal to the sample
+
+                                               }       //if(i_ChannelCount==i_Sum)
+                                       }       //else if(i_ScanType!=1)
+                               }       //if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1))
+
+                       }       //else if ((ui_StatusRegister & 0x2) == 0x2)
+                       break;
+               }               //switch(i_ADDIDATAType)
+               break;
+       case 2:
+       case 3:
+               i_APCI3200_InterruptHandleEos(dev);
+               break;
+       }                       //switch(i_ScanType)
+       return;
+}
+
+/*
+  +----------------------------------------------------------------------------+
+  | Function name     :int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)   |
+  |                                                                                                             |
+  |                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Task              : .                   |
+  |                     This function copies the acquired data(from FIFO)      |
+  |                            to Comedi buffer.                                                                        |
+  |                                                                                                                     |
+  +----------------------------------------------------------------------------+
+  | Input Parameters  : struct comedi_device *dev                                                                       |
+  |                                                                                                                                     |
+  |                                                                                             |
+  +----------------------------------------------------------------------------+
+  | Return Value      : 0                                                                       |
+  |                                                                                                                                 |
+  +----------------------------------------------------------------------------+
+*/
+int i_APCI3200_InterruptHandleEos(struct comedi_device * dev)
+{
+       UINT ui_StatusRegister = 0;
+       struct comedi_subdevice *s = dev->subdevices + 0;
+
+       //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+       //comedi_async *async = s->async;
+       //UINT *data;
+       //data=async->data+async->buf_int_ptr;//new samples added from here onwards
+       int n = 0, i = 0;
+       //END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+  /************************************/
+       /*Read the interrupt status register */
+  /************************************/
+       //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16);
+       ui_StatusRegister =
+               inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 16);
+
+  /*************************/
+       /*Test if interrupt occur */
+  /*************************/
+
+       if ((ui_StatusRegister & 0x2) == 0x2) {
+      /*************************/
+               /*Read the channel number */
+      /*************************/
+               //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24);
+               //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+               //This value is not used
+               //ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24);
+               s->async->events = 0;
+               //END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+      /*************************************/
+               /*Read the digital Analog Input value */
+      /*************************************/
+
+               //data[i_Count] = inl(devpriv->iobase+i_Offset + 28);
+               //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+               //data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28);
+               s_BoardInfos[dev->minor].ui_ScanValueArray[s_BoardInfos[dev->
+                               minor].i_Count] =
+                       inl(devpriv->iobase +
+                       s_BoardInfos[dev->minor].i_Offset + 28);
+               //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+               //if((i_Count == (i_LastChannel-i_FirstChannel+3)))
+               if ((s_BoardInfos[dev->minor].i_Count ==
+                               (s_BoardInfos[dev->minor].i_LastChannel -
+                                       s_BoardInfos[dev->minor].
+                                       i_FirstChannel + 3))) {
+
+                       //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+                       s_BoardInfos[dev->minor].i_Count++;
+
+                       for (i = s_BoardInfos[dev->minor].i_FirstChannel;
+                               i <= s_BoardInfos[dev->minor].i_LastChannel;
+                               i++) {
+                               i_APCI3200_GetChannelCalibrationValue(dev, i,
+                                       &s_BoardInfos[dev->minor].
+                                       ui_ScanValueArray[s_BoardInfos[dev->
+                                                       minor].i_Count + ((i -
+                                                               s_BoardInfos
+                                                               [dev->minor].
+                                                               i_FirstChannel)
+                                                       * 3)],
+                                       &s_BoardInfos[dev->minor].
+                                       ui_ScanValueArray[s_BoardInfos[dev->
+                                                       minor].i_Count + ((i -
+                                                               s_BoardInfos
+                                                               [dev->minor].
+                                                               i_FirstChannel)
+                                                       * 3) + 1],
+                                       &s_BoardInfos[dev->minor].
+                                       ui_ScanValueArray[s_BoardInfos[dev->
+                                                       minor].i_Count + ((i -
+                                                               s_BoardInfos
+                                                               [dev->minor].
+                                                               i_FirstChannel)
+                                                       * 3) + 2]);
+                       }
+
+                       //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+                       //i_Count=-1;
+
+                       s_BoardInfos[dev->minor].i_Count = -1;
+
+                       //async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
+                       //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT);
+                       //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT);
+                       //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT);
+                       //comedi_eos(dev,s);
+
+                       // Set the event type (Comedi Buffer End Of Scan)
+                       s->async->events |= COMEDI_CB_EOS;
+
+                       // Test if enougth memory is available and allocate it for 7 values
+                       //n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int));
+                       n = comedi_buf_write_alloc(s->async,
+                               (7 + 12) * sizeof(unsigned int));
+
+                       // If not enougth memory available, event is set to Comedi Buffer Errror
+                       if (n > ((7 + 12) * sizeof(unsigned int))) {
+                               printk("\ncomedi_buf_write_alloc n = %i", n);
+                               s->async->events |= COMEDI_CB_ERROR;
+                       }
+                       // Write all 7 scan values in the comedi buffer
+                       comedi_buf_memcpy_to(s->async, 0,
+                               (unsigned int *) s_BoardInfos[dev->minor].
+                               ui_ScanValueArray, (7 + 12) * sizeof(unsigned int));
+
+                       // Update comedi buffer pinters indexes
+                       comedi_buf_write_free(s->async,
+                               (7 + 12) * sizeof(unsigned int));
+
+                       // Send events
+                       comedi_event(dev, s);
+                       //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+                       //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+                       //
+                       //if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over
+                       //  {
+                       //    /* buffer rollover */
+                       //    s->async->buf_int_ptr=0;
+                       //    comedi_eobuf(dev,s);
+                       //  }
+                       //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+               }
+               //i_Count++;
+               s_BoardInfos[dev->minor].i_Count++;
+       }
+       //i_InterruptFlag=0;
+       s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+       return 0;
+}