aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers/addi-data
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers/addi-data')
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c1047
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h73
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c2032
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h74
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c1020
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h46
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c5363
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h271
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c861
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h47
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c3588
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h76
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c848
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h43
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c2049
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h57
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c1038
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h44
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c203
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h27
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h476
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c3062
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.h462
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_eeprom.c1158
-rw-r--r--drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h457
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c1265
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h71
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c600
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h123
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c285
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h63
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c3045
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h165
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c542
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h64
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c1105
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h119
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c780
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h94
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c460
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h70
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c579
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h81
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c549
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h61
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c2697
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h241
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c3642
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h187
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c742
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h94
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c1691
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h62
53 files changed, 43899 insertions, 0 deletions
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
new file mode 100644
index 000000000000..c96aee09e1b6
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
@@ -0,0 +1,1047 @@
+/*
+ * 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.
+ */
+/*
+ | Description : APCI-1710 82X54 timer module |
+*/
+
+#include "APCI1710_82x54.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitTimer |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TimerNbr, |
+| BYTE_ b_TimerMode, |
+| ULONG_ ul_ReloadValue, |
+| BYTE_ b_InputClockSelection, |
+| BYTE_ b_InputClockLevel, |
+| BYTE_ b_OutputLevel, |
+| BYTE_ b_HardwareGateLevel)
+INT i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data)
+|
++----------------------------------------------------------------------------+
+| Task : Configure the Timer (b_TimerNbr) operating mode |
+| (b_TimerMode) from selected module (b_ModulNbr). |
+| You must calling this function be for you call any |
+| other function witch access of the timer. |
+| |
+| |
+| Timer mode description table |
+| |
+|+--------+-----------------------------+--------------+--------------------+|
+||Selected+ Mode description +u_ReloadValue | Hardware gate input||
+|| mode | | description | action ||
+|+--------+-----------------------------+--------------+--------------------+|
+|| |Mode 0 is typically used | | ||
+|| |for event counting. After | | ||
+|| |the initialisation, OUT | | ||
+|| |is initially low, and | | ||
+|| 0 |will remain low until the |Start counting| Hardware gate ||
+|| |counter reaches zero. | value | ||
+|| |OUT then goes high and | | ||
+|| |remains high until a new | | ||
+|| |count is written. See | | ||
+|| |"i_APCI1710_WriteTimerValue" | | ||
+|| |function. | | ||
+|+--------+-----------------------------+--------------+--------------------+|
+|| |Mode 1 is similar to mode 0 | | ||
+|| |except for the gate input | | ||
+|| 1 |action. The gate input is not|Start counting| Hardware trigger ||
+|| |used for enabled or disabled | value | ||
+|| |the timer. | | ||
+|| |The gate input is used for | | ||
+|| |triggered the timer. | | ||
+|+--------+-----------------------------+--------------+--------------------+|
+|| |This mode functions like a | | ||
+|| |divide-by-ul_ReloadValue | | ||
+|| |counter. It is typically used| | ||
+|| |to generate a real time clock| | ||
+|| |interrupt. OUT will initially| | ||
+|| 2 |be high after the | Division | Hardware gate ||
+|| |initialisation. When the | factor | ||
+|| |initial count has decremented| | ||
+|| |to 1, OUT goes low for one | | ||
+|| |CLK pule. OUT then goes high | | ||
+|| |again, the counter reloads | | ||
+|| |the initial count | | ||
+|| |(ul_ReloadValue) and the | | ||
+|| |process is repeated. | | ||
+|| |This action can generated a | | ||
+|| |interrupt. See function | | ||
+|| |"i_APCI1710_SetBoardInt- | | ||
+|| |RoutineX" | | ||
+|| |and "i_APCI1710_EnableTimer" | | ||
+|+--------+-----------------------------+--------------+--------------------+|
+|| |Mode 3 is typically used for | | ||
+|| |baud rate generation. This | | ||
+|| |mode is similar to mode 2 | | ||
+|| |except for the duty cycle of | | ||
+|| 3 |OUT. OUT will initially be | Division | Hardware gate ||
+|| |high after the initialisation| factor | ||
+|| |When half the initial count | | ||
+|| |(ul_ReloadValue) has expired,| | ||
+|| |OUT goes low for the | | ||
+|| |remainder of the count. The | | ||
+|| |mode is periodic; the | | ||
+|| |sequence above is repeated | | ||
+|| |indefinitely. | | ||
+|+--------+-----------------------------+--------------+--------------------+|
+|| |OUT will be initially high | | ||
+|| |after the initialisation. | | ||
+|| |When the initial count | | ||
+|| 4 |expires OUT will go low for |Start counting| Hardware gate ||
+|| |one CLK pulse and then go | value | ||
+|| |high again. | | ||
+|| |The counting sequences is | | ||
+|| |triggered by writing a new | | ||
+|| |value. See | | ||
+|| |"i_APCI1710_WriteTimerValue" | | ||
+|| |function. If a new count is | | ||
+|| |written during counting, | | ||
+|| |it will be loaded on the | | ||
+|| |next CLK pulse | | ||
+|+--------+-----------------------------+--------------+--------------------+|
+|| |Mode 5 is similar to mode 4 | | ||
+|| |except for the gate input | | ||
+|| |action. The gate input is not| | ||
+|| 5 |used for enabled or disabled |Start counting| Hardware trigger ||
+|| |the timer. The gate input is | value | ||
+|| |used for triggered the timer.| | ||
+|+--------+-----------------------------+--------------+--------------------+|
+| |
+| |
+| |
+| Input clock selection table |
+| |
+| +--------------------------------+------------------------------------+ |
+| | b_InputClockSelection | Description | |
+| | parameter | | |
+| +--------------------------------+------------------------------------+ |
+| | APCI1710_PCI_BUS_CLOCK | For the timer input clock, the PCI | |
+| | | bus clock / 4 is used. This PCI bus| |
+| | | clock can be 30MHz or 33MHz. For | |
+| | | Timer 0 only this selection are | |
+| | | available. | |
+| +--------------------------------+------------------------------------+ |
+| | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the| |
+| | | possibility to inject a input clock| |
+| | | for Timer 1 or Timer 2. The source | |
+| | | from this clock can eat the output | |
+| | | clock from Timer 0 or any other | |
+| | | clock source. | |
+| +--------------------------------+------------------------------------+ |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board |
+| APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
+| BYTE_ b_TimerNbr : Timer number to |
+| configure (0 to 2) |
+| BYTE_ b_TimerMode : Timer mode selection |
+| (0 to 5) |
+| 0: Interrupt on terminal|
+| count |
+| 1: Hardware |
+| retriggerable one- |
+| shot |
+| 2: Rate generator |
+| 3: Square wave mode |
+| 4: Software triggered |
+| strobe |
+| 5: Hardware triggered |
+| strobe |
+| See timer mode |
+| description table. |
+| ULONG_ ul_ReloadValue : Start counting value |
+| or division factor |
+| See timer mode |
+| description table. |
+| BYTE_ b_InputClockSelection : Selection from input |
+| timer clock. |
+| See input clock |
+| selection table. |
+| BYTE_ b_InputClockLevel : Selection from input |
+| clock level. |
+| 0 : Low active |
+| (Input inverted) |
+| 1 : High active |
+| BYTE_ b_OutputLevel, : Selection from output |
+| clock level. |
+| 0 : Low active |
+| 1 : High active |
+| (Output inverted) |
+| BYTE_ b_HardwareGateLevel : Selection from |
+| hardware gate level. |
+| 0 : Low active |
+| (Input inverted) |
+| 1 : High active |
+| If you will not used |
+| the hardware gate set |
+| this value to 0.
+|b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+ b_TimerMode = (BYTE) data[0];
+ ul_ReloadValue = (ULONG) data[1];
+ b_InputClockSelection =(BYTE) data[2];
+ b_InputClockLevel =(BYTE) data[3];
+ b_OutputLevel =(BYTE) data[4];
+ b_HardwareGateLevel =(BYTE) data[5];
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: Timer selection wrong |
+| -4: The module is not a TIMER module |
+| -5: Timer mode selection is wrong |
+| -6: Input timer clock selection is wrong |
+| -7: Selection from input clock level is wrong |
+| -8: Selection from output clock level is wrong |
+| -9: Selection from hardware gate level is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ INT i_ReturnValue = 0;
+ BYTE b_ModulNbr;
+ BYTE b_TimerNbr;
+ BYTE b_TimerMode;
+ ULONG ul_ReloadValue;
+ BYTE b_InputClockSelection;
+ BYTE b_InputClockLevel;
+ BYTE b_OutputLevel;
+ BYTE b_HardwareGateLevel;
+
+ //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+ DWORD dw_Test = 0;
+ //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+ b_TimerMode = (BYTE) data[0];
+ ul_ReloadValue = (ULONG) data[1];
+ b_InputClockSelection = (BYTE) data[2];
+ b_InputClockLevel = (BYTE) data[3];
+ b_OutputLevel = (BYTE) data[4];
+ b_HardwareGateLevel = (BYTE) data[5];
+
+ /* Test the module number */
+ if (b_ModulNbr < 4) {
+ /* Test if 82X54 timer */
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ /* Test the timer number */
+
+ if (b_TimerNbr <= 2) {
+ /* Test the timer mode */
+ if (b_TimerMode <= 5) {
+ //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+ /* Test te imput clock selection */
+ /*
+ if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) ||
+ ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1))))
+ */
+
+ if (((b_TimerNbr == 0) &&
+ (b_InputClockSelection == APCI1710_PCI_BUS_CLOCK)) ||
+ ((b_TimerNbr == 0) &&
+ (b_InputClockSelection == APCI1710_10MHZ)) ||
+ ((b_TimerNbr != 0) &&
+ ((b_InputClockSelection == APCI1710_PCI_BUS_CLOCK) ||
+ (b_InputClockSelection == APCI1710_FRONT_CONNECTOR_INPUT) ||
+ (b_InputClockSelection == APCI1710_10MHZ)))) {
+ //BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+ if (((b_InputClockSelection == APCI1710_10MHZ) &&
+ ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) ||
+ (b_InputClockSelection != APCI1710_10MHZ)) {
+ //END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz
+ /* Test the input clock level selection */
+
+ if ((b_InputClockLevel == 0) ||
+ (b_InputClockLevel == 1)) {
+ /* Test the output clock level selection */
+ if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) {
+ /* Test the hardware gate level selection */
+ if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) {
+ //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+ /* Test if version > 1.1 and clock selection = 10MHz */
+ if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) {
+ /* Test if 40MHz quartz on board */
+ dw_Test = inl(devpriv->s_BoardInfos.ui_Address + (16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)));
+
+ dw_Test = (dw_Test >> 16) & 1;
+ } else {
+ dw_Test = 1;
+ }
+
+ /* Test if detection OK */
+ if (dw_Test == 1) {
+ //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+ /* Initialisation OK */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init = 1;
+
+ /* Save the input clock selection */
+ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockSelection = b_InputClockSelection;
+
+ /* Save the input clock level */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockLevel = ~b_InputClockLevel & 1;
+
+ /* Save the output level */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel = ~b_OutputLevel & 1;
+
+ /* Save the gate level */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel;
+
+ /* Set the configuration word and disable the timer */
+ //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+ /*
+ devpriv->s_ModuleInfo [b_ModulNbr].
+ s_82X54ModuleInfo.
+ s_82X54TimerInfo [b_TimerNbr].
+ dw_ConfigurationWord = (DWORD) (((b_HardwareGateLevel << 0) & 0x1) |
+ ((b_InputClockLevel << 1) & 0x2) |
+ (((~b_OutputLevel & 1) << 2) & 0x4) |
+ ((b_InputClockSelection << 4) & 0x10));
+ */
+ /* Test if 10MHz selected */
+ if (b_InputClockSelection == APCI1710_10MHZ) {
+ b_InputClockSelection = 2;
+ }
+
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (DWORD)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30));
+ //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+ /* Initialise the 82X54 Timer */
+ outl((DWORD) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+ /* Write the reload value */
+ outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ //BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+ } // if (dw_Test == 1)
+ else {
+ /* Input timer clock selection is wrong */
+ i_ReturnValue = -6;
+ } // if (dw_Test == 1)
+ //END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz
+ } // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))
+ else {
+ /* Selection from hardware gate level is wrong */
+ DPRINTK("Selection from hardware gate level is wrong\n");
+ i_ReturnValue = -9;
+ } // if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1))
+ } // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
+ else {
+ /* Selection from output clock level is wrong */
+ DPRINTK("Selection from output clock level is wrong\n");
+ i_ReturnValue = -8;
+ } // if ((b_OutputLevel == 0) || (b_OutputLevel == 1))
+ } // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
+ else {
+ /* Selection from input clock level is wrong */
+ DPRINTK("Selection from input clock level is wrong\n");
+ i_ReturnValue = -7;
+ } // if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1))
+ } else {
+ /* Input timer clock selection is wrong */
+ DPRINTK("Input timer clock selection is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /* Input timer clock selection is wrong */
+ DPRINTK("Input timer clock selection is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
+ else {
+ /* Timer mode selection is wrong */
+ DPRINTK("Timer mode selection is wrong\n");
+ i_ReturnValue = -5;
+ } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5))
+ } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+ else {
+ /* Timer selection wrong */
+ DPRINTK("Timer selection wrong\n");
+ i_ReturnValue = -3;
+ } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+ } else {
+ /* The module is not a TIMER module */
+ DPRINTK("The module is not a TIMER module\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /* Module number error */
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnableTimer |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TimerNbr, |
+| BYTE_ b_InterruptEnable)
+INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Enable OR Disable the Timer (b_TimerNbr) from selected module |
+| (b_ModulNbr). You must calling the |
+| "i_APCI1710_InitTimer" function be for you call this |
+| function. If you enable the timer interrupt, the timer |
+| generate a interrupt after the timer value reach |
+| the zero. See function "i_APCI1710_SetBoardIntRoutineX"|
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board |
+| APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number |
+| (0 to 3) |
+| BYTE_ b_TimerNbr : Timer number to enable |
+| (0 to 2) |
+| BYTE_ b_InterruptEnable : Enable or disable the |
+| timer interrupt. |
+| APCI1710_ENABLE : |
+| Enable the timer interrupt |
+| APCI1710_DISABLE : |
+| Disable the timer interrupt|
+i_ReturnValue=insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+ b_ActionType = (BYTE) data[0]; // enable disable
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: Timer selection wrong |
+| -4: The module is not a TIMER module |
+| -5: Timer not initialised see function |
+| "i_APCI1710_InitTimer" |
+| -6: Interrupt parameter is wrong |
+| -7: Interrupt function not initialised. |
+| See function "i_APCI1710_SetBoardIntRoutineX" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device * dev,
+ struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_DummyRead;
+ BYTE b_ModulNbr;
+ BYTE b_TimerNbr;
+ BYTE b_ActionType;
+ BYTE b_InterruptEnable;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec);
+ b_ActionType = (BYTE) data[0]; // enable disable
+
+ /* Test the module number */
+ if (b_ModulNbr < 4) {
+ /* Test if 82X54 timer */
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ /* Test the timer number */
+ if (b_TimerNbr <= 2) {
+ /* Test if timer initialised */
+ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
+
+ switch (b_ActionType) {
+ case APCI1710_ENABLE:
+ b_InterruptEnable = (BYTE) data[1];
+ /* Test the interrupt selection */
+ if ((b_InterruptEnable == APCI1710_ENABLE) ||
+ (b_InterruptEnable == APCI1710_DISABLE)) {
+ if (b_InterruptEnable == APCI1710_ENABLE) {
+
+ dw_DummyRead = inl(devpriv->s_BoardInfos.ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+ /* Enable the interrupt */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord | 0x8;
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ devpriv->tsk_Current = current; // Save the current process task structure
+
+ } // if (b_InterruptEnable == APCI1710_ENABLE)
+ else {
+ /* Disable the interrupt */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7;
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+ /* Save the interrupt flag */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));
+ } // if (b_InterruptEnable == APCI1710_ENABLE)
+
+ /* Test if error occur */
+ if (i_ReturnValue >= 0) {
+ /* Save the interrupt flag */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask | ((1 & b_InterruptEnable) << b_TimerNbr);
+
+ /* Enable the timer */
+ outl(1, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ }
+ } else {
+ /* Interrupt parameter is wrong */
+ DPRINTK("\n");
+ i_ReturnValue = -6;
+ }
+ break;
+ case APCI1710_DISABLE:
+ /* Test the interrupt flag */
+ if (((devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask >> b_TimerNbr) & 1) == 1) {
+ /* Disable the interrupt */
+
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr]. dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7;
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+ /* Save the interrupt flag */
+ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr));
+ }
+
+ /* Disable the timer */
+ outl(0, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ break;
+ } // Switch end
+ } else {
+ /* Timer not initialised see function */
+ DPRINTK ("Timer not initialised see function\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /* Timer selection wrong */
+ DPRINTK("Timer selection wrong\n");
+ i_ReturnValue = -3;
+ } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+ } else {
+ /* The module is not a TIMER module */
+ DPRINTK("The module is not a TIMER module\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /* Module number error */
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadAllTimerValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PULONG_ pul_TimerValueArray)
+INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the all timer values from selected timer |
+| module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board |
+| APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_TimerValueArray : Timer value array. |
+| Element 0 contain the timer 0 value. |
+| Element 1 contain the timer 1 value. |
+| Element 2 contain the timer 2 value. |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a TIMER module |
+| -4: Timer 0 not initialised see function |
+| "i_APCI1710_InitTimer" |
+| -5: Timer 1 not initialised see function |
+| "i_APCI1710_InitTimer" |
+| -6: Timer 2 not initialised see function |
+| "i_APCI1710_InitTimer" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ INT i_ReturnValue = 0;
+ BYTE b_ModulNbr, b_ReadType;
+ PULONG pul_TimerValueArray;
+
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_ReadType = CR_CHAN(insn->chanspec);
+ pul_TimerValueArray = (PULONG) data;
+ i_ReturnValue = insn->n;
+
+ switch (b_ReadType) {
+ case APCI1710_TIMER_READINTERRUPT:
+
+ data[0] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].b_OldModuleMask;
+ data[1] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+ data[2] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+ /* Increment the read FIFO */
+ devpriv->s_InterruptParameters.ui_Read = (devpriv->s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+ break;
+
+ case APCI1710_TIMER_READALLTIMER:
+ /* Test the module number */
+ if (b_ModulNbr < 4) {
+ /* Test if 82X54 timer */
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ /* Test if timer 0 iniutialised */
+ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[0].b_82X54Init == 1) {
+ /* Test if timer 1 iniutialised */
+ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[1].b_82X54Init == 1) {
+ /* Test if timer 2 iniutialised */
+ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[2].b_82X54Init == 1) {
+ /* Latch all counter */
+ outl(0x17, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
+
+ /* Read the timer 0 value */
+ pul_TimerValueArray[0] = inl(devpriv->s_BoardInfos.ui_Address + 0 + (64 * b_ModulNbr));
+
+ /* Read the timer 1 value */
+ pul_TimerValueArray[1] = inl(devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
+
+ /* Read the timer 2 value */
+ pul_TimerValueArray[2] = inl(devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr));
+ } else {
+ /* Timer 2 not initialised see function */
+ DPRINTK("Timer 2 not initialised see function\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /* Timer 1 not initialised see function */
+ DPRINTK("Timer 1 not initialised see function\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /* Timer 0 not initialised see function */
+ DPRINTK("Timer 0 not initialised see function\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /* The module is not a TIMER module */
+ DPRINTK("The module is not a TIMER module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /* Module number error */
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ } // End of Switch
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
+struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read write functions for Timer |
++----------------------------------------------------------------------------+
+| Input Parameters :
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_BitsType;
+ INT i_ReturnValue = 0;
+ b_BitsType = data[0];
+
+ printk("\n82X54");
+
+ switch (b_BitsType) {
+ case APCI1710_TIMER_READVALUE:
+ i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
+ (BYTE)CR_AREF(insn->chanspec),
+ (BYTE)CR_CHAN(insn->chanspec),
+ (PULONG) & data[0]);
+ break;
+
+ case APCI1710_TIMER_GETOUTPUTLEVEL:
+ i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
+ (BYTE)CR_AREF(insn->chanspec),
+ (BYTE)CR_CHAN(insn->chanspec),
+ (PBYTE) &data[0]);
+ break;
+
+ case APCI1710_TIMER_GETPROGRESSSTATUS:
+ i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
+ (BYTE)CR_AREF(insn->chanspec),
+ (BYTE)CR_CHAN(insn->chanspec),
+ (PBYTE)&data[0]);
+ break;
+
+ case APCI1710_TIMER_WRITEVALUE:
+ i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
+ (BYTE)CR_AREF(insn->chanspec),
+ (BYTE)CR_CHAN(insn->chanspec),
+ (ULONG)data[1]);
+
+ break;
+
+ default:
+ printk("Bits Config Parameter Wrong\n");
+ i_ReturnValue = -1;
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadTimerValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TimerNbr, |
+| PULONG_ pul_TimerValue) |
++----------------------------------------------------------------------------+
+| Task : Return the timer value from selected digital timer |
+| (b_TimerNbr) from selected timer module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board |
+| APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number |
+| (0 to 3) |
+| BYTE_ b_TimerNbr : Timer number to read |
+| (0 to 2) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_TimerValue : Timer value |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: Timer selection wrong |
+| -4: The module is not a TIMER module |
+| -5: Timer not initialised see function |
+| "i_APCI1710_InitTimer" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadTimerValue(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ PULONG pul_TimerValue)
+{
+ INT i_ReturnValue = 0;
+
+ /* Test the module number */
+ if (b_ModulNbr < 4) {
+ /* Test if 82X54 timer */
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ /* Test the timer number */
+ if (b_TimerNbr <= 2) {
+ /* Test if timer initialised */
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_82X54ModuleInfo.
+ s_82X54TimerInfo[b_TimerNbr].
+ b_82X54Init == 1) {
+ /* Latch the timer value */
+ outl((2 << b_TimerNbr) | 0xD0,
+ devpriv->s_BoardInfos.
+ ui_Address + 12 +
+ (64 * b_ModulNbr));
+
+ /* Read the counter value */
+ *pul_TimerValue =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + (b_TimerNbr * 4) +
+ (64 * b_ModulNbr));
+ } else {
+ /* Timer not initialised see function */
+ DPRINTK("Timer not initialised see function\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /* Timer selection wrong */
+ DPRINTK("Timer selection wrong\n");
+ i_ReturnValue = -3;
+ } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+ } else {
+ /* The module is not a TIMER module */
+ DPRINTK("The module is not a TIMER module\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /* Module number error */
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : _INT_ i_APCI1710_GetTimerOutputLevel |
+ | (BYTE_ b_BoardHandle, |
+ | BYTE_ b_ModulNbr, |
+ | BYTE_ b_TimerNbr, |
+ | PBYTE_ pb_OutputLevel) |
+ +----------------------------------------------------------------------------+
+ | Task : Return the output signal level (pb_OutputLevel) from |
+ | selected digital timer (b_TimerNbr) from selected timer|
+ | module (b_ModulNbr). |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : BYTE_ b_BoardHandle : Handle of board |
+ | APCI-1710 |
+ | BYTE_ b_ModulNbr : Selected module number |
+ | (0 to 3) |
+ | BYTE_ b_TimerNbr : Timer number to test |
+ | (0 to 2) |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PBYTE_ pb_OutputLevel : Output signal level |
+ | 0 : The output is low |
+ | 1 : The output is high |
+ +----------------------------------------------------------------------------+
+ | Return Value : 0: No error |
+ | -1: The handle parameter of the board is wrong |
+ | -2: Module selection wrong |
+ | -3: Timer selection wrong |
+ | -4: The module is not a TIMER module |
+ | -5: Timer not initialised see function |
+ | "i_APCI1710_InitTimer" |
+ +----------------------------------------------------------------------------+
+ */
+
+INT i_APCI1710_GetTimerOutputLevel(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ PBYTE pb_OutputLevel)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_TimerStatus;
+
+ /* Test the module number */
+ if (b_ModulNbr < 4) {
+ /* Test if 82X54 timer */
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ /* Test the timer number */
+ if (b_TimerNbr <= 2) {
+ /* Test if timer initialised */
+ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
+ /* Latch the timer value */
+ outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
+
+ /* Read the timer status */
+ dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+ *pb_OutputLevel = (BYTE) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel);
+ } else {
+ /* Timer not initialised see function */
+ DPRINTK("Timer not initialised see function\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /* Timer selection wrong */
+ DPRINTK("Timer selection wrong\n");
+ i_ReturnValue = -3;
+ } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+ } else {
+ /* The module is not a TIMER module */
+ DPRINTK("The module is not a TIMER module\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /* Module number error */
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetTimerProgressStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TimerNbr, |
+| PBYTE_ pb_TimerStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the progress status (pb_TimerStatus) from |
+| selected digital timer (b_TimerNbr) from selected timer|
+| module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board |
+| APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number |
+| (0 to 3) |
+| BYTE_ b_TimerNbr : Timer number to test |
+| (0 to 2) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_TimerStatus : Output signal level |
+| 0 : Timer not in progress |
+| 1 : Timer in progress |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: Timer selection wrong |
+| -4: The module is not a TIMER module |
+| -5: Timer not initialised see function |
+| "i_APCI1710_InitTimer" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ PBYTE pb_TimerStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_TimerStatus;
+
+ /* Test the module number */
+ if (b_ModulNbr < 4) {
+ /* Test if 82X54 timer */
+
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ /* Test the timer number */
+ if (b_TimerNbr <= 2) {
+ /* Test if timer initialised */
+ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
+ /* Latch the timer value */
+ outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
+
+ /* Read the timer status */
+ dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+
+ *pb_TimerStatus = (BYTE) ((dw_TimerStatus) >> 8) & 1;
+ printk("ProgressStatus : %d", *pb_TimerStatus);
+ } else {
+ /* Timer not initialised see function */
+ i_ReturnValue = -5;
+ }
+ } else {
+ /* Timer selection wrong */
+ i_ReturnValue = -3;
+ } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+ } else {
+ /* The module is not a TIMER module */
+
+ i_ReturnValue = -4;
+ }
+ } else {
+ /* Module number error */
+
+ i_ReturnValue = -2;
+ }
+
+ return i_ReturnValue;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_WriteTimerValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TimerNbr, |
+| ULONG_ ul_WriteValue) |
++----------------------------------------------------------------------------+
+| Task : Write the value (ul_WriteValue) into the selected timer|
+| (b_TimerNbr) from selected timer module (b_ModulNbr). |
+| The action in depend of the time mode selection. |
+| See timer mode description table. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board |
+| APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number |
+| (0 to 3) |
+| BYTE_ b_TimerNbr : Timer number to write |
+| (0 to 2) |
+| ULONG_ ul_WriteValue : Value to write |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: Timer selection wrong |
+| -4: The module is not a TIMER module |
+| -5: Timer not initialised see function |
+| "i_APCI1710_InitTimer" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_WriteTimerValue(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ ULONG ul_WriteValue)
+{
+ INT i_ReturnValue = 0;
+
+ /* Test the module number */
+ if (b_ModulNbr < 4) {
+ /* Test if 82X54 timer */
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+ /* Test the timer number */
+ if (b_TimerNbr <= 2) {
+ /* Test if timer initialised */
+ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) {
+ /* Write the value */
+ outl(ul_WriteValue, devpriv->s_BoardInfos.ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr));
+ } else {
+ /* Timer not initialised see function */
+ DPRINTK("Timer not initialised see function\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /* Timer selection wrong */
+ DPRINTK("Timer selection wrong\n");
+ i_ReturnValue = -3;
+ } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2))
+ } else {
+ /* The module is not a TIMER module */
+ DPRINTK("The module is not a TIMER module\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /* Module number error */
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return i_ReturnValue;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
new file mode 100644
index 000000000000..4797c0b77a43
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_PCI_BUS_CLOCK 0
+#define APCI1710_FRONT_CONNECTOR_INPUT 1
+#define APCI1710_TIMER_READVALUE 0
+#define APCI1710_TIMER_GETOUTPUTLEVEL 1
+#define APCI1710_TIMER_GETPROGRESSSTATUS 2
+#define APCI1710_TIMER_WRITEVALUE 3
+
+#define APCI1710_TIMER_READINTERRUPT 1
+#define APCI1710_TIMER_READALLTIMER 2
+
+/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
+#ifndef APCI1710_10MHZ
+#define APCI1710_10MHZ 10
+#endif
+/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
+
+/*
+ * 82X54 TIMER INISIALISATION FUNCTION
+ */
+INT i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*
+ * 82X54 READ FUNCTION
+ */
+INT i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*
+ * 82X54 READ & WRITE FUNCTION
+ */
+INT i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ PULONG pul_TimerValue);
+
+INT i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ PBYTE pb_OutputLevel);
+
+INT i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ PBYTE pb_TimerStatus);
+
+/*
+ * 82X54 WRITE FUNCTION
+ */
+INT i_APCI1710_WriteTimerValue(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_TimerNbr,
+ ULONG ul_WriteValue);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
new file mode 100644
index 000000000000..1a54d3b2c694
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
@@ -0,0 +1,2032 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : CHRONO.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 chronometer module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | 29/06/98 | S. Weber | Digital input / output implementation |
+ |----------|-----------|------------------------------------------------|
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+ | | | |
+ | | | |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "APCI1710_Chrono.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitChrono |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_ChronoMode, |
+| BYTE_ b_PCIInputClock, |
+| BYTE_ b_TimingUnit, |
+| ULONG_ ul_TimingInterval, |
+| PULONG_ pul_RealTimingInterval)
+
++----------------------------------------------------------------------------+
+| Task : Configure the chronometer operating mode (b_ChronoMode)|
+| from selected module (b_ModulNbr). |
+| The ul_TimingInterval and ul_TimingUnit determine the |
+| timing base for the measurement. |
+| The pul_RealTimingInterval return the real timing |
+| value. You must calling this function be for you call |
+| any other function witch access of the chronometer. |
+| |
+| Witch this functionality from the APCI-1710 you have |
+| the possibility to measure the timing witch two event. |
+| |
+| The mode 0 and 1 is appropriate for period measurement.|
+| The mode 2 and 3 is appropriate for frequent |
+| measurement. |
+| The mode 4 to 7 is appropriate for measuring the timing|
+| between two event. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr CR_AREF(insn->chanspec) : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_ChronoMode data[0] : Chronometer action mode |
+| (0 to 7). |
+| BYTE_ b_PCIInputClock data[1] : Selection from PCI bus clock|
+| - APCI1710_30MHZ : |
+| The PC have a PCI bus |
+| clock from 30 MHz |
+| - APCI1710_33MHZ : |
+| The PC have a PCI bus |
+| clock from 33 MHz |
+| - APCI1710_40MHZ |
+| The APCI-1710 have a |
+| integrated 40Mhz |
+| quartz. |
+| BYTE_ b_TimingUnit data[2] : Base timing unity (0 to 4) |
+| 0 : ns |
+| 1 : µs |
+| 2 : ms |
+| 3 : s |
+| 4 : mn |
+| ULONG_ ul_TimingInterval : data[3] Base timing value. |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing |
+| value.
+| data[0]
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: Chronometer mode selection is wrong |
+| -5: The selected PCI input clock is wrong |
+| -6: Timing unity selection is wrong |
+| -7: Base timing selection is wrong |
+| -8: You can not used the 40MHz clock selection wich |
+| this board |
+| -9: You can not used the 40MHz clock selection wich |
+| this CHRONOS version |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ ULONG ul_TimerValue = 0;
+ ULONG ul_TimingInterval = 0;
+ ULONG ul_RealTimingInterval = 0;
+ double d_RealTimingInterval = 0;
+ DWORD dw_ModeArray[8] =
+ { 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 };
+ BYTE b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit;
+
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_ChronoMode = (BYTE) data[0];
+ b_PCIInputClock = (BYTE) data[1];
+ b_TimingUnit = (BYTE) data[2];
+ ul_TimingInterval = (ULONG) data[3];
+ i_ReturnValue = insn->n;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if chronometer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+ /*****************************/
+ /* Test the chronometer mode */
+ /*****************************/
+
+ if (b_ChronoMode <= 7) {
+ /**************************/
+ /* Test the PCI bus clock */
+ /**************************/
+
+ if ((b_PCIInputClock == APCI1710_30MHZ) ||
+ (b_PCIInputClock == APCI1710_33MHZ) ||
+ (b_PCIInputClock == APCI1710_40MHZ)) {
+ /*************************/
+ /* Test the timing unity */
+ /*************************/
+
+ if (b_TimingUnit <= 4) {
+ /**********************************/
+ /* Test the base timing selection */
+ /**********************************/
+
+ if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 66) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165576UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 60) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150240UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 50) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374182UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 1UL))) {
+ /**************************/
+ /* Test the board version */
+ /**************************/
+
+ if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) {
+ /************************/
+ /* Test the TOR version */
+ /************************/
+
+ if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || (b_PCIInputClock != APCI1710_40MHZ)) {
+ fpu_begin
+ ();
+
+ /****************************************/
+ /* Calculate the timer 0 division fator */
+ /****************************************/
+
+ switch (b_TimingUnit) {
+ /******/
+ /* ns */
+ /******/
+
+ case 0:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (0.001 * b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (0.001 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (0.001 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (0.001
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (0.001 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 0.99392);
+ }
+
+ break;
+
+ /******/
+ /* æs */
+ /******/
+
+ case 1:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (1.0 * b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (1.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (1.0 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (
+ (double)
+ 1.0
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (1.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 0.99392);
+ }
+
+ break;
+
+ /******/
+ /* ms */
+ /******/
+
+ case 2:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ ul_TimingInterval
+ *
+ (1000
+ *
+ b_PCIInputClock);
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (1000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (1000.0 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (1000.0
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (1000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 0.99392);
+ }
+
+ break;
+
+ /*****/
+ /* s */
+ /*****/
+
+ case 3:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (1000000.0
+ *
+ b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (1000000.0
+ *
+ (double)
+ b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (1000000.0
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 0.99392);
+ }
+
+ break;
+
+ /******/
+ /* mn */
+ /******/
+
+ case 4:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (ul_TimingInterval
+ *
+ 60)
+ *
+ (1000000.0
+ *
+ b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)(ul_TimingInterval * 60.0) * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (1000000.0
+ *
+ (double)
+ b_PCIInputClock))
+ /
+ 60;
+ d_RealTimingInterval
+ =
+ (
+ (double)
+ ul_TimerValue
+ /
+ (0.001 * (double)b_PCIInputClock)) / 60.0;
+
+ if ((double)(((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 0.99392);
+ }
+
+ break;
+ }
+
+ fpu_end();
+
+ /****************************/
+ /* Save the PCI input clock */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_PCIInputClock
+ =
+ b_PCIInputClock;
+
+ /*************************/
+ /* Save the timing unity */
+ /*************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_TimingUnit
+ =
+ b_TimingUnit;
+
+ /************************/
+ /* Save the base timing */
+ /************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ d_TimingInterval
+ =
+ d_RealTimingInterval;
+
+ /****************************/
+ /* Set the chronometer mode */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg
+ =
+ dw_ModeArray
+ [b_ChronoMode];
+
+ /***********************/
+ /* Test if 40 MHz used */
+ /***********************/
+
+ if (b_PCIInputClock == APCI1710_40MHZ) {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg
+ |
+ 0x80;
+ }
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr));
+
+ /***********************/
+ /* Write timer 0 value */
+ /***********************/
+
+ outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
+
+ /*********************/
+ /* Chronometer init. */
+ /*********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_ChronoInit
+ =
+ 1;
+ } else {
+ /***********************************************/
+ /* TOR version error for 40MHz clock selection */
+ /***********************************************/
+
+ DPRINTK("TOR version error for 40MHz clock selection\n");
+ i_ReturnValue
+ =
+ -9;
+ }
+ } else {
+ /**************************************************************/
+ /* You can not used the 40MHz clock selection wich this board */
+ /**************************************************************/
+
+ DPRINTK("You can not used the 40MHz clock selection wich this board\n");
+ i_ReturnValue =
+ -8;
+ }
+ } else {
+ /**********************************/
+ /* Base timing selection is wrong */
+ /**********************************/
+
+ DPRINTK("Base timing selection is wrong\n");
+ i_ReturnValue = -7;
+ }
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ else {
+ /***********************************/
+ /* Timing unity selection is wrong */
+ /***********************************/
+
+ DPRINTK("Timing unity selection is wrong\n");
+ i_ReturnValue = -6;
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+ else {
+ /*****************************************/
+ /* The selected PCI input clock is wrong */
+ /*****************************************/
+
+ DPRINTK("The selected PCI input clock is wrong\n");
+ i_ReturnValue = -5;
+ } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+ } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7)
+ else {
+ /***************************************/
+ /* Chronometer mode selection is wrong */
+ /***************************************/
+
+ DPRINTK("Chronometer mode selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7)
+ } else {
+ /******************************************/
+ /* The module is not a Chronometer module */
+ /******************************************/
+
+ DPRINTK("The module is not a Chronometer module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+ data[0] = ul_RealTimingInterval;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnableChrono |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_CycleMode, |
+| BYTE_ b_InterruptEnable)
+INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Enable the chronometer from selected module |
+| (b_ModulNbr). You must calling the |
+| "i_APCI1710_InitChrono" function be for you call this |
+| function. |
+| If you enable the chronometer interrupt, the |
+| chronometer generate a interrupt after the stop signal.|
+| See function "i_APCI1710_SetBoardIntRoutineX" and the |
+| Interrupt mask description chapter from this manual. |
+| The b_CycleMode parameter determine if you will |
+| measured a single or more cycle.
+
+| Disable the chronometer from selected module |
+| (b_ModulNbr). If you disable the chronometer after a |
+| start signal occur and you restart the chronometer |
+| witch the " i_APCI1710_EnableChrono" function, if no |
+| stop signal occur this start signal is ignored.
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr CR_AREF(chanspec) : Selected module number (0 to 3) |
+ data[0] ENABle/Disable chrono
+| BYTE_ b_CycleMode : Selected the chronometer |
+| data[1] acquisition mode |
+| BYTE_ b_InterruptEnable : Enable or disable the |
+| data[2] chronometer interrupt. |
+| APCI1710_ENABLE: |
+| Enable the chronometer |
+| interrupt |
+| APCI1710_DISABLE: |
+| Disable the chronometer |
+| interrupt |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
+| -5: Chronometer acquisition mode cycle is wrong |
+| -6: Interrupt parameter is wrong |
+| -7: Interrupt function not initialised. |
+| See function "i_APCI1710_SetBoardIntRoutineX"
+ -8: data[0] wrong input |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ BYTE b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_Action = (BYTE) data[0];
+ b_CycleMode = (BYTE) data[1];
+ b_InterruptEnable = (BYTE) data[2];
+ i_ReturnValue = insn->n;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if chronometer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+ /***********************************/
+ /* Test if chronometer initialised */
+ /***********************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.b_ChronoInit == 1) {
+
+ switch (b_Action) {
+
+ case APCI1710_ENABLE:
+
+ /*********************************/
+ /* Test the cycle mode parameter */
+ /*********************************/
+
+ if ((b_CycleMode == APCI1710_SINGLE)
+ || (b_CycleMode ==
+ APCI1710_CONTINUOUS)) {
+ /***************************/
+ /* Test the interrupt flag */
+ /***************************/
+
+ if ((b_InterruptEnable ==
+ APCI1710_ENABLE)
+ || (b_InterruptEnable ==
+ APCI1710_DISABLE))
+ {
+
+ /***************************/
+ /* Save the interrupt flag */
+ /***************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_InterruptMask
+ =
+ b_InterruptEnable;
+
+ /***********************/
+ /* Save the cycle mode */
+ /***********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_CycleMode =
+ b_CycleMode;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg =
+ (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg &
+ 0x8F) | ((1 &
+ b_InterruptEnable)
+ << 5) | ((1 &
+ b_CycleMode)
+ << 6) | 0x10;
+
+ /*****************************/
+ /* Test if interrupt enabled */
+ /*****************************/
+
+ if (b_InterruptEnable ==
+ APCI1710_ENABLE)
+ {
+ /****************************/
+ /* Clear the interrupt flag */
+ /****************************/
+
+ outl(devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg,
+ devpriv->
+ s_BoardInfos.
+ ui_Address
+ + 32 +
+ (64 * b_ModulNbr));
+ devpriv->tsk_Current = current; // Save the current process task structure
+ }
+
+ /***********************************/
+ /* Enable or disable the interrupt */
+ /* Enable the chronometer */
+ /***********************************/
+
+ outl(devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg,
+ devpriv->
+ s_BoardInfos.
+ ui_Address +
+ 16 +
+ (64 * b_ModulNbr));
+
+ /*************************/
+ /* Clear status register */
+ /*************************/
+
+ outl(0, devpriv->
+ s_BoardInfos.
+ ui_Address +
+ 36 +
+ (64 * b_ModulNbr));
+
+ } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+ else {
+ /********************************/
+ /* Interrupt parameter is wrong */
+ /********************************/
+
+ DPRINTK("Interrupt parameter is wrong\n");
+ i_ReturnValue = -6;
+ } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+ } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+ else {
+ /***********************************************/
+ /* Chronometer acquisition mode cycle is wrong */
+ /***********************************************/
+
+ DPRINTK("Chronometer acquisition mode cycle is wrong\n");
+ i_ReturnValue = -5;
+ } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+ break;
+
+ case APCI1710_DISABLE:
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_InterruptMask = 0;
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg =
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.
+ dw_ConfigReg & 0x2F;
+
+ /***************************/
+ /* Disable the interrupt */
+ /* Disable the chronometer */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.dw_ConfigReg,
+ devpriv->s_BoardInfos.
+ ui_Address + 16 +
+ (64 * b_ModulNbr));
+
+ /***************************/
+ /* Test if continuous mode */
+ /***************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_CycleMode ==
+ APCI1710_CONTINUOUS) {
+ /*************************/
+ /* Clear status register */
+ /*************************/
+
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 36 +
+ (64 * b_ModulNbr));
+ }
+ break;
+
+ default:
+ DPRINTK("Inputs wrong! Enable or Disable chrono\n");
+ i_ReturnValue = -8;
+ } // switch ENABLE/DISABLE
+ } else {
+ /*******************************/
+ /* Chronometer not initialised */
+ /*******************************/
+
+ DPRINTK("Chronometer not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a Chronometer module */
+ /******************************************/
+
+ DPRINTK("The module is not a Chronometer module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name :INT i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s,
+struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read functions for Timer |
++----------------------------------------------------------------------------+
+| Input Parameters :
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadChrono(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_ReadType;
+ INT i_ReturnValue = insn->n;
+
+ b_ReadType = CR_CHAN(insn->chanspec);
+
+ switch (b_ReadType) {
+ case APCI1710_CHRONO_PROGRESS_STATUS:
+ i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_CHRONO_READVALUE:
+ i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (UINT) insn->unused[0],
+ (PBYTE) & data[0], (PULONG) & data[1]);
+ break;
+
+ case APCI1710_CHRONO_CONVERTVALUE:
+ i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (ULONG) insn->unused[0],
+ (PULONG) & data[0],
+ (PBYTE) & data[1],
+ (PBYTE) & data[2],
+ (PUINT) & data[3],
+ (PUINT) & data[4], (PUINT) & data[5]);
+ break;
+
+ case APCI1710_CHRONO_READINTERRUPT:
+ printk("In Chrono Read Interrupt\n");
+
+ data[0] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].b_OldModuleMask;
+ data[1] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+ data[2] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+ /**************************/
+ /* Increment the read FIFO */
+ /***************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Read = (devpriv->
+ s_InterruptParameters.
+ ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+ break;
+
+ default:
+ printk("ReadType Parameter wrong\n");
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetChronoProgressStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_ChronoStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the chronometer status (pb_ChronoStatus) from |
+| selected chronometer module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer |
+| status. |
+| 0 : Measurement not started.|
+| No start signal occur. |
+| 1 : Measurement started. |
+| A start signal occur. |
+| 2 : Measurement stopped. |
+| A stop signal occur. |
+| The measurement is |
+| terminate. |
+| 3: A overflow occur. You |
+| must change the base |
+| timing witch the |
+| function |
+| "i_APCI1710_InitChrono" |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetChronoProgressStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_ChronoStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if chronometer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+ /***********************************/
+ /* Test if chronometer initialised */
+ /***********************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.b_ChronoInit == 1) {
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 8 + (64 * b_ModulNbr));
+
+ /********************/
+ /* Test if overflow */
+ /********************/
+
+ if ((dw_Status & 8) == 8) {
+ /******************/
+ /* Overflow occur */
+ /******************/
+
+ *pb_ChronoStatus = 3;
+ } // if ((dw_Status & 8) == 8)
+ else {
+ /*******************************/
+ /* Test if measurement stopped */
+ /*******************************/
+
+ if ((dw_Status & 2) == 2) {
+ /***********************/
+ /* A stop signal occur */
+ /***********************/
+
+ *pb_ChronoStatus = 2;
+ } // if ((dw_Status & 2) == 2)
+ else {
+ /*******************************/
+ /* Test if measurement started */
+ /*******************************/
+
+ if ((dw_Status & 1) == 1) {
+ /************************/
+ /* A start signal occur */
+ /************************/
+
+ *pb_ChronoStatus = 1;
+ } // if ((dw_Status & 1) == 1)
+ else {
+ /***************************/
+ /* Measurement not started */
+ /***************************/
+
+ *pb_ChronoStatus = 0;
+ } // if ((dw_Status & 1) == 1)
+ } // if ((dw_Status & 2) == 2)
+ } // if ((dw_Status & 8) == 8)
+ } else {
+ /*******************************/
+ /* Chronometer not initialised */
+ /*******************************/
+ DPRINTK("Chronometer not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a Chronometer module */
+ /******************************************/
+ DPRINTK("The module is not a Chronometer module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadChronoValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| UINT_ ui_TimeOut, |
+| PBYTE_ pb_ChronoStatus, |
+| PULONG_ pul_ChronoValue) |
++----------------------------------------------------------------------------+
+| Task : Return the chronometer status (pb_ChronoStatus) and the|
+| timing value (pul_ChronoValue) after a stop signal |
+| occur from selected chronometer module (b_ModulNbr). |
+| This function are only avaible if you have disabled |
+| the interrupt functionality. See function |
+| "i_APCI1710_EnableChrono" and the Interrupt mask |
+| description chapter. |
+| You can test the chronometer status witch the |
+| "i_APCI1710_GetChronoProgressStatus" function. |
+| |
+| The returned value from pul_ChronoValue parameter is |
+| not real measured timing. |
+| You must used the "i_APCI1710_ConvertChronoValue" |
+| function or make this operation for calculate the |
+| timing: |
+| |
+| Timing = pul_ChronoValue * pul_RealTimingInterval. |
+| |
+| pul_RealTimingInterval is the returned parameter from |
+| "i_APCI1710_InitChrono" function and the time unity is |
+| the b_TimingUnit from "i_APCI1710_InitChrono" function|
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer |
+| status. |
+| 0 : Measurement not started.|
+| No start signal occur. |
+| 1 : Measurement started. |
+| A start signal occur. |
+| 2 : Measurement stopped. |
+| A stop signal occur. |
+| The measurement is |
+| terminate. |
+| 3: A overflow occur. You |
+| must change the base |
+| timing witch the |
+| function |
+| "i_APCI1710_InitChrono" |
+| PULONG pul_ChronoValue : Chronometer timing value. |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
+| -5: Timeout parameter is wrong (0 to 65535) |
+| -6: Interrupt routine installed. You can not read |
+| directly the chronometer measured timing. |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadChronoValue(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ UINT ui_TimeOut, PBYTE pb_ChronoStatus, PULONG pul_ChronoValue)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+ DWORD dw_TimeOut = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if chronometer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+ /***********************************/
+ /* Test if chronometer initialised */
+ /***********************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.b_ChronoInit == 1) {
+ /*****************************/
+ /* Test the timout parameter */
+ /*****************************/
+
+ if ((ui_TimeOut >= 0)
+ && (ui_TimeOut <= 65535UL)) {
+
+ for (;;) {
+ /*******************/
+ /* Read the status */
+ /*******************/
+
+ dw_Status =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 8 +
+ (64 * b_ModulNbr));
+
+ /********************/
+ /* Test if overflow */
+ /********************/
+
+ if ((dw_Status & 8) == 8) {
+ /******************/
+ /* Overflow occur */
+ /******************/
+
+ *pb_ChronoStatus = 3;
+
+ /***************************/
+ /* Test if continuous mode */
+ /***************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_CycleMode ==
+ APCI1710_CONTINUOUS)
+ {
+ /*************************/
+ /* Clear status register */
+ /*************************/
+
+ outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
+ }
+
+ break;
+ } // if ((dw_Status & 8) == 8)
+ else {
+ /*******************************/
+ /* Test if measurement stopped */
+ /*******************************/
+
+ if ((dw_Status & 2) ==
+ 2) {
+ /***********************/
+ /* A stop signal occur */
+ /***********************/
+
+ *pb_ChronoStatus
+ = 2;
+
+ /***************************/
+ /* Test if continnous mode */
+ /***************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_ChronoModuleInfo.
+ b_CycleMode
+ ==
+ APCI1710_CONTINUOUS)
+ {
+ /*************************/
+ /* Clear status register */
+ /*************************/
+
+ outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr));
+ }
+ break;
+ } // if ((dw_Status & 2) == 2)
+ else {
+ /*******************************/
+ /* Test if measurement started */
+ /*******************************/
+
+ if ((dw_Status & 1) == 1) {
+ /************************/
+ /* A start signal occur */
+ /************************/
+
+ *pb_ChronoStatus
+ =
+ 1;
+ } // if ((dw_Status & 1) == 1)
+ else {
+ /***************************/
+ /* Measurement not started */
+ /***************************/
+
+ *pb_ChronoStatus
+ =
+ 0;
+ } // if ((dw_Status & 1) == 1)
+ } // if ((dw_Status & 2) == 2)
+ } // if ((dw_Status & 8) == 8)
+
+ if (dw_TimeOut == ui_TimeOut) {
+ /*****************/
+ /* Timeout occur */
+ /*****************/
+
+ break;
+ } else {
+ /*************************/
+ /* Increment the timeout */
+ /*************************/
+
+ dw_TimeOut =
+ dw_TimeOut + 1;
+ mdelay(1000);
+
+ }
+ } // for (;;)
+
+ /*****************************/
+ /* Test if stop signal occur */
+ /*****************************/
+
+ if (*pb_ChronoStatus == 2) {
+ /**********************************/
+ /* Read the measured timing value */
+ /**********************************/
+
+ *pul_ChronoValue =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 4 +
+ (64 * b_ModulNbr));
+
+ if (*pul_ChronoValue != 0) {
+ *pul_ChronoValue =
+ *pul_ChronoValue
+ - 1;
+ }
+ } else {
+ /*************************/
+ /* Test if timeout occur */
+ /*************************/
+
+ if ((*pb_ChronoStatus != 3)
+ && (dw_TimeOut ==
+ ui_TimeOut)
+ && (ui_TimeOut != 0)) {
+ /*****************/
+ /* Timeout occur */
+ /*****************/
+
+ *pb_ChronoStatus = 4;
+ }
+ }
+
+ } else {
+ /******************************/
+ /* Timeout parameter is wrong */
+ /******************************/
+ DPRINTK("Timeout parameter is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /*******************************/
+ /* Chronometer not initialised */
+ /*******************************/
+ DPRINTK("Chronometer not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a Chronometer module */
+ /******************************************/
+ DPRINTK("The module is not a Chronometer module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ConvertChronoValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| ULONG_ ul_ChronoValue, |
+| PULONG_ pul_Hour, |
+| PBYTE_ pb_Minute, |
+| PBYTE_ pb_Second, |
+| PUINT_ pui_MilliSecond, |
+| PUINT_ pui_MicroSecond, |
+| PUINT_ pui_NanoSecond) |
++----------------------------------------------------------------------------+
+| Task : Convert the chronometer measured timing |
+| (ul_ChronoValue) in to h, mn, s, ms, µs, ns. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3)|
+| ULONG_ ul_ChronoValue : Measured chronometer timing |
+| value. |
+| See"i_APCI1710_ReadChronoValue"|
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_Hour : Chronometer timing hour |
+| PBYTE_ pb_Minute : Chronometer timing minute |
+| PBYTE_ pb_Second : Chronometer timing second |
+| PUINT_ pui_MilliSecond : Chronometer timing mini |
+| second |
+| PUINT_ pui_MicroSecond : Chronometer timing micro |
+| second |
+| PUINT_ pui_NanoSecond : Chronometer timing nano |
+| second |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ConvertChronoValue(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ ULONG ul_ChronoValue,
+ PULONG pul_Hour,
+ PBYTE pb_Minute,
+ PBYTE pb_Second,
+ PUINT pui_MilliSecond, PUINT pui_MicroSecond, PUINT pui_NanoSecond)
+{
+ INT i_ReturnValue = 0;
+ double d_Hour;
+ double d_Minute;
+ double d_Second;
+ double d_MilliSecond;
+ double d_MicroSecond;
+ double d_NanoSecond;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if chronometer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+ /***********************************/
+ /* Test if chronometer initialised */
+ /***********************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.b_ChronoInit == 1) {
+ fpu_begin();
+
+ d_Hour = (double)ul_ChronoValue *(double)
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.d_TimingInterval;
+
+ switch (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.b_TimingUnit) {
+ case 0:
+ d_Hour = d_Hour / (double)1000.0;
+
+ case 1:
+ d_Hour = d_Hour / (double)1000.0;
+
+ case 2:
+ d_Hour = d_Hour / (double)1000.0;
+
+ case 3:
+ d_Hour = d_Hour / (double)60.0;
+
+ case 4:
+ /**********************/
+ /* Calculate the hour */
+ /**********************/
+
+ d_Hour = d_Hour / (double)60.0;
+ *pul_Hour = (ULONG) d_Hour;
+
+ /************************/
+ /* Calculate the minute */
+ /************************/
+
+ d_Minute = d_Hour - *pul_Hour;
+ d_Minute = d_Minute * 60;
+ *pb_Minute = (BYTE) d_Minute;
+
+ /************************/
+ /* Calculate the second */
+ /************************/
+
+ d_Second = d_Minute - *pb_Minute;
+ d_Second = d_Second * 60;
+ *pb_Second = (BYTE) d_Second;
+
+ /*****************************/
+ /* Calculate the mini second */
+ /*****************************/
+
+ d_MilliSecond = d_Second - *pb_Second;
+ d_MilliSecond = d_MilliSecond * 1000;
+ *pui_MilliSecond = (UINT) d_MilliSecond;
+
+ /******************************/
+ /* Calculate the micro second */
+ /******************************/
+
+ d_MicroSecond =
+ d_MilliSecond -
+ *pui_MilliSecond;
+ d_MicroSecond = d_MicroSecond * 1000;
+ *pui_MicroSecond = (UINT) d_MicroSecond;
+
+ /******************************/
+ /* Calculate the micro second */
+ /******************************/
+
+ d_NanoSecond =
+ d_MicroSecond -
+ *pui_MicroSecond;
+ d_NanoSecond = d_NanoSecond * 1000;
+ *pui_NanoSecond = (UINT) d_NanoSecond;
+ break;
+ }
+
+ fpu_end();
+ } else {
+ /*******************************/
+ /* Chronometer not initialised */
+ /*******************************/
+ DPRINTK("Chronometer not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a Chronometer module */
+ /******************************************/
+ DPRINTK("The module is not a Chronometer module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Sets the output witch has been passed with the |
+| parameter b_Channel. Setting an output means setting an|
+| output high. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3)|
+| BYTE_ b_OutputChannel : Selection from digital output |
+| CR_CHAN() channel (0 to 2) |
+| 0 : Channel H |
+| 1 : Channel A |
+| 2 : Channel B |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: The selected digital output is wrong |
+| -5: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_SetChronoChlOff |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_OutputChannel) |
++----------------------------------------------------------------------------+
+| Task : Resets the output witch has been passed with the |
+| parameter b_Channel. Resetting an output means setting |
+| an output low. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710
+ data[0] : Chl ON, Chl OFF , Chl Read , Port Read
+
+| BYTE_ b_ModulNbr CR_AREF : Selected module number (0 to 3)|
+| BYTE_ b_OutputChannel CR_CHAN : Selection from digital output |
+| channel (0 to 2) |
+| 0 : Channel H |
+| 1 : Channel A |
+| 2 : Channel B |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: The selected digital output is wrong |
+| -5: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadChronoChlValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_InputChannel, |
+| PBYTE_ pb_ChannelStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the status from selected digital input |
+| (b_InputChannel) from selected chronometer |
+| module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3)|
+| BYTE_ b_InputChannel : Selection from digital input |
+| channel (0 to 2) |
+| CR_CHAN() 0 : Channel E |
+| 1 : Channel F |
+| 2 : Channel G |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel status.|
+| data[0] 0 : Channel is not active |
+| 1 : Channel is active |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: The selected digital input is wrong |
+| -5: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadChronoPortValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_PortValue) |
++----------------------------------------------------------------------------+
+| Task : Return the status from digital inputs port from |
+| selected (b_ModulNbr) chronometer module. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3)|
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_PortValue : Digital inputs port status.
+| data[0]
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a Chronometer module |
+| -4: Chronometer not initialised see function |
+| "i_APCI1710_InitChrono" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ BYTE b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
+ DWORD dw_Status;
+ PBYTE pb_ChannelStatus;
+ PBYTE pb_PortValue;
+
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ i_ReturnValue = insn->n;
+ b_IOType = (BYTE) data[0];
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if chronometer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+ /***********************************/
+ /* Test if chronometer initialised */
+ /***********************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_ChronoModuleInfo.b_ChronoInit == 1) {
+ /***********************************/
+ /* Test the digital output channel */
+ /***********************************/
+ switch (b_IOType) {
+
+ case APCI1710_CHRONO_SET_CHANNELOFF:
+
+ b_OutputChannel =
+ (BYTE) CR_CHAN(insn->chanspec);
+ if (b_OutputChannel <= 2) {
+
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 20 +
+ (b_OutputChannel * 4) +
+ (64 * b_ModulNbr));
+ } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+ else {
+ /****************************************/
+ /* The selected digital output is wrong */
+ /****************************************/
+
+ DPRINTK("The selected digital output is wrong\n");
+ i_ReturnValue = -4;
+
+ } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+
+ break;
+
+ case APCI1710_CHRONO_SET_CHANNELON:
+
+ b_OutputChannel =
+ (BYTE) CR_CHAN(insn->chanspec);
+ if (b_OutputChannel <= 2) {
+
+ outl(1, devpriv->s_BoardInfos.
+ ui_Address + 20 +
+ (b_OutputChannel * 4) +
+ (64 * b_ModulNbr));
+ } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+ else {
+ /****************************************/
+ /* The selected digital output is wrong */
+ /****************************************/
+
+ DPRINTK("The selected digital output is wrong\n");
+ i_ReturnValue = -4;
+
+ } // if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2))
+
+ break;
+
+ case APCI1710_CHRONO_READ_CHANNEL:
+ /**********************************/
+ /* Test the digital input channel */
+ /**********************************/
+ pb_ChannelStatus = (PBYTE) & data[0];
+ b_InputChannel =
+ (BYTE) CR_CHAN(insn->chanspec);
+
+ if (b_InputChannel <= 2) {
+
+ dw_Status =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 12 +
+ (64 * b_ModulNbr));
+
+ *pb_ChannelStatus =
+ (BYTE) (((dw_Status >>
+ b_InputChannel)
+ & 1) ^ 1);
+ } // if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
+ else {
+ /***************************************/
+ /* The selected digital input is wrong */
+ /***************************************/
+
+ DPRINTK("The selected digital input is wrong\n");
+ i_ReturnValue = -4;
+ } // if ((b_InputChannel >= 0) && (b_InputChannel <= 2))
+
+ break;
+
+ case APCI1710_CHRONO_READ_PORT:
+
+ pb_PortValue = (PBYTE) & data[0];
+
+ dw_Status =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 12 +
+ (64 * b_ModulNbr));
+
+ *pb_PortValue =
+ (BYTE) ((dw_Status & 0x7) ^ 7);
+ break;
+ }
+ } else {
+ /*******************************/
+ /* Chronometer not initialised */
+ /*******************************/
+
+ DPRINTK("Chronometer not initialised\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a Chronometer module */
+ /******************************************/
+
+ DPRINTK("The module is not a Chronometer module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
new file mode 100644
index 000000000000..26b50cefee5a
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_30MHZ 30
+#define APCI1710_33MHZ 33
+#define APCI1710_40MHZ 40
+
+#define APCI1710_SINGLE 0
+#define APCI1710_CONTINUOUS 1
+
+#define APCI1710_CHRONO_PROGRESS_STATUS 0
+#define APCI1710_CHRONO_READVALUE 1
+#define APCI1710_CHRONO_CONVERTVALUE 2
+#define APCI1710_CHRONO_READINTERRUPT 3
+
+#define APCI1710_CHRONO_SET_CHANNELON 0
+#define APCI1710_CHRONO_SET_CHANNELOFF 1
+#define APCI1710_CHRONO_READ_CHANNEL 2
+#define APCI1710_CHRONO_READ_PORT 3
+
+/*
+ * CHRONOMETER INISIALISATION FUNCTION
+ */
+INT i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+/*
+ * CHRONOMETER READ FUNCTION
+ */
+INT i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_ChronoStatus);
+
+INT i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ UINT ui_TimeOut, PBYTE pb_ChronoStatus,
+ PULONG pul_ChronoValue);
+
+INT i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ ULONG ul_ChronoValue,
+ PULONG pul_Hour,
+ PBYTE pb_Minute,
+ PBYTE pb_Second,
+ PUINT pui_MilliSecond, PUINT pui_MicroSecond,
+ PUINT pui_NanoSecond);
+
+/*
+ * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
+ */
+INT i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
new file mode 100644
index 000000000000..8be27aedaaf5
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
@@ -0,0 +1,1020 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : DIG_IO.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 digital I/O module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | 16/06/98 | S. Weber | Digital input / output implementation |
+ |----------|-----------|------------------------------------------------|
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+ | | | |
+ | | | |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "APCI1710_Dig_io.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, |
+| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
++----------------------------------------------------------------------------+
+| Task : Configure the digital I/O operating mode from selected |
+| module (b_ModulNbr). You must calling this function be|
+| for you call any other function witch access of digital|
+| I/O. |
++----------------------------------------------------------------------------+
+| Input Parameters : |
+| BYTE_ b_ModulNbr data[0]: Module number to |
+| configure (0 to 3) |
+| BYTE_ b_ChannelAMode data[1] : Channel A mode selection |
+| 0 : Channel used for digital |
+| input |
+| 1 : Channel used for digital |
+| output |
+| BYTE_ b_ChannelBMode data[2] : Channel B mode selection |
+| 0 : Channel used for digital |
+| input |
+| 1 : Channel used for digital |
+| output |
+ data[0] memory on/off
+Activates and deactivates the digital output memory.
+ After having |
+| called up this function with memory on,the output you have previously|
+| activated with the function are not reset
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a digital I/O module |
+| -4: Bi-directional channel A configuration error |
+| -5: Bi-directional channel B configuration error |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
+ BYTE b_MemoryOnOff, b_ConfigType;
+ INT i_ReturnValue = 0;
+ DWORD dw_WriteConfig = 0;
+
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_ConfigType = (BYTE) data[0]; // Memory or Init
+ b_ChannelAMode = (BYTE) data[1];
+ b_ChannelBMode = (BYTE) data[2];
+ b_MemoryOnOff = (BYTE) data[1]; // if memory operation
+ i_ReturnValue = insn->n;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr >= 4) {
+ DPRINTK("Module Number invalid\n");
+ i_ReturnValue = -2;
+ return i_ReturnValue;
+ }
+ switch (b_ConfigType) {
+ case APCI1710_DIGIO_MEMORYONOFF:
+
+ if (b_MemoryOnOff) // If Memory ON
+ {
+ /****************************/
+ /* Set the output memory on */
+ /****************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.b_OutputMemoryEnabled = 1;
+
+ /***************************/
+ /* Clear the output memory */
+ /***************************/
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.dw_OutputMemory = 0;
+ } else // If memory off
+ {
+ /*****************************/
+ /* Set the output memory off */
+ /*****************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.b_OutputMemoryEnabled = 0;
+ }
+ break;
+
+ case APCI1710_DIGIO_INIT:
+
+ /*******************************/
+ /* Test if digital I/O counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+
+ /***************************************************/
+ /* Test the bi-directional channel A configuration */
+ /***************************************************/
+
+ if ((b_ChannelAMode == 0) || (b_ChannelAMode == 1)) {
+ /***************************************************/
+ /* Test the bi-directional channel B configuration */
+ /***************************************************/
+
+ if ((b_ChannelBMode == 0)
+ || (b_ChannelBMode == 1)) {
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.b_DigitalInit =
+ 1;
+
+ /********************************/
+ /* Save channel A configuration */
+ /********************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelAMode = b_ChannelAMode;
+
+ /********************************/
+ /* Save channel B configuration */
+ /********************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelBMode = b_ChannelBMode;
+
+ /*****************************************/
+ /* Set the channel A and B configuration */
+ /*****************************************/
+
+ dw_WriteConfig =
+ (DWORD) (b_ChannelAMode |
+ (b_ChannelBMode * 2));
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(dw_WriteConfig,
+ devpriv->s_BoardInfos.
+ ui_Address + 4 +
+ (64 * b_ModulNbr));
+
+ } else {
+ /************************************************/
+ /* Bi-directional channel B configuration error */
+ /************************************************/
+ DPRINTK("Bi-directional channel B configuration error\n");
+ i_ReturnValue = -5;
+ }
+
+ } else {
+ /************************************************/
+ /* Bi-directional channel A configuration error */
+ /************************************************/
+ DPRINTK("Bi-directional channel A configuration error\n");
+ i_ReturnValue = -4;
+
+ }
+
+ } else {
+ /******************************************/
+ /* The module is not a digital I/O module */
+ /******************************************/
+ DPRINTK("The module is not a digital I/O module\n");
+ i_ReturnValue = -3;
+ }
+ } // end of Switch
+ printk("Return Value %d\n", i_ReturnValue);
+ return i_ReturnValue;
+}
+
+/*
++----------------------------------------------------------------------------+
+| INPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+
+|INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,comedi_subdevice
+*s, struct comedi_insn *insn,unsigned int *data)
+
++----------------------------------------------------------------------------+
+| Task : Read the status from selected digital I/O digital input|
+| (b_InputChannel) |
++----------------------------------------------------------------------------|
+
+
+|
+| BYTE_ b_ModulNbr CR_AREF(chanspec) : Selected module number |
+| (0 to 3) |
+| BYTE_ b_InputChannel CR_CHAN(chanspec) : Selection from digital |
+| input ( 0 to 6) |
+| 0 : Channel C |
+| 1 : Channel D |
+| 2 : Channel E |
+| 3 : Channel F |
+| 4 : Channel G |
+| 5 : Channel A |
+| 6 : Channel B
+
+
+ |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Digital input channel |
+| status |
+| 0 : Channle is not active|
+| 1 : Channle is active |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a digital I/O module |
+| -4: The selected digital I/O digital input is wrong |
+| -5: Digital I/O not initialised |
+| -6: The digital channel A is used for output |
+| -7: The digital channel B is used for output |
++----------------------------------------------------------------------------+
+*/
+
+//_INT_ i_APCI1710_ReadDigitalIOChlValue (BYTE_ b_BoardHandle,
+// BYTE_ b_ModulNbr,
+// BYTE_ b_InputChannel,
+//
+// PBYTE_ pb_ChannelStatus)
+INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg;
+ BYTE b_ModulNbr, b_InputChannel;
+ PBYTE pb_ChannelStatus;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
+ data[0] = 0;
+ pb_ChannelStatus = (PBYTE) & data[0];
+ i_ReturnValue = insn->n;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if digital I/O counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+ /******************************************/
+ /* Test the digital imnput channel number */
+ /******************************************/
+
+ if (b_InputChannel <= 6) {
+ /**********************************************/
+ /* Test if the digital I/O module initialised */
+ /**********************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.b_DigitalInit == 1) {
+ /**********************************/
+ /* Test if channel A or channel B */
+ /**********************************/
+
+ if (b_InputChannel > 4) {
+ /*********************/
+ /* Test if channel A */
+ /*********************/
+
+ if (b_InputChannel == 5) {
+ /***************************/
+ /* Test the channel A mode */
+ /***************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelAMode
+ != 0) {
+ /********************************************/
+ /* The digital channel A is used for output */
+ /********************************************/
+
+ i_ReturnValue =
+ -6;
+ }
+ } // if (b_InputChannel == 5)
+ else {
+ /***************************/
+ /* Test the channel B mode */
+ /***************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelBMode
+ != 0) {
+ /********************************************/
+ /* The digital channel B is used for output */
+ /********************************************/
+
+ i_ReturnValue =
+ -7;
+ }
+ } // if (b_InputChannel == 5)
+ } // if (b_InputChannel > 4)
+
+ /***********************/
+ /* Test if error occur */
+ /***********************/
+
+ if (i_ReturnValue >= 0) {
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+
+ //INPDW (ps_APCI1710Variable->
+ // s_Board [b_BoardHandle].
+ // s_BoardInfos.
+ // ui_Address + (64 * b_ModulNbr),
+ // &dw_StatusReg);
+
+ dw_StatusReg =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address +
+ (64 * b_ModulNbr));
+
+ *pb_ChannelStatus =
+ (BYTE) ((dw_StatusReg ^
+ 0x1C) >>
+ b_InputChannel) & 1;
+
+ } // if (i_ReturnValue == 0)
+ } else {
+ /*******************************/
+ /* Digital I/O not initialised */
+ /*******************************/
+ DPRINTK("Digital I/O not initialised\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /********************************/
+ /* Selected digital input error */
+ /********************************/
+ DPRINTK("Selected digital input error\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a digital I/O module */
+ /******************************************/
+ DPRINTK("The module is not a digital I/O module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| OUTPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device
+|*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)
+
++----------------------------------------------------------------------------+
+| Task : Sets or resets the output witch has been passed with the |
+| parameter b_Channel. Setting an output means setting |
+| an ouput high. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr (aref ) : Selected module number (0 to 3)|
+| BYTE_ b_OutputChannel (CR_CHAN) : Selection from digital output |
+| channel (0 to 2) |
+| 0 : Channel H |
+| 1 : Channel A |
+| 2 : Channel B |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a digital I/O module |
+| -4: The selected digital output is wrong |
+| -5: digital I/O not initialised see function |
+| " i_APCI1710_InitDigitalIO" |
+| -6: The digital channel A is used for input |
+| -7: The digital channel B is used for input
+ -8: Digital Output Memory OFF. |
+| Use previously the function |
+| "i_APCI1710_SetDigitalIOMemoryOn". |
++----------------------------------------------------------------------------+
+*/
+
+//_INT_ i_APCI1710_SetDigitalIOChlOn (BYTE_ b_BoardHandle,
+// BYTE_ b_ModulNbr,
+// BYTE_ b_OutputChannel)
+INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_WriteValue = 0;
+ BYTE b_ModulNbr, b_OutputChannel;
+ i_ReturnValue = insn->n;
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_OutputChannel = CR_CHAN(insn->chanspec);
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if digital I/O counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+ /**********************************************/
+ /* Test if the digital I/O module initialised */
+ /**********************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.b_DigitalInit == 1) {
+ /******************************************/
+ /* Test the digital output channel number */
+ /******************************************/
+
+ switch (b_OutputChannel) {
+ /*************/
+ /* Channel H */
+ /*************/
+
+ case 0:
+ break;
+
+ /*************/
+ /* Channel A */
+ /*************/
+
+ case 1:
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelAMode != 1) {
+ /*******************************************/
+ /* The digital channel A is used for input */
+ /*******************************************/
+
+ i_ReturnValue = -6;
+ }
+ break;
+
+ /*************/
+ /* Channel B */
+ /*************/
+
+ case 2:
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelBMode != 1) {
+ /*******************************************/
+ /* The digital channel B is used for input */
+ /*******************************************/
+
+ i_ReturnValue = -7;
+ }
+ break;
+
+ default:
+ /****************************************/
+ /* The selected digital output is wrong */
+ /****************************************/
+
+ i_ReturnValue = -4;
+ break;
+ }
+
+ /***********************/
+ /* Test if error occur */
+ /***********************/
+
+ if (i_ReturnValue >= 0) {
+
+ /*********************************/
+ /* Test if set channel ON */
+ /*********************************/
+ if (data[0]) {
+ /*********************************/
+ /* Test if output memory enabled */
+ /*********************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_OutputMemoryEnabled ==
+ 1) {
+ dw_WriteValue =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ | (1 <<
+ b_OutputChannel);
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ = dw_WriteValue;
+ } else {
+ dw_WriteValue =
+ 1 <<
+ b_OutputChannel;
+ }
+ } // set channel off
+ else {
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_OutputMemoryEnabled ==
+ 1) {
+ dw_WriteValue =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ & (0xFFFFFFFFUL
+ -
+ (1 << b_OutputChannel));
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ = dw_WriteValue;
+ } else {
+ /*****************************/
+ /* Digital Output Memory OFF */
+ /*****************************/
+ // +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn"
+ i_ReturnValue = -8;
+ }
+
+ }
+ /*******************/
+ /* Write the value */
+ /*******************/
+
+ //OUTPDW (ps_APCI1710Variable->
+ // s_Board [b_BoardHandle].
+ // s_BoardInfos.
+ // ui_Address + (64 * b_ModulNbr),
+ // dw_WriteValue);
+ outl(dw_WriteValue,
+ devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulNbr));
+ }
+ } else {
+ /*******************************/
+ /* Digital I/O not initialised */
+ /*******************************/
+
+ i_ReturnValue = -5;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a digital I/O module */
+ /******************************************/
+
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+
+|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,comedi_subdevice
+ *s, struct comedi_insn *insn,unsigned int *data)
++----------------------------------------------------------------------------+
+| Task : write:
+ Sets or resets one or several outputs from port. |
+| Setting an output means setting an output high. |
+| If you have switched OFF the digital output memory |
+| (OFF), all the other output are set to "0".
+
+| read:
+ Read the status from digital input port |
+| from selected digital I/O module (b_ModulNbr)
++----------------------------------------------------------------------------+
+| Input Parameters :
+ BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr CR_AREF(aref) : Selected module number (0 to 3)|
+| BYTE_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 )
+| data[0] read or write port
+ data[1] if write then indicate ON or OFF
+
+ if read : data[1] will return port status.
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
+
+ INPUT :
+
+ 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a digital I/O module |
+| -4: Digital I/O not initialised
+
+ OUTPUT: 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a digital I/O module |
+| -4: Output value wrong |
+| -5: digital I/O not initialised see function |
+| " i_APCI1710_InitDigitalIO" |
+| -6: The digital channel A is used for input |
+| -7: The digital channel B is used for input
+ -8: Digital Output Memory OFF. |
+| Use previously the function |
+| "i_APCI1710_SetDigitalIOMemoryOn". |
++----------------------------------------------------------------------------+
+*/
+
+//_INT_ i_APCI1710_SetDigitalIOPortOn (BYTE_ b_BoardHandle,
+// BYTE_ b_ModulNbr,
+// BYTE_ b_PortValue)
+INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_WriteValue = 0;
+ DWORD dw_StatusReg;
+ BYTE b_ModulNbr, b_PortValue;
+ BYTE b_PortOperation, b_PortOnOFF;
+
+ PBYTE pb_PortValue;
+
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_PortOperation = (BYTE) data[0]; // Input or output
+ b_PortOnOFF = (BYTE) data[1]; // if output then On or Off
+ b_PortValue = (BYTE) data[2]; // if out put then Value
+ i_ReturnValue = insn->n;
+ pb_PortValue = (PBYTE) & data[0];
+// if input then read value
+
+ switch (b_PortOperation) {
+ case APCI1710_INPUT:
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if digital I/O counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+ /**********************************************/
+ /* Test if the digital I/O module initialised */
+ /**********************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.b_DigitalInit == 1) {
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+
+ //INPDW (ps_APCI1710Variable->
+ // s_Board [b_BoardHandle].
+ // s_BoardInfos.
+ // ui_Address + (64 * b_ModulNbr),
+ // &dw_StatusReg);
+
+ dw_StatusReg =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulNbr));
+ *pb_PortValue =
+ (BYTE) (dw_StatusReg ^ 0x1C);
+
+ } else {
+ /*******************************/
+ /* Digital I/O not initialised */
+ /*******************************/
+
+ i_ReturnValue = -4;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a digital I/O module */
+ /******************************************/
+
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ i_ReturnValue = -2;
+ }
+
+ break;
+
+ case APCI1710_OUTPUT:
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if digital I/O counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_DIGITAL_IO) {
+ /**********************************************/
+ /* Test if the digital I/O module initialised */
+ /**********************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_DigitalIOInfo.b_DigitalInit == 1) {
+ /***********************/
+ /* Test the port value */
+ /***********************/
+
+ if (b_PortValue <= 7) {
+ /***********************************/
+ /* Test the digital output channel */
+ /***********************************/
+
+ /**************************/
+ /* Test if channel A used */
+ /**************************/
+
+ if ((b_PortValue & 2) == 2) {
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelAMode
+ != 1) {
+ /*******************************************/
+ /* The digital channel A is used for input */
+ /*******************************************/
+
+ i_ReturnValue =
+ -6;
+ }
+ } // if ((b_PortValue & 2) == 2)
+
+ /**************************/
+ /* Test if channel B used */
+ /**************************/
+
+ if ((b_PortValue & 4) == 4) {
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_ChannelBMode
+ != 1) {
+ /*******************************************/
+ /* The digital channel B is used for input */
+ /*******************************************/
+
+ i_ReturnValue =
+ -7;
+ }
+ } // if ((b_PortValue & 4) == 4)
+
+ /***********************/
+ /* Test if error occur */
+ /***********************/
+
+ if (i_ReturnValue >= 0) {
+
+ //if(data[1])
+ //{
+ switch (b_PortOnOFF) {
+ /*********************************/
+ /* Test if set Port ON */
+ /*********************************/
+
+ case APCI1710_ON:
+
+ /*********************************/
+ /* Test if output memory enabled */
+ /*********************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_OutputMemoryEnabled
+ == 1) {
+ dw_WriteValue
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ |
+ b_PortValue;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ =
+ dw_WriteValue;
+ } else {
+ dw_WriteValue
+ =
+ b_PortValue;
+ }
+ break;
+
+ // If Set PORT OFF
+ case APCI1710_OFF:
+
+ /*********************************/
+ /* Test if output memory enabled */
+ /*********************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ b_OutputMemoryEnabled
+ == 1) {
+ dw_WriteValue
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ &
+ (0xFFFFFFFFUL
+ -
+ b_PortValue);
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_DigitalIOInfo.
+ dw_OutputMemory
+ =
+ dw_WriteValue;
+ } else {
+ /*****************************/
+ /* Digital Output Memory OFF */
+ /*****************************/
+
+ i_ReturnValue
+ =
+ -8;
+ }
+ } // switch
+
+ /*******************/
+ /* Write the value */
+ /*******************/
+
+ // OUTPDW (ps_APCI1710Variable->
+ // s_Board [b_BoardHandle].
+ // s_BoardInfos.
+ // ui_Address + (64 * b_ModulNbr),
+ // dw_WriteValue);
+ outl(dw_WriteValue,
+ devpriv->
+ s_BoardInfos.
+ ui_Address +
+ (64 * b_ModulNbr));
+ }
+ } else {
+ /**********************/
+ /* Output value wrong */
+ /**********************/
+
+ i_ReturnValue = -4;
+ }
+ } else {
+ /*******************************/
+ /* Digital I/O not initialised */
+ /*******************************/
+
+ i_ReturnValue = -5;
+ }
+ } else {
+ /******************************************/
+ /* The module is not a digital I/O module */
+ /******************************************/
+
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ i_ReturnValue = -2;
+ }
+ break;
+
+ default:
+ i_ReturnValue = -9;
+ DPRINTK("NO INPUT/OUTPUT specified\n");
+ } //switch INPUT / OUTPUT
+ return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
new file mode 100644
index 000000000000..5ef157a55ca1
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_ON 1 /* Digital Output ON or OFF */
+#define APCI1710_OFF 0
+
+#define APCI1710_INPUT 0 /* Digital I/O */
+#define APCI1710_OUTPUT 1
+
+#define APCI1710_DIGIO_MEMORYONOFF 0x10
+#define APCI1710_DIGIO_INIT 0x11
+
+/*
+ * DIGITAL I/O INISIALISATION FUNCTION
+ */
+INT i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*
+ * INPUT OUTPUT FUNCTIONS
+ */
+INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
new file mode 100644
index 000000000000..1062f2fdec30
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
@@ -0,0 +1,5363 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : INC_CPT.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 incremental counter module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ |----------|-----------|------------------------------------------------|
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+ | 29/06/01 | Guinot C. | - 1100/0231 -> 0701/0232 |
+ | | | See i_APCI1710_DisableFrequencyMeasurement |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_INCCPT.h"
+
+/*
++----------------------------------------------------------------------------+
+| INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+struct comedi_insn *insn,unsigned int *data)
+
++----------------------------------------------------------------------------+
+| Task : Configuration function for INC_CPT |
++----------------------------------------------------------------------------+
+| Input Parameters : |
++----------------------------------------------------------------------------+
+| Output Parameters : *data
++----------------------------------------------------------------------------+
+| Return Value : |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_ConfigType;
+ INT i_ReturnValue = 0;
+ ui_ConfigType = CR_CHAN(insn->chanspec);
+
+ printk("\nINC_CPT");
+
+ devpriv->tsk_Current = current; // Save the current process task structure
+ switch (ui_ConfigType) {
+ case APCI1710_INCCPT_INITCOUNTER:
+ i_ReturnValue = i_APCI1710_InitCounter(dev,
+ CR_AREF(insn->chanspec),
+ (BYTE) data[0],
+ (BYTE) data[1],
+ (BYTE) data[2], (BYTE) data[3], (BYTE) data[4]);
+ break;
+
+ case APCI1710_INCCPT_COUNTERAUTOTEST:
+ i_ReturnValue = i_APCI1710_CounterAutoTest(dev,
+ (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_INITINDEX:
+ i_ReturnValue = i_APCI1710_InitIndex(dev,
+ CR_AREF(insn->chanspec),
+ (BYTE) data[0],
+ (BYTE) data[1], (BYTE) data[2], (BYTE) data[3]);
+ break;
+
+ case APCI1710_INCCPT_INITREFERENCE:
+ i_ReturnValue = i_APCI1710_InitReference(dev,
+ CR_AREF(insn->chanspec), (BYTE) data[0]);
+ break;
+
+ case APCI1710_INCCPT_INITEXTERNALSTROBE:
+ i_ReturnValue = i_APCI1710_InitExternalStrobe(dev,
+ CR_AREF(insn->chanspec),
+ (BYTE) data[0], (BYTE) data[1]);
+ break;
+
+ case APCI1710_INCCPT_INITCOMPARELOGIC:
+ i_ReturnValue = i_APCI1710_InitCompareLogic(dev,
+ CR_AREF(insn->chanspec), (UINT) data[0]);
+ break;
+
+ case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:
+ i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
+ CR_AREF(insn->chanspec),
+ (BYTE) data[0],
+ (BYTE) data[1], (ULONG) data[2], (PULONG) & data[0]);
+ break;
+
+ default:
+ printk("Insn Config : Config Parameter Wrong\n");
+
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitCounter |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_CounterRange, |
+| BYTE_ b_FirstCounterModus, |
+| BYTE_ b_FirstCounterOption, |
+| BYTE_ b_SecondCounterModus, |
+| BYTE_ b_SecondCounterOption) |
++----------------------------------------------------------------------------+
+| Task : Configure the counter operating mode from selected |
+| module (b_ModulNbr). You must calling this function be |
+| for you call any other function witch access of |
+| counters. |
+| |
+| Counter range |
+| ------------- |
+| +------------------------------------+-----------------------------------+ |
+| | Parameter Passed value | Description | |
+| |------------------------------------+-----------------------------------| |
+| |b_ModulNbr APCI1710_16BIT_COUNTER | The module is configured for | |
+| | | two 16-bit counter. | |
+| | | - b_FirstCounterModus and | |
+| | | b_FirstCounterOption | |
+| | | configure the first 16 bit | |
+| | | counter. | |
+| | | - b_SecondCounterModus and | |
+| | | b_SecondCounterOption | |
+| | | configure the second 16 bit | |
+| | | counter. | |
+| |------------------------------------+-----------------------------------| |
+| |b_ModulNbr APCI1710_32BIT_COUNTER | The module is configured for one | |
+| | | 32-bit counter. | |
+| | | - b_FirstCounterModus and | |
+| | | b_FirstCounterOption | |
+| | | configure the 32 bit counter. | |
+| | | - b_SecondCounterModus and | |
+| | | b_SecondCounterOption | |
+| | | are not used and have no | |
+| | | importance. | |
+| +------------------------------------+-----------------------------------+ |
+| |
+| Counter operating mode |
+| ---------------------- |
+| |
+| +--------------------+-------------------------+-------------------------+ |
+| | Parameter | Passed value | Description | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus | APCI1710_QUADRUPLE_MODE | In the quadruple mode, | |
+| | or | | the edge analysis | |
+| |b_SecondCounterModus| | circuit generates a | |
+| | | | counting pulse from | |
+| | | | each edge of 2 signals | |
+| | | | which are phase shifted | |
+| | | | in relation to each | |
+| | | | other. | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus | APCI1710_DOUBLE_MODE | Functions in the same | |
+| | or | | way as the quadruple | |
+| |b_SecondCounterModus| | mode, except that only | |
+| | | | two of the four edges | |
+| | | | are analysed per | |
+| | | | period | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus | APCI1710_SIMPLE_MODE | Functions in the same | |
+| | or | | way as the quadruple | |
+| |b_SecondCounterModus| | mode, except that only | |
+| | | | one of the four edges | |
+| | | | is analysed per | |
+| | | | period. | |
+| |--------------------+-------------------------+-------------------------| |
+| |b_FirstCounterModus | APCI1710_DIRECT_MODE | In the direct mode the | |
+| | or | | both edge analysis | |
+| |b_SecondCounterModus| | circuits are inactive. | |
+| | | | The inputs A, B in the | |
+| | | | 32-bit mode or A, B and | |
+| | | | C, D in the 16-bit mode | |
+| | | | represent, each, one | |
+| | | | clock pulse gate circuit| |
+| | | | There by frequency and | |
+| | | | pulse duration | |
+| | | | measurements can be | |
+| | | | performed. | |
+| +--------------------+-------------------------+-------------------------+ |
+| |
+| |
+| IMPORTANT! |
+| If you have configured the module for two 16-bit counter, a mixed |
+| mode with a counter in quadruple/double/single mode |
+| and the other counter in direct mode is not possible! |
+| |
+| |
+| Counter operating option for quadruple/double/simple mode |
+| --------------------------------------------------------- |
+| |
+| +----------------------+-------------------------+------------------------+|
+| | Parameter | Passed value | Description ||
+| |----------------------+-------------------------+------------------------||
+| |b_FirstCounterOption | APCI1710_HYSTERESIS_ON | In both edge analysis ||
+| | or | | circuits is available ||
+| |b_SecondCounterOption | | one hysteresis circuit.||
+| | | | It suppresses each ||
+| | | | time the first counting||
+| | | | pulse after a change ||
+| | | | of rotation. ||
+| |----------------------+-------------------------+------------------------||
+| |b_FirstCounterOption | APCI1710_HYSTERESIS_OFF | The first counting ||
+| | or | | pulse is not suppress ||
+| |b_SecondCounterOption | | after a change of ||
+| | | | rotation. ||
+| +----------------------+-------------------------+------------------------+|
+| |
+| |
+| IMPORTANT! |
+| This option are only avaible if you have selected the direct mode. |
+| |
+| |
+| Counter operating option for direct mode |
+| ---------------------------------------- |
+| |
+| +----------------------+--------------------+----------------------------+ |
+| | Parameter | Passed value | Description | |
+| |----------------------+--------------------+----------------------------| |
+| |b_FirstCounterOption | APCI1710_INCREMENT | The counter increment for | |
+| | or | | each counting pulse | |
+| |b_SecondCounterOption | | | |
+| |----------------------+--------------------+----------------------------| |
+| |b_FirstCounterOption | APCI1710_DECREMENT | The counter decrement for | |
+| | or | | each counting pulse | |
+| |b_SecondCounterOption | | | |
+| +----------------------+--------------------+----------------------------+ |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
+| BYTE_ b_CounterRange : Selection form counter |
+| range. |
+| BYTE_ b_FirstCounterModus : First counter operating |
+| mode. |
+| BYTE_ b_FirstCounterOption : First counter option. |
+| BYTE_ b_SecondCounterModus : Second counter operating |
+| mode. |
+| BYTE_ b_SecondCounterOption : Second counter option. |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module is not a counter module |
+| -3: The selected counter range is wrong. |
+| -4: The selected first counter operating mode is wrong. |
+| -5: The selected first counter operating option is wrong|
+| -6: The selected second counter operating mode is wrong.|
+| -7: The selected second counter operating option is |
+| wrong. |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitCounter(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ BYTE b_CounterRange,
+ BYTE b_FirstCounterModus,
+ BYTE b_FirstCounterOption,
+ BYTE b_SecondCounterModus, BYTE b_SecondCounterOption)
+{
+ INT i_ReturnValue = 0;
+
+ /*******************************/
+ /* Test if incremental counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER) {
+ /**************************/
+ /* Test the counter range */
+ /**************************/
+
+ if (b_CounterRange == APCI1710_16BIT_COUNTER
+ || b_CounterRange == APCI1710_32BIT_COUNTER) {
+ /********************************/
+ /* Test the first counter modus */
+ /********************************/
+
+ if (b_FirstCounterModus == APCI1710_QUADRUPLE_MODE ||
+ b_FirstCounterModus == APCI1710_DOUBLE_MODE ||
+ b_FirstCounterModus == APCI1710_SIMPLE_MODE ||
+ b_FirstCounterModus == APCI1710_DIRECT_MODE) {
+ /*********************************/
+ /* Test the first counter option */
+ /*********************************/
+
+ if ((b_FirstCounterModus == APCI1710_DIRECT_MODE
+ && (b_FirstCounterOption ==
+ APCI1710_INCREMENT
+ || b_FirstCounterOption
+ == APCI1710_DECREMENT))
+ || (b_FirstCounterModus !=
+ APCI1710_DIRECT_MODE
+ && (b_FirstCounterOption ==
+ APCI1710_HYSTERESIS_ON
+ || b_FirstCounterOption
+ ==
+ APCI1710_HYSTERESIS_OFF)))
+ {
+ /**************************/
+ /* Test if 16-bit counter */
+ /**************************/
+
+ if (b_CounterRange ==
+ APCI1710_16BIT_COUNTER) {
+ /*********************************/
+ /* Test the second counter modus */
+ /*********************************/
+
+ if ((b_FirstCounterModus !=
+ APCI1710_DIRECT_MODE
+ &&
+ (b_SecondCounterModus
+ ==
+ APCI1710_QUADRUPLE_MODE
+ ||
+ b_SecondCounterModus
+ ==
+ APCI1710_DOUBLE_MODE
+ ||
+ b_SecondCounterModus
+ ==
+ APCI1710_SIMPLE_MODE))
+ || (b_FirstCounterModus
+ ==
+ APCI1710_DIRECT_MODE
+ &&
+ b_SecondCounterModus
+ ==
+ APCI1710_DIRECT_MODE))
+ {
+ /**********************************/
+ /* Test the second counter option */
+ /**********************************/
+
+ if ((b_SecondCounterModus == APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_INCREMENT || b_SecondCounterOption == APCI1710_DECREMENT)) || (b_SecondCounterModus != APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_HYSTERESIS_ON || b_SecondCounterOption == APCI1710_HYSTERESIS_OFF))) {
+ i_ReturnValue =
+ 0;
+ } else {
+ /*********************************************************/
+ /* The selected second counter operating option is wrong */
+ /*********************************************************/
+
+ DPRINTK("The selected second counter operating option is wrong\n");
+ i_ReturnValue =
+ -7;
+ }
+ } else {
+ /*******************************************************/
+ /* The selected second counter operating mode is wrong */
+ /*******************************************************/
+
+ DPRINTK("The selected second counter operating mode is wrong\n");
+ i_ReturnValue = -6;
+ }
+ }
+ } else {
+ /********************************************************/
+ /* The selected first counter operating option is wrong */
+ /********************************************************/
+
+ DPRINTK("The selected first counter operating option is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /******************************************************/
+ /* The selected first counter operating mode is wrong */
+ /******************************************************/
+ DPRINTK("The selected first counter operating mode is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /***************************************/
+ /* The selected counter range is wrong */
+ /***************************************/
+
+ DPRINTK("The selected counter range is wrong\n");
+ i_ReturnValue = -3;
+ }
+
+ /*************************/
+ /* Test if a error occur */
+ /*************************/
+
+ if (i_ReturnValue == 0) {
+ /**************************/
+ /* Test if 16-Bit counter */
+ /**************************/
+
+ if (b_CounterRange == APCI1710_32BIT_COUNTER) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister1 = b_CounterRange |
+ b_FirstCounterModus |
+ b_FirstCounterOption;
+ } else {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister1 = b_CounterRange |
+ (b_FirstCounterModus & 0x5) |
+ (b_FirstCounterOption & 0x20) |
+ (b_SecondCounterModus & 0xA) |
+ (b_SecondCounterOption & 0x40);
+
+ /***********************/
+ /* Test if direct mode */
+ /***********************/
+
+ if (b_FirstCounterModus == APCI1710_DIRECT_MODE) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister1 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister1 |
+ APCI1710_DIRECT_MODE;
+ }
+ }
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.
+ ui_Address + 20 + (64 * b_ModulNbr));
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_CounterInit = 1;
+ }
+ } else {
+ /**************************************/
+ /* The module is not a counter module */
+ /**************************************/
+
+ DPRINTK("The module is not a counter module\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_CounterAutoTest |
+| (BYTE_ b_BoardHandle, |
+| PBYTE_ pb_TestStatus) |
++----------------------------------------------------------------------------+
+| Task : A test mode is intended for testing the component and |
+| the connected periphery. All the 8-bit counter chains |
+| are operated internally as down counters. |
+| Independently from the external signals, |
+| all the four 8-bit counter chains are decremented in |
+| parallel by each negative clock pulse edge of CLKX. |
+| |
+| Counter auto test conclusion |
+| ---------------------------- |
+| +-----------------+-----------------------------+ |
+| | pb_TestStatus | Error description | |
+| | mask | | |
+| |-----------------+-----------------------------| |
+| | 0000 | No error detected | |
+| |-----------------|-----------------------------| |
+| | 0001 | Error detected of counter 0 | |
+| |-----------------|-----------------------------| |
+| | 0010 | Error detected of counter 1 | |
+| |-----------------|-----------------------------| |
+| | 0100 | Error detected of counter 2 | |
+| |-----------------|-----------------------------| |
+| | 1000 | Error detected of counter 3 | |
+| +-----------------+-----------------------------+ |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_TestStatus : Auto test conclusion. See table|
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus)
+{
+ BYTE b_ModulCpt = 0;
+ INT i_ReturnValue = 0;
+ DWORD dw_LathchValue;
+
+ *pb_TestStatus = 0;
+
+ /********************************/
+ /* Test if counter module found */
+ /********************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[0] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER
+ || (devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[1] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER
+ || (devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[2] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER
+ || (devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[3] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER) {
+ for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) {
+ /*******************************/
+ /* Test if incremental counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulCpt] &
+ 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER) {
+ /******************/
+ /* Start the test */
+ /******************/
+
+ outl(3, devpriv->s_BoardInfos.
+ ui_Address + 16 + (64 * b_ModulCpt));
+
+ /*********************/
+ /* Tatch the counter */
+ /*********************/
+
+ outl(1, devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulCpt));
+
+ /************************/
+ /* Read the latch value */
+ /************************/
+
+ dw_LathchValue = inl(devpriv->s_BoardInfos.
+ ui_Address + 4 + (64 * b_ModulCpt));
+
+ if ((dw_LathchValue & 0xFF) !=
+ ((dw_LathchValue >> 8) & 0xFF)
+ && (dw_LathchValue & 0xFF) !=
+ ((dw_LathchValue >> 16) & 0xFF)
+ && (dw_LathchValue & 0xFF) !=
+ ((dw_LathchValue >> 24) & 0xFF)) {
+ *pb_TestStatus =
+ *pb_TestStatus | (1 <<
+ b_ModulCpt);
+ }
+
+ /*****************/
+ /* Stop the test */
+ /*****************/
+
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 16 + (64 * b_ModulCpt));
+ }
+ }
+ } else {
+ /***************************/
+ /* No counter module found */
+ /***************************/
+
+ DPRINTK("No counter module found\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitIndex (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_ReferenceAction, |
+| BYTE_ b_IndexOperation, |
+| BYTE_ b_AutoMode, |
+| BYTE_ b_InterruptEnable) |
++----------------------------------------------------------------------------+
+| Task : Initialise the index corresponding to the selected |
+| module (b_ModulNbr). If a INDEX flag occur, you have |
+| the possibility to clear the 32-Bit counter or to latch|
+| the current 32-Bit value in to the first latch |
+| register. The b_IndexOperation parameter give the |
+| possibility to choice the INDEX action. |
+| If you have enabled the automatic mode, each INDEX |
+| action is cleared automatically, else you must read |
+| the index status ("i_APCI1710_ReadIndexStatus") |
+| after each INDEX action. |
+| |
+| |
+| Index action |
+| ------------ |
+| |
+| +------------------------+------------------------------------+ |
+| | b_IndexOperation | Operation | |
+| |------------------------+------------------------------------| |
+| |APCI1710_LATCH_COUNTER | After a index signal, the counter | |
+| | | value (32-Bit) is latched in to | |
+| | | the first latch register | |
+| |------------------------|------------------------------------| |
+| |APCI1710_CLEAR_COUNTER | After a index signal, the counter | |
+| | | value is cleared (32-Bit) | |
+| +------------------------+------------------------------------+ |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_ReferenceAction : Determine if the reference |
+| must set or no for the |
+| acceptance from index |
+| APCI1710_ENABLE : |
+| Reference must be set for |
+| accepted the index |
+| APCI1710_DISABLE : |
+| Reference have not |
+| importance |
+| BYTE_ b_IndexOperation : Index operating mode. |
+| See table. |
+| BYTE_ b_AutoMode : Enable or disable the |
+| automatic index reset. |
+| APCI1710_ENABLE : |
+| Enable the automatic mode |
+| APCI1710_DISABLE : |
+| Disable the automatic mode |
+| BYTE_ b_InterruptEnable : Enable or disable the |
+| interrupt. |
+| APCI1710_ENABLE : |
+| Enable the interrupt |
+| APCI1710_DISABLE : |
+| Disable the interrupt |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4 The reference action parameter is wrong |
+| -5: The index operating mode parameter is wrong |
+| -6: The auto mode parameter is wrong |
+| -7: Interrupt parameter is wrong |
+| -8: Interrupt function not initialised. |
+| See function "i_APCI1710_SetBoardIntRoutineX" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitIndex(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ BYTE b_ReferenceAction,
+ BYTE b_IndexOperation, BYTE b_AutoMode, BYTE b_InterruptEnable)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /********************************/
+ /* Test the reference parameter */
+ /********************************/
+
+ if (b_ReferenceAction == APCI1710_ENABLE ||
+ b_ReferenceAction == APCI1710_DISABLE) {
+ /****************************/
+ /* Test the index parameter */
+ /****************************/
+
+ if (b_IndexOperation ==
+ APCI1710_HIGH_EDGE_LATCH_COUNTER
+ || b_IndexOperation ==
+ APCI1710_LOW_EDGE_LATCH_COUNTER
+ || b_IndexOperation ==
+ APCI1710_HIGH_EDGE_CLEAR_COUNTER
+ || b_IndexOperation ==
+ APCI1710_LOW_EDGE_CLEAR_COUNTER
+ || b_IndexOperation ==
+ APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER
+ || b_IndexOperation ==
+ APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+ {
+ /********************************/
+ /* Test the auto mode parameter */
+ /********************************/
+
+ if (b_AutoMode == APCI1710_ENABLE ||
+ b_AutoMode == APCI1710_DISABLE)
+ {
+ /***************************/
+ /* Test the interrupt mode */
+ /***************************/
+
+ if (b_InterruptEnable ==
+ APCI1710_ENABLE
+ || b_InterruptEnable ==
+ APCI1710_DISABLE) {
+
+ /************************************/
+ /* Makte the configuration commando */
+ /************************************/
+
+ if (b_ReferenceAction ==
+ APCI1710_ENABLE)
+ {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ |
+ APCI1710_ENABLE_INDEX_ACTION;
+ } else {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ &
+ APCI1710_DISABLE_INDEX_ACTION;
+ }
+
+ /****************************************/
+ /* Test if low level latch or/and clear */
+ /****************************************/
+
+ if (b_IndexOperation ==
+ APCI1710_LOW_EDGE_LATCH_COUNTER
+ ||
+ b_IndexOperation
+ ==
+ APCI1710_LOW_EDGE_CLEAR_COUNTER
+ ||
+ b_IndexOperation
+ ==
+ APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+ {
+ /*************************************/
+ /* Set the index level to low (DQ26) */
+ /*************************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ |
+ APCI1710_SET_LOW_INDEX_LEVEL;
+ } else {
+ /**************************************/
+ /* Set the index level to high (DQ26) */
+ /**************************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ &
+ APCI1710_SET_HIGH_INDEX_LEVEL;
+ }
+
+ /***********************************/
+ /* Test if latch and clear counter */
+ /***********************************/
+
+ if (b_IndexOperation ==
+ APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER
+ ||
+ b_IndexOperation
+ ==
+ APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+ {
+ /***************************************/
+ /* Set the latch and clear flag (DQ27) */
+ /***************************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ |
+ APCI1710_ENABLE_LATCH_AND_CLEAR;
+ } // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+ else {
+ /*****************************************/
+ /* Clear the latch and clear flag (DQ27) */
+ /*****************************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ &
+ APCI1710_DISABLE_LATCH_AND_CLEAR;
+
+ /*************************/
+ /* Test if latch counter */
+ /*************************/
+
+ if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER) {
+ /*********************************/
+ /* Enable the latch from counter */
+ /*********************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ |
+ APCI1710_INDEX_LATCH_COUNTER;
+ } else {
+ /*********************************/
+ /* Enable the clear from counter */
+ /*********************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ &
+ (~APCI1710_INDEX_LATCH_COUNTER);
+ }
+ } // // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER)
+
+ if (b_AutoMode ==
+ APCI1710_DISABLE)
+ {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ |
+ APCI1710_INDEX_AUTO_MODE;
+ } else {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2
+ &
+ (~APCI1710_INDEX_AUTO_MODE);
+ }
+
+ if (b_InterruptEnable ==
+ APCI1710_ENABLE)
+ {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3
+ |
+ APCI1710_ENABLE_INDEX_INT;
+ } else {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3
+ &
+ APCI1710_DISABLE_INDEX_INT;
+ }
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.
+ b_IndexInit = 1;
+
+ } else {
+ /********************************/
+ /* Interrupt parameter is wrong */
+ /********************************/
+ DPRINTK("Interrupt parameter is wrong\n");
+ i_ReturnValue = -7;
+ }
+ } else {
+ /************************************/
+ /* The auto mode parameter is wrong */
+ /************************************/
+
+ DPRINTK("The auto mode parameter is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /***********************************************/
+ /* The index operating mode parameter is wrong */
+ /***********************************************/
+
+ DPRINTK("The index operating mode parameter is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /*******************************************/
+ /* The reference action parameter is wrong */
+ /*******************************************/
+
+ DPRINTK("The reference action parameter is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitReference |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_ReferenceLevel) |
++----------------------------------------------------------------------------+
+| Task : Initialise the reference corresponding to the selected |
+| module (b_ModulNbr). |
+| |
+| Reference level |
+| --------------- |
+| +--------------------+-------------------------+ |
+| | b_ReferenceLevel | Operation | |
+| +--------------------+-------------------------+ |
+| | APCI1710_LOW | Reference occur if "0" | |
+| |--------------------|-------------------------| |
+| | APCI1710_HIGH | Reference occur if "1" | |
+| +--------------------+-------------------------+ |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_ReferenceLevel : Reference level. |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number parameter is wrong |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Reference level parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitReference(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_ReferenceLevel)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /**************************************/
+ /* Test the reference level parameter */
+ /**************************************/
+
+ if (b_ReferenceLevel == 0 || b_ReferenceLevel == 1) {
+ if (b_ReferenceLevel == 1) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 |
+ APCI1710_REFERENCE_HIGH;
+ } else {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 &
+ APCI1710_REFERENCE_LOW;
+ }
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_ReferenceInit = 1;
+ } else {
+ /**************************************/
+ /* Reference level parameter is wrong */
+ /**************************************/
+
+ DPRINTK("Reference level parameter is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitExternalStrobe |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_ExternalStrobe, |
+| BYTE_ b_ExternalStrobeLevel) |
++----------------------------------------------------------------------------+
+| Task : Initialises the external strobe level corresponding to |
+| the selected module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_ExternalStrobe : External strobe selection |
+| 0 : External strobe A |
+| 1 : External strobe B |
+| BYTE_ b_ExternalStrobeLevel : External strobe level |
+| APCI1710_LOW : |
+| External latch occurs if "0" |
+| APCI1710_HIGH : |
+| External latch occurs if "1" |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number is wrong |
+| -3: Counter not initialised. |
+| See function "i_APCI1710_InitCounter" |
+| -4: External strobe selection is wrong |
+| -5: External strobe level parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_ExternalStrobe, BYTE b_ExternalStrobeLevel)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /**************************************/
+ /* Test the external strobe selection */
+ /**************************************/
+
+ if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) {
+ /******************/
+ /* Test the level */
+ /******************/
+
+ if ((b_ExternalStrobeLevel == APCI1710_HIGH) ||
+ ((b_ExternalStrobeLevel == APCI1710_LOW
+ && (devpriv->
+ s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] &
+ 0xFFFF) >=
+ 0x3135))) {
+ /*****************/
+ /* Set the level */
+ /*****************/
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4 = (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4 & (0xFF -
+ (0x10 << b_ExternalStrobe))) | ((b_ExternalStrobeLevel ^ 1) << (4 + b_ExternalStrobe));
+ } else {
+ /********************************************/
+ /* External strobe level parameter is wrong */
+ /********************************************/
+
+ DPRINTK("External strobe level parameter is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)
+ else {
+ /**************************************/
+ /* External strobe selection is wrong */
+ /**************************************/
+
+ DPRINTK("External strobe selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1)
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : _INT_ i_APCI1710_InitCompareLogic |
+ | (BYTE_ b_BoardHandle, |
+ | BYTE_ b_ModulNbr, |
+ | UINT_ ui_CompareValue) |
+ +----------------------------------------------------------------------------+
+ | Task : Set the 32-Bit compare value. At that moment that the |
+ | incremental counter arrive to the compare value |
+ | (ui_CompareValue) a interrupt is generated. |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+ | BYTE_ b_ModulNbr : Module number to configure |
+ | (0 to 3) |
+ | UINT_ ui_CompareValue : 32-Bit compare value |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -
+ +----------------------------------------------------------------------------+
+ | Return Value : 0: No error |
+ | -1: The handle parameter of the board is wrong |
+ | -2: No counter module found |
+ | -3: Counter not initialised see function |
+ | "i_APCI1710_InitCounter" |
+ +----------------------------------------------------------------------------+
+ */
+
+INT i_APCI1710_InitCompareLogic(struct comedi_device * dev,
+ BYTE b_ModulNbr, UINT ui_CompareValue)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+
+ outl(ui_CompareValue, devpriv->s_BoardInfos.
+ ui_Address + 28 + (64 * b_ModulNbr));
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_CompareLogicInit = 1;
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitFrequencyMeasurement |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PCIInputClock, |
+| BYTE_ b_TimingUnity, |
+| ULONG_ ul_TimingInterval, |
+| PULONG_ pul_RealTimingInterval) |
++----------------------------------------------------------------------------+
+| Task : Sets the time for the frequency measurement. |
+| Configures the selected TOR incremental counter of the |
+| selected module (b_ModulNbr). The ul_TimingInterval and|
+| ul_TimingUnity determine the time base for the |
+| measurement. The pul_RealTimingInterval returns the |
+| real time value. You must call up this function before |
+| you call up any other function which gives access to |
+| the frequency measurement. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Number of the module to be |
+| configured (0 to 3) |
+| BYTE_ b_PCIInputClock : Selection of the PCI bus |
+| clock |
+| - APCI1710_30MHZ : |
+| The PC has a PCI bus clock |
+| of 30 MHz |
+| - APCI1710_33MHZ : |
+| The PC has a PCI bus clock |
+| of 33 MHz |
+| BYTE_ b_TimingUnity : Base time unit (0 to 2) |
+| 0 : ns |
+| 1 : æs |
+| 2 : ms |
+| ULONG_ ul_TimingInterval: Base time value. |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_RealTimingInterval : Real base time value. |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number is wrong |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: The selected PCI input clock is wrong |
+| -5: Timing unity selection is wrong |
+| -6: Base timing selection is wrong |
+| -7: 40MHz quartz not on board |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ BYTE b_PCIInputClock,
+ BYTE b_TimingUnity,
+ ULONG ul_TimingInterval, PULONG pul_RealTimingInterval)
+{
+ INT i_ReturnValue = 0;
+ ULONG ul_TimerValue = 0;
+ double d_RealTimingInterval;
+ DWORD dw_Status = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /**************************/
+ /* Test the PCI bus clock */
+ /**************************/
+
+ if ((b_PCIInputClock == APCI1710_30MHZ) ||
+ (b_PCIInputClock == APCI1710_33MHZ) ||
+ (b_PCIInputClock == APCI1710_40MHZ)) {
+ /************************/
+ /* Test the timing unit */
+ /************************/
+
+ if (b_TimingUnity <= 2) {
+ /**********************************/
+ /* Test the base timing selection */
+ /**********************************/
+
+ if (((b_PCIInputClock == APCI1710_30MHZ)
+ && (b_TimingUnity == 0)
+ && (ul_TimingInterval >=
+ 266)
+ && (ul_TimingInterval <=
+ 8738133UL))
+ || ((b_PCIInputClock ==
+ APCI1710_30MHZ)
+ && (b_TimingUnity == 1)
+ && (ul_TimingInterval >=
+ 1)
+ && (ul_TimingInterval <=
+ 8738UL))
+ || ((b_PCIInputClock ==
+ APCI1710_30MHZ)
+ && (b_TimingUnity == 2)
+ && (ul_TimingInterval >=
+ 1)
+ && (ul_TimingInterval <=
+ 8UL))
+ || ((b_PCIInputClock ==
+ APCI1710_33MHZ)
+ && (b_TimingUnity == 0)
+ && (ul_TimingInterval >=
+ 242)
+ && (ul_TimingInterval <=
+ 7943757UL))
+ || ((b_PCIInputClock ==
+ APCI1710_33MHZ)
+ && (b_TimingUnity == 1)
+ && (ul_TimingInterval >=
+ 1)
+ && (ul_TimingInterval <=
+ 7943UL))
+ || ((b_PCIInputClock ==
+ APCI1710_33MHZ)
+ && (b_TimingUnity == 2)
+ && (ul_TimingInterval >=
+ 1)
+ && (ul_TimingInterval <=
+ 7UL))
+ || ((b_PCIInputClock ==
+ APCI1710_40MHZ)
+ && (b_TimingUnity == 0)
+ && (ul_TimingInterval >=
+ 200)
+ && (ul_TimingInterval <=
+ 6553500UL))
+ || ((b_PCIInputClock ==
+ APCI1710_40MHZ)
+ && (b_TimingUnity == 1)
+ && (ul_TimingInterval >=
+ 1)
+ && (ul_TimingInterval <=
+ 6553UL))
+ || ((b_PCIInputClock ==
+ APCI1710_40MHZ)
+ && (b_TimingUnity == 2)
+ && (ul_TimingInterval >=
+ 1)
+ && (ul_TimingInterval <=
+ 6UL))) {
+ /**********************/
+ /* Test if 40MHz used */
+ /**********************/
+
+ if (b_PCIInputClock ==
+ APCI1710_40MHZ) {
+ /******************************/
+ /* Test if firmware >= Rev1.5 */
+ /******************************/
+
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3135) {
+ /*********************************/
+ /* Test if 40MHz quartz on board */
+ /*********************************/
+
+ /*INPDW (ps_APCI1710Variable->
+ s_Board [b_BoardHandle].
+ s_BoardInfos.
+ ui_Address + 36 + (64 * b_ModulNbr), &dw_Status); */
+ dw_Status =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ + 36 +
+ (64 * b_ModulNbr));
+
+ /******************************/
+ /* Test the quartz flag (DQ0) */
+ /******************************/
+
+ if ((dw_Status & 1) != 1) {
+ /*****************************/
+ /* 40MHz quartz not on board */
+ /*****************************/
+
+ DPRINTK("40MHz quartz not on board\n");
+ i_ReturnValue
+ =
+ -7;
+ }
+ } else {
+ /*****************************/
+ /* 40MHz quartz not on board */
+ /*****************************/
+ DPRINTK("40MHz quartz not on board\n");
+ i_ReturnValue =
+ -7;
+ }
+ } // if (b_PCIInputClock == APCI1710_40MHZ)
+
+ /***************************/
+ /* Test if not error occur */
+ /***************************/
+
+ if (i_ReturnValue == 0) {
+ /****************************/
+ /* Test the INC_CPT version */
+ /****************************/
+
+ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131) {
+
+ /**********************/
+ /* Test if 40MHz used */
+ /**********************/
+
+ if (b_PCIInputClock == APCI1710_40MHZ) {
+ /*********************************/
+ /* Enable the 40MHz quarz (DQ30) */
+ /*********************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ |
+ APCI1710_ENABLE_40MHZ_FREQUENCY;
+ } // if (b_PCIInputClock == APCI1710_40MHZ)
+ else {
+ /**********************************/
+ /* Disable the 40MHz quarz (DQ30) */
+ /**********************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ &
+ APCI1710_DISABLE_40MHZ_FREQUENCY;
+
+ } // if (b_PCIInputClock == APCI1710_40MHZ)
+
+ /********************************/
+ /* Calculate the division fator */
+ /********************************/
+
+ fpu_begin();
+ switch (b_TimingUnity) {
+ /******/
+ /* ns */
+ /******/
+
+ case 0:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (0.00025 * b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (0.00025 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (0.00025
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
+ *pul_RealTimingInterval
+ =
+ *pul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ break;
+
+ /******/
+ /* æs */
+ /******/
+
+ case 1:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (0.25 * b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (0.25 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (
+ (double)
+ 0.25
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
+ *pul_RealTimingInterval
+ =
+ *pul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ break;
+
+ /******/
+ /* ms */
+ /******/
+
+ case 2:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ ul_TimingInterval
+ *
+ (250.0
+ *
+ b_PCIInputClock);
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (250.0 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (250.0
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) {
+ *pul_RealTimingInterval
+ =
+ *pul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ break;
+ }
+
+ fpu_end();
+ /*************************/
+ /* Write the timer value */
+ /*************************/
+
+ outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 32 + (64 * b_ModulNbr));
+
+ /*******************************/
+ /* Set the initialisation flag */
+ /*******************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.
+ b_FrequencyMeasurementInit
+ = 1;
+ } else {
+ /***************************/
+ /* Counter not initialised */
+ /***************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue =
+ -3;
+ }
+ } // if (i_ReturnValue == 0)
+ } else {
+ /**********************************/
+ /* Base timing selection is wrong */
+ /**********************************/
+
+ DPRINTK("Base timing selection is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /***********************************/
+ /* Timing unity selection is wrong */
+ /***********************************/
+
+ DPRINTK("Timing unity selection is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /*****************************************/
+ /* The selected PCI input clock is wrong */
+ /*****************************************/
+
+ DPRINTK("The selected PCI input clock is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*########################################################################### */
+
+ //INSN BITS
+/*########################################################################### */
+
+/*
++----------------------------------------------------------------------------+
+| Function Name :INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Set & Clear Functions for INC_CPT |
++----------------------------------------------------------------------------+
+| Input Parameters :
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_BitsType;
+ INT i_ReturnValue = 0;
+ ui_BitsType = CR_CHAN(insn->chanspec);
+ devpriv->tsk_Current = current; // Save the current process task structure
+
+ switch (ui_BitsType) {
+ case APCI1710_INCCPT_CLEARCOUNTERVALUE:
+ i_ReturnValue = i_APCI1710_ClearCounterValue(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_CLEARALLCOUNTERVALUE:
+ i_ReturnValue = i_APCI1710_ClearAllCounterValue(dev);
+ break;
+
+ case APCI1710_INCCPT_SETINPUTFILTER:
+ i_ReturnValue = i_APCI1710_SetInputFilter(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (BYTE) data[0], (BYTE) data[1]);
+ break;
+
+ case APCI1710_INCCPT_LATCHCOUNTER:
+ i_ReturnValue = i_APCI1710_LatchCounter(dev,
+ (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+ break;
+
+ case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE:
+ i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev,
+ (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+ break;
+
+ case APCI1710_INCCPT_SETDIGITALCHLON:
+ i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_SETDIGITALCHLOFF:
+ i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ default:
+ printk("Bits Config Parameter Wrong\n");
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ClearCounterValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Clear the counter value from selected module |
+| (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number parameter is wrong |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*********************/
+ /* Clear the counter */
+ /*********************/
+
+ outl(1, devpriv->s_BoardInfos.
+ ui_Address + 16 + (64 * b_ModulNbr));
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ClearAllCounterValue |
+| (BYTE_ b_BoardHandle) |
++----------------------------------------------------------------------------+
+| Task : Clear all counter value. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev)
+{
+ BYTE b_ModulCpt = 0;
+ INT i_ReturnValue = 0;
+
+ /********************************/
+ /* Test if counter module found */
+ /********************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[0] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER
+ || (devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[1] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER
+ || (devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[2] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER
+ || (devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[3] & 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER) {
+ for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) {
+ /*******************************/
+ /* Test if incremental counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulCpt] &
+ 0xFFFF0000UL) ==
+ APCI1710_INCREMENTAL_COUNTER) {
+ /*********************/
+ /* Clear the counter */
+ /*********************/
+
+ outl(1, devpriv->s_BoardInfos.
+ ui_Address + 16 + (64 * b_ModulCpt));
+ }
+ }
+ } else {
+ /***************************/
+ /* No counter module found */
+ /***************************/
+
+ DPRINTK("No counter module found\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_SetInputFilter |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_Module, |
+| BYTE_ b_PCIInputClock, |
+| BYTE_ b_Filter) |
++----------------------------------------------------------------------------+
+| Task : Disable or enable the software filter from selected |
+| module (b_ModulNbr). b_Filter determine the filter time|
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Number of the module to be |
+| configured (0 to 3) |
+| BYTE_ b_PCIInputClock : Selection of the PCI bus |
+| clock |
+| - APCI1710_30MHZ : |
+| The PC has a PCI bus clock |
+| of 30 MHz |
+| - APCI1710_33MHZ : |
+| The PC has a PCI bus clock |
+| of 33 MHz |
+| - APCI1710_40MHZ : |
+| The APCI1710 has a 40MHz |
+| quartz |
+| BYTE_ b_Filter : Filter selection |
+| |
+| 30 MHz |
+| ------ |
+| 0: Software filter not used |
+| 1: Filter from 266ns (3.750000MHz) |
+| 2: Filter from 400ns (2.500000MHz) |
+| 3: Filter from 533ns (1.876170MHz) |
+| 4: Filter from 666ns (1.501501MHz) |
+| 5: Filter from 800ns (1.250000MHz) |
+| 6: Filter from 933ns (1.071800MHz) |
+| 7: Filter from 1066ns (0.938080MHz) |
+| 8: Filter from 1200ns (0.833333MHz) |
+| 9: Filter from 1333ns (0.750000MHz) |
+| 10: Filter from 1466ns (0.682100MHz) |
+| 11: Filter from 1600ns (0.625000MHz) |
+| 12: Filter from 1733ns (0.577777MHz) |
+| 13: Filter from 1866ns (0.535900MHz) |
+| 14: Filter from 2000ns (0.500000MHz) |
+| 15: Filter from 2133ns (0.468800MHz) |
+| |
+| 33 MHz |
+| ------ |
+| 0: Software filter not used |
+| 1: Filter from 242ns (4.125000MHz) |
+| 2: Filter from 363ns (2.754820MHz) |
+| 3: Filter from 484ns (2.066115MHz) |
+| 4: Filter from 605ns (1.652892MHz) |
+| 5: Filter from 726ns (1.357741MHz) |
+| 6: Filter from 847ns (1.180637MHz) |
+| 7: Filter from 968ns (1.033055MHz) |
+| 8: Filter from 1089ns (0.918273MHz) |
+| 9: Filter from 1210ns (0.826446MHz) |
+| 10: Filter from 1331ns (0.751314MHz) |
+| 11: Filter from 1452ns (0.688705MHz) |
+| 12: Filter from 1573ns (0.635727MHz) |
+| 13: Filter from 1694ns (0.590318MHz) |
+| 14: Filter from 1815ns (0.550964MHz) |
+| 15: Filter from 1936ns (0.516528MHz) |
+| |
+| 40 MHz |
+| ------ |
+| 0: Software filter not used |
+| 1: Filter from 200ns (5.000000MHz) |
+| 2: Filter from 300ns (3.333333MHz) |
+| 3: Filter from 400ns (2.500000MHz) |
+| 4: Filter from 500ns (2.000000MHz) |
+| 5: Filter from 600ns (1.666666MHz) |
+| 6: Filter from 700ns (1.428500MHz) |
+| 7: Filter from 800ns (1.250000MHz) |
+| 8: Filter from 900ns (1.111111MHz) |
+| 9: Filter from 1000ns (1.000000MHz) |
+| 10: Filter from 1100ns (0.909090MHz) |
+| 11: Filter from 1200ns (0.833333MHz) |
+| 12: Filter from 1300ns (0.769200MHz) |
+| 13: Filter from 1400ns (0.714200MHz) |
+| 14: Filter from 1500ns (0.666666MHz) |
+| 15: Filter from 1600ns (0.625000MHz) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number is wrong |
+| -3: The module is not a counter module |
+| -4: The selected PCI input clock is wrong |
+| -5: The selected filter value is wrong |
+| -6: 40MHz quartz not on board |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetInputFilter(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_PCIInputClock, BYTE b_Filter)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if incremental counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
+ /******************************/
+ /* Test if firmware >= Rev1.5 */
+ /******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF) >= 0x3135) {
+ /**************************/
+ /* Test the PCI bus clock */
+ /**************************/
+
+ if ((b_PCIInputClock == APCI1710_30MHZ) ||
+ (b_PCIInputClock == APCI1710_33MHZ) ||
+ (b_PCIInputClock == APCI1710_40MHZ)) {
+ /*************************/
+ /* Test the filter value */
+ /*************************/
+
+ if (b_Filter < 16) {
+ /**********************/
+ /* Test if 40MHz used */
+ /**********************/
+
+ if (b_PCIInputClock ==
+ APCI1710_40MHZ) {
+ /*********************************/
+ /* Test if 40MHz quartz on board */
+ /*********************************/
+
+ dw_Status =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address +
+ 36 +
+ (64 * b_ModulNbr));
+
+ /******************************/
+ /* Test the quartz flag (DQ0) */
+ /******************************/
+
+ if ((dw_Status & 1) !=
+ 1) {
+ /*****************************/
+ /* 40MHz quartz not on board */
+ /*****************************/
+
+ DPRINTK("40MHz quartz not on board\n");
+ i_ReturnValue =
+ -6;
+ }
+ } // if (b_PCIInputClock == APCI1710_40MHZ)
+
+ /***************************/
+ /* Test if error not occur */
+ /***************************/
+
+ if (i_ReturnValue == 0) {
+ /**********************/
+ /* Test if 40MHz used */
+ /**********************/
+
+ if (b_PCIInputClock ==
+ APCI1710_40MHZ)
+ {
+ /*********************************/
+ /* Enable the 40MHz quarz (DQ31) */
+ /*********************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ |
+ APCI1710_ENABLE_40MHZ_FILTER;
+
+ } // if (b_PCIInputClock == APCI1710_40MHZ)
+ else {
+ /**********************************/
+ /* Disable the 40MHz quarz (DQ31) */
+ /**********************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ &
+ APCI1710_DISABLE_40MHZ_FILTER;
+
+ } // if (b_PCIInputClock == APCI1710_40MHZ)
+
+ /************************/
+ /* Set the filter value */
+ /************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3
+ =
+ (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3
+ & 0x1F) |
+ ((b_Filter &
+ 0x7) <<
+ 5);
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ =
+ (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4
+ & 0xFE) |
+ ((b_Filter &
+ 0x8) >>
+ 3);
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->
+ s_BoardInfos.
+ ui_Address +
+ 20 +
+ (64 * b_ModulNbr));
+ } // if (i_ReturnValue == 0)
+ } // if (b_Filter < 16)
+ else {
+ /**************************************/
+ /* The selected filter value is wrong */
+ /**************************************/
+
+ DPRINTK("The selected filter value is wrong\n");
+ i_ReturnValue = -5;
+ } // if (b_Filter < 16)
+ } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))
+ else {
+ /*****************************************/
+ /* The selected PCI input clock is wrong */
+ /*****************************************/
+
+ DPRINTK("The selected PCI input clock is wrong\n");
+ i_ReturnValue = 4;
+ } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ))
+ } else {
+ /**************************************/
+ /* The module is not a counter module */
+ /**************************************/
+
+ DPRINTK("The module is not a counter module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /**************************************/
+ /* The module is not a counter module */
+ /**************************************/
+
+ DPRINTK("The module is not a counter module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_LatchCounter (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_LatchReg) |
++----------------------------------------------------------------------------+
+| Task : Latch the courant value from selected module |
+| (b_ModulNbr) in to the selected latch register |
+| (b_LatchReg). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_LatchReg : Selected latch register |
+| 0 : for the first latch register |
+| 1 : for the second latch register |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: The selected latch register parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_LatchCounter(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_LatchReg)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*************************************/
+ /* Test the latch register parameter */
+ /*************************************/
+
+ if (b_LatchReg < 2) {
+ /*********************/
+ /* Tatch the counter */
+ /*********************/
+
+ outl(1 << (b_LatchReg * 4),
+ devpriv->s_BoardInfos.ui_Address +
+ (64 * b_ModulNbr));
+ } else {
+ /**************************************************/
+ /* The selected latch register parameter is wrong */
+ /**************************************************/
+
+ DPRINTK("The selected latch register parameter is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_SetIndexAndReferenceSource |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_SourceSelection) |
++----------------------------------------------------------------------------+
+| Task : Determine the hardware source for the index and the |
+| reference logic. Per default the index logic is |
+| connected to the difference input C and the reference |
+| logic is connected to the 24V input E |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_SourceSelection : APCI1710_SOURCE_0 : |
+| The index logic is connected |
+| to the difference input C and|
+| the reference logic is |
+| connected to the 24V input E.|
+| This is the default |
+| configuration. |
+| APCI1710_SOURCE_1 : |
+| The reference logic is |
+| connected to the difference |
+| input C and the index logic |
+| is connected to the 24V |
+| input E |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number is wrong |
+| -3: The module is not a counter module. |
+| -4: The source selection is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_SourceSelection)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if incremental counter */
+ /*******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
+ /******************************/
+ /* Test if firmware >= Rev1.5 */
+ /******************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF) >= 0x3135) {
+ /*****************************/
+ /* Test the source selection */
+ /*****************************/
+
+ if (b_SourceSelection == APCI1710_SOURCE_0 ||
+ b_SourceSelection == APCI1710_SOURCE_1)
+ {
+ /******************************************/
+ /* Test if invert the index and reference */
+ /******************************************/
+
+ if (b_SourceSelection ==
+ APCI1710_SOURCE_1) {
+ /********************************************/
+ /* Invert index and reference source (DQ25) */
+ /********************************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4 =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4 |
+ APCI1710_INVERT_INDEX_RFERENCE;
+ } else {
+ /****************************************/
+ /* Set the default configuration (DQ25) */
+ /****************************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4 =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister4 &
+ APCI1710_DEFAULT_INDEX_RFERENCE;
+ }
+ } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)
+ else {
+ /*********************************/
+ /* The source selection is wrong */
+ /*********************************/
+
+ DPRINTK("The source selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1)
+ } else {
+ /**************************************/
+ /* The module is not a counter module */
+ /**************************************/
+
+ DPRINTK("The module is not a counter module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /**************************************/
+ /* The module is not a counter module */
+ /**************************************/
+
+ DPRINTK("The module is not a counter module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***************************************/
+ /* The selected module number is wrong */
+ /***************************************/
+
+ DPRINTK("The selected module number is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_SetDigitalChlOn |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Sets the digital output H Setting an output means |
+| setting an ouput high. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Number of the module to be |
+| configured (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number is wrong |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.b_ModeRegister3 | 0x10;
+
+ /*********************/
+ /* Set the output On */
+ /*********************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
+ ui_Address + 20 + (64 * b_ModulNbr));
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_SetDigitalChlOff |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Resets the digital output H. Resetting an output means |
+| setting an ouput low. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Number of the module to be |
+| configured (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The selected module number is wrong |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.b_ModeRegister3 & 0xEF;
+
+ /**********************/
+ /* Set the output Off */
+ /**********************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
+ ui_Address + 20 + (64 * b_ModulNbr));
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*########################################################################### */
+
+ // INSN WRITE
+/*########################################################################### */
+
+/*
++----------------------------------------------------------------------------+
+| Function Name :INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Enable Disable functions for INC_CPT |
++----------------------------------------------------------------------------+
+| Input Parameters :
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_WriteType;
+ INT i_ReturnValue = 0;
+
+ ui_WriteType = CR_CHAN(insn->chanspec);
+ devpriv->tsk_Current = current; // Save the current process task structure
+
+ switch (ui_WriteType) {
+ case APCI1710_INCCPT_ENABLELATCHINTERRUPT:
+ i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_DISABLELATCHINTERRUPT:
+ i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:
+ i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (BYTE) data[0], (UINT) data[1]);
+ break;
+
+ case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
+ i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev,
+ (BYTE) CR_AREF(insn->chanspec), (ULONG) data[0]);
+
+ break;
+
+ case APCI1710_INCCPT_ENABLEINDEX:
+ i_APCI1710_EnableIndex(dev, (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_DISABLEINDEX:
+ i_ReturnValue = i_APCI1710_DisableIndex(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_ENABLECOMPARELOGIC:
+ i_ReturnValue = i_APCI1710_EnableCompareLogic(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_DISABLECOMPARELOGIC:
+ i_ReturnValue = i_APCI1710_DisableCompareLogic(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT:
+ i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev,
+ (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+ break;
+
+ case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT:
+ i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev,
+ (BYTE) CR_AREF(insn->chanspec));
+ break;
+
+ default:
+ printk("Write Config Parameter Wrong\n");
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnableLatchInterrupt |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Enable the latch interrupt from selected module |
+| (b_ModulNbr). Each software or hardware latch occur a |
+| interrupt. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Interrupt routine not installed see function |
+| "i_APCI1710_SetBoardIntRoutine" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+
+ /********************/
+ /* Enable interrupt */
+ /********************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 | APCI1710_ENABLE_LATCH_INT;
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos.
+ ui_Address + 20 + (64 * b_ModulNbr));
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_DisableLatchInterrupt |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Disable the latch interrupt from selected module |
+| (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Interrupt routine not installed see function |
+| "i_APCI1710_SetBoardIntRoutine" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4 &
+ ((APCI1710_DISABLE_LATCH_INT << 8) | 0xFF),
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+
+ mdelay(1000);
+
+ /*********************/
+ /* Disable interrupt */
+ /*********************/
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 & APCI1710_DISABLE_LATCH_INT;
+
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_Write16BitCounterValue |
+| (BYTE_ b_BoardHandle |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_SelectedCounter, |
+| UINT_ ui_WriteValue) |
++----------------------------------------------------------------------------+
+| Task : Write a 16-Bit value (ui_WriteValue) in to the selected|
+| 16-Bit counter (b_SelectedCounter) from selected module|
+| (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_SelectedCounter : Selected 16-Bit counter |
+| (0 or 1) |
+| UINT_ ui_WriteValue : 16-Bit write value |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: The selected 16-Bit counter parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_SelectedCounter, UINT ui_WriteValue)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /******************************/
+ /* Test the counter selection */
+ /******************************/
+
+ if (b_SelectedCounter < 2) {
+ /*******************/
+ /* Write the value */
+ /*******************/
+
+ outl((ULONG) ((ULONG) (ui_WriteValue) << (16 *
+ b_SelectedCounter)),
+ devpriv->s_BoardInfos.ui_Address + 8 +
+ (b_SelectedCounter * 4) +
+ (64 * b_ModulNbr));
+ } else {
+ /**************************************************/
+ /* The selected 16-Bit counter parameter is wrong */
+ /**************************************************/
+
+ DPRINTK("The selected 16-Bit counter parameter is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_Write32BitCounterValue |
+| (BYTE_ b_BoardHandle |
+| BYTE_ b_ModulNbr, |
+| ULONG_ ul_WriteValue) |
++----------------------------------------------------------------------------+
+| Task : Write a 32-Bit value (ui_WriteValue) in to the selected|
+| module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| ULONG_ ul_WriteValue : 32-Bit write value |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev,
+ BYTE b_ModulNbr, ULONG ul_WriteValue)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*******************/
+ /* Write the value */
+ /*******************/
+
+ outl(ul_WriteValue, devpriv->s_BoardInfos.
+ ui_Address + 4 + (64 * b_ModulNbr));
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnableIndex (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Enable the INDEX actions |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Index not initialised see function |
+| "i_APCI1710_InitIndex" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+ ULONG ul_InterruptLatchReg;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*****************************/
+ /* Test if index initialised */
+ /*****************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 | APCI1710_ENABLE_INDEX;
+
+ ul_InterruptLatchReg =
+ inl(devpriv->s_BoardInfos.ui_Address +
+ 24 + (64 * b_ModulNbr));
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+ } else {
+ /*************************************************************/
+ /* Index not initialised see function "i_APCI1710_InitIndex" */
+ /*************************************************************/
+
+ DPRINTK("Index not initialised \n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_DisableIndex (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Disable the INDEX actions |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Index not initialised see function |
+| "i_APCI1710_InitIndex" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisableIndex(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*****************************/
+ /* Test if index initialised */
+ /*****************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 &
+ APCI1710_DISABLE_INDEX;
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+ } else {
+ /*************************************************************/
+ /* Index not initialised see function "i_APCI1710_InitIndex" */
+ /*************************************************************/
+
+ DPRINTK("Index not initialised \n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnableCompareLogic |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Enable the 32-Bit compare logic. At that moment that |
+| the incremental counter arrive to the compare value a |
+| interrupt is generated. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : -
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Compare logic not initialised. |
+| See function "i_APCI1710_InitCompareLogic" |
+| -5: Interrupt function not initialised. |
+| See function "i_APCI1710_SetBoardIntRoutineX" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*************************************/
+ /* Test if compare logic initialised */
+ /*************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_CompareLogicInit == 1) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 |
+ APCI1710_ENABLE_COMPARE_INT;
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+ } else {
+ /*********************************/
+ /* Compare logic not initialised */
+ /*********************************/
+
+ DPRINTK("Compare logic not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_DisableCompareLogic |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Task : Disable the 32-Bit compare logic.
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : -
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Compare logic not initialised. |
+| See function "i_APCI1710_InitCompareLogic" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*************************************/
+ /* Test if compare logic initialised */
+ /*************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_CompareLogicInit == 1) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 &
+ APCI1710_DISABLE_COMPARE_INT;
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+ } else {
+ /*********************************/
+ /* Compare logic not initialised */
+ /*********************************/
+
+ DPRINTK("Compare logic not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : _INT_ i_APCI1710_EnableFrequencyMeasurement |
+ | (BYTE_ b_BoardHandle, |
+ | BYTE_ b_ModulNbr, |
+ | BYTE_ b_InterruptEnable) |
+ +----------------------------------------------------------------------------+
+ | Task : Enables the frequency measurement function |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+ | BYTE_ b_ModulNbr : Number of the module to be |
+ | configured (0 to 3) |
+ | BYTE_ b_InterruptEnable: Enable or disable the |
+ | interrupt. |
+ | APCI1710_ENABLE: |
+ | Enable the interrupt |
+ | APCI1710_DISABLE: |
+ | Disable the interrupt |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : - |
+ +----------------------------------------------------------------------------+
+ | Return Value : 0: No error |
+ | -1: The handle parameter of the board is wrong |
+ | -2: The selected module number is wrong |
+ | -3: Counter not initialised see function |
+ | "i_APCI1710_InitCounter" |
+ | -4: Frequency measurement logic not initialised. |
+ | See function "i_APCI1710_InitFrequencyMeasurement" |
+ | -5: Interrupt parameter is wrong |
+ | -6: Interrupt function not initialised. |
+ +----------------------------------------------------------------------------+
+ */
+
+INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_InterruptEnable)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /********************************************/
+ /* Test if frequency mesurement initialised */
+ /********************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_FrequencyMeasurementInit == 1) {
+ /***************************/
+ /* Test the interrupt mode */
+ /***************************/
+
+ if ((b_InterruptEnable == APCI1710_DISABLE) ||
+ (b_InterruptEnable == APCI1710_ENABLE))
+ {
+
+ /************************************/
+ /* Enable the frequency measurement */
+ /************************************/
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 |
+ APCI1710_ENABLE_FREQUENCY;
+
+ /*********************************************/
+ /* Disable or enable the frequency interrupt */
+ /*********************************************/
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 = (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 &
+ APCI1710_DISABLE_FREQUENCY_INT)
+ | (b_InterruptEnable << 3);
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.
+ ui_Address + 20 +
+ (64 * b_ModulNbr));
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.
+ b_FrequencyMeasurementEnable =
+ 1;
+ } else {
+ /********************************/
+ /* Interrupt parameter is wrong */
+ /********************************/
+
+ DPRINTK("Interrupt parameter is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /***********************************************/
+ /* Frequency measurement logic not initialised */
+ /***********************************************/
+
+ DPRINTK("Frequency measurement logic not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : _INT_ i_APCI1710_DisableFrequencyMeasurement |
+ | (BYTE_ b_BoardHandle, |
+ | BYTE_ b_ModulNbr) |
+ +----------------------------------------------------------------------------+
+ | Task : Disables the frequency measurement function |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+ | BYTE_ b_ModulNbr : Number of the module to be |
+ | configured (0 to 3) |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : - |
+ +----------------------------------------------------------------------------+
+ | Return Value : 0: No error |
+ | -1: The handle parameter of the board is wrong |
+ | -2: The selected module number is wrong |
+ | -3: Counter not initialised see function |
+ | "i_APCI1710_InitCounter" |
+ | -4: Frequency measurement logic not initialised. |
+ | See function "i_APCI1710_InitFrequencyMeasurement" |
+ +----------------------------------------------------------------------------+
+ */
+
+INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, BYTE b_ModulNbr)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /********************************************/
+ /* Test if frequency mesurement initialised */
+ /********************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_FrequencyMeasurementInit == 1) {
+ /*************************************/
+ /* Disable the frequency measurement */
+ /*************************************/
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 &
+ APCI1710_DISABLE_FREQUENCY
+ // Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared
+ & APCI1710_DISABLE_FREQUENCY_INT;
+ // End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+
+ /*************************************/
+ /* Disable the frequency measurement */
+ /*************************************/
+
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.
+ b_FrequencyMeasurementEnable = 0;
+ } else {
+ /***********************************************/
+ /* Frequency measurement logic not initialised */
+ /***********************************************/
+
+ DPRINTK("Frequency measurement logic not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*########################################################################### */
+
+ // INSN READ
+
+/*########################################################################### */
+
+/*
++----------------------------------------------------------------------------+
+| Function Name :INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
+struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read and Get functions for INC_CPT |
++----------------------------------------------------------------------------+
+| Input Parameters :
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_ReadType;
+ INT i_ReturnValue = 0;
+
+ ui_ReadType = CR_CHAN(insn->chanspec);
+
+ devpriv->tsk_Current = current; // Save the current process task structure
+ switch (ui_ReadType) {
+ case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
+ i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (BYTE) CR_RANGE(insn->chanspec), (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_READLATCHREGISTERVALUE:
+ i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (BYTE) CR_RANGE(insn->chanspec), (PULONG) & data[0]);
+ printk("Latch Register Value %d\n", data[0]);
+ break;
+
+ case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
+ i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (BYTE) CR_RANGE(insn->chanspec), (PUINT) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
+ i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PULONG) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_GETINDEXSTATUS:
+ i_ReturnValue = i_APCI1710_GetIndexStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_GETREFERENCESTATUS:
+ i_ReturnValue = i_APCI1710_GetReferenceStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_GETUASSTATUS:
+ i_ReturnValue = i_APCI1710_GetUASStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_GETCBSTATUS:
+ i_ReturnValue = i_APCI1710_GetCBStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_GET16BITCBSTATUS:
+ i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (PBYTE) & data[0], (PBYTE) & data[1]);
+ break;
+
+ case APCI1710_INCCPT_GETUDSTATUS:
+ i_ReturnValue = i_APCI1710_GetUDStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+
+ break;
+
+ case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:
+ i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev,
+ (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]);
+ break;
+
+ case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:
+ i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (PBYTE) & data[0],
+ (PBYTE) & data[1], (PULONG) & data[2]);
+ break;
+
+ case APCI1710_INCCPT_READINTERRUPT:
+ data[0] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].b_OldModuleMask;
+ data[1] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+ data[2] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+ /**************************/
+ /* Increment the read FIFO */
+ /***************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Read = (devpriv->s_InterruptParameters.
+ ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+ break;
+
+ default:
+ printk("ReadType Parameter wrong\n");
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadLatchRegisterStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_LatchReg, |
+| PBYTE_ pb_LatchStatus) |
++----------------------------------------------------------------------------+
+| Task : Read the latch register status from selected module |
+| (b_ModulNbr) and selected latch register (b_LatchReg). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_LatchReg : Selected latch register |
+| 0 : for the first latch register |
+| 1 : for the second latch register |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_LatchStatus : Latch register status. |
+| 0 : No latch occur |
+| 1 : A software latch occur |
+| 2 : A hardware latch occur |
+| 3 : A software and hardware |
+| latch occur |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: The selected latch register parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_LatchReg, PBYTE pb_LatchStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_LatchReg;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*************************************/
+ /* Test the latch register parameter */
+ /*************************************/
+
+ if (b_LatchReg < 2) {
+ dw_LatchReg = inl(devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulNbr));
+
+ *pb_LatchStatus =
+ (BYTE) ((dw_LatchReg >> (b_LatchReg *
+ 4)) & 0x3);
+ } else {
+ /**************************************************/
+ /* The selected latch register parameter is wrong */
+ /**************************************************/
+
+ DPRINTK("The selected latch register parameter is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadLatchRegisterValue |
+| (BYTE_ b_BoardHandle,|
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_LatchReg, |
+| PULONG_ pul_LatchValue) |
++----------------------------------------------------------------------------+
+| Task : Read the latch register value from selected module |
+| (b_ModulNbr) and selected latch register (b_LatchReg). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_LatchReg : Selected latch register |
+| 0 : for the first latch register |
+| 1 : for the second latch register |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_LatchValue : Latch register value |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: The selected latch register parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_LatchReg, PULONG pul_LatchValue)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*************************************/
+ /* Test the latch register parameter */
+ /*************************************/
+
+ if (b_LatchReg < 2) {
+ *pul_LatchValue = inl(devpriv->s_BoardInfos.
+ ui_Address + ((b_LatchReg + 1) * 4) +
+ (64 * b_ModulNbr));
+
+ } else {
+ /**************************************************/
+ /* The selected latch register parameter is wrong */
+ /**************************************************/
+
+ DPRINTK("The selected latch register parameter is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_Read16BitCounterValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_SelectedCounter, |
+| PUINT_ pui_CounterValue) |
++----------------------------------------------------------------------------+
+| Task : Latch the selected 16-Bit counter (b_SelectedCounter) |
+| from selected module (b_ModulNbr) in to the first |
+| latch register and return the latched value. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| BYTE_ b_SelectedCounter : Selected 16-Bit counter |
+| (0 or 1) |
++----------------------------------------------------------------------------+
+| Output Parameters : PUINT_ pui_CounterValue : 16-Bit counter value |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: The selected 16-Bit counter parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev,
+ BYTE b_ModulNbr, BYTE b_SelectedCounter, PUINT pui_CounterValue)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_LathchValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /******************************/
+ /* Test the counter selection */
+ /******************************/
+
+ if (b_SelectedCounter < 2) {
+ /*********************/
+ /* Latch the counter */
+ /*********************/
+
+ outl(1, devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulNbr));
+
+ /************************/
+ /* Read the latch value */
+ /************************/
+
+ dw_LathchValue = inl(devpriv->s_BoardInfos.
+ ui_Address + 4 + (64 * b_ModulNbr));
+
+ *pui_CounterValue =
+ (UINT) ((dw_LathchValue >> (16 *
+ b_SelectedCounter)) &
+ 0xFFFFU);
+ } else {
+ /**************************************************/
+ /* The selected 16-Bit counter parameter is wrong */
+ /**************************************************/
+
+ DPRINTK("The selected 16-Bit counter parameter is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_Read32BitCounterValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PULONG_ pul_CounterValue) |
++----------------------------------------------------------------------------+
+| Task : Latch the 32-Bit counter from selected module |
+| (b_ModulNbr) in to the first latch register and return |
+| the latched value. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_CounterValue : 32-Bit counter value |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev,
+ BYTE b_ModulNbr, PULONG pul_CounterValue)
+{
+ INT i_ReturnValue = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*********************/
+ /* Tatch the counter */
+ /*********************/
+
+ outl(1, devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulNbr));
+
+ /************************/
+ /* Read the latch value */
+ /************************/
+
+ *pul_CounterValue = inl(devpriv->s_BoardInfos.
+ ui_Address + 4 + (64 * b_ModulNbr));
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetIndexStatus (BYTE_ b_BoardHandle,|
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_IndexStatus)|
++----------------------------------------------------------------------------+
+| Task : Return the index status |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_IndexStatus : 0 : No INDEX occur |
+| 1 : A INDEX occur |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Index not initialised see function |
+| "i_APCI1710_InitIndex" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetIndexStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_IndexStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*****************************/
+ /* Test if index initialised */
+ /*****************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_IndexInit) {
+ dw_StatusReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (64 * b_ModulNbr));
+
+ *pb_IndexStatus = (BYTE) (dw_StatusReg & 1);
+ } else {
+ /*************************************************************/
+ /* Index not initialised see function "i_APCI1710_InitIndex" */
+ /*************************************************************/
+
+ DPRINTK("Index not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetReferenceStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_ReferenceStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the reference status |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_ReferenceStatus : 0 : No REFERENCE occur |
+| 1 : A REFERENCE occur |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Reference not initialised see function |
+| "i_APCI1710_InitReference" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_ReferenceStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*********************************/
+ /* Test if reference initialised */
+ /*********************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_ReferenceInit) {
+ dw_StatusReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 24 + (64 * b_ModulNbr));
+
+ *pb_ReferenceStatus =
+ (BYTE) (~dw_StatusReg & 1);
+ } else {
+ /*********************************************************************/
+ /* Reference not initialised see function "i_APCI1710_InitReference" */
+ /*********************************************************************/
+
+ DPRINTK("Reference not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetUASStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_UASStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the error signal (UAS) status |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_UASStatus : 0 : UAS is low "0" |
+| 1 : UAS is high "1" |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetUASStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_UASStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ dw_StatusReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 24 + (64 * b_ModulNbr));
+
+ *pb_UASStatus = (BYTE) ((dw_StatusReg >> 1) & 1);
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetCBStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_CBStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the counter overflow status |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_CBStatus : 0 : Counter no overflow |
+| 1 : Counter overflow |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetCBStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_CBStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ dw_StatusReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 16 + (64 * b_ModulNbr));
+
+ *pb_CBStatus = (BYTE) (dw_StatusReg & 1);
+
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_Get16BitCBStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_CBStatusCounter0, |
+| PBYTE_ pb_CBStatusCounter1) |
++----------------------------------------------------------------------------+
+| Task : Returns the counter overflow (counter initialised to |
+| 2*16-bit) status from selected incremental counter |
+| module |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_CBStatusCounter0 : 0 : No overflow occur for |
+| the first 16-bit |
+| counter |
+| 1 : Overflow occur for the|
+| first 16-bit counter |
+| PBYTE_ pb_CBStatusCounter1 : 0 : No overflow occur for |
+| the second 16-bit |
+| counter |
+| 1 : Overflow occur for the|
+| second 16-bit counter |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Counter not initialised to 2*16-bit mode. |
+| See function "i_APCI1710_InitCounter" |
+| -5: Firmware revision error |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0, PBYTE pb_CBStatusCounter1)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*************************/
+ /* Test if 2*16-Bit mode */
+ /*************************/
+
+ if ((devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister1 & 0x10) == 0x10) {
+ /*****************************/
+ /* Test the Firmware version */
+ /*****************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] & 0xFFFF) >=
+ 0x3136) {
+ dw_StatusReg =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 16 +
+ (64 * b_ModulNbr));
+
+ *pb_CBStatusCounter1 =
+ (BYTE) ((dw_StatusReg >> 0) &
+ 1);
+ *pb_CBStatusCounter0 =
+ (BYTE) ((dw_StatusReg >> 1) &
+ 1);
+ } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)
+ else {
+ /****************************/
+ /* Firmware revision error */
+ /****************************/
+
+ i_ReturnValue = -5;
+ } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136)
+ } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)
+ else {
+ /********************************************/
+ /* Counter not initialised to 2*16-bit mode */
+ /* "i_APCI1710_InitCounter" */
+ /********************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -4;
+ } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10)
+ } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)
+ else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1)
+ } // if (b_ModulNbr < 4)
+ else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ } // if (b_ModulNbr < 4)
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetUDStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_UDStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the counter progress status |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_UDStatus : 0 : Counter progress in the |
+| selected mode down |
+| 1 : Counter progress in the |
+| selected mode up |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetUDStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_UDStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ dw_StatusReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 24 + (64 * b_ModulNbr));
+
+ *pb_UDStatus = (BYTE) ((dw_StatusReg >> 2) & 1);
+
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetInterruptUDLatchedStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| PBYTE_ pb_UDStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the counter progress latched status after a |
+| index interrupt occur. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_UDStatus : 0 : Counter progress in the |
+| selected mode down |
+| 1 : Counter progress in the |
+| selected mode up |
+| 2 : No index interrupt occur |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: No counter module found |
+| -3: Counter not initialised see function |
+| "i_APCI1710_InitCounter" |
+| -4: Interrupt function not initialised. |
+| See function "i_APCI1710_SetBoardIntRoutineX" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev,
+ BYTE b_ModulNbr, PBYTE pb_UDStatus)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /*********************************/
+ /* Test if index interrupt occur */
+ /*********************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_IndexInterruptOccur == 1) {
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_IndexInterruptOccur = 0;
+
+ dw_StatusReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (64 * b_ModulNbr));
+
+ *pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 1);
+ } else {
+ /****************************/
+ /* No index interrupt occur */
+ /****************************/
+
+ *pb_UDStatus = 2;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : _INT_ i_APCI1710_ReadFrequencyMeasurement |
+ | (BYTE_ b_BoardHandle, |
+ | BYTE_ b_ModulNbr, |
+ | PBYTE_ pb_Status, |
+ | PULONG_ pul_ReadValue) |
+ +----------------------------------------------------------------------------+
+ | Task : Returns the status (pb_Status) and the number of |
+ | increments in the set time. |
+ | See function " i_APCI1710_InitFrequencyMeasurement " |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+ | BYTE_ b_ModulNbr : Number of the module to be |
+ | configured (0 to 3) |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : PBYTE_ pb_Status : Returns the frequency |
+ | measurement status |
+ | 0 : Counting cycle not |
+ | started. |
+ | 1 : Counting cycle started. |
+ | 2 : Counting cycle stopped. |
+ | The measurement cycle is |
+ | completed. |
+ | PBYTE_ pb_UDStatus : 0 : Counter progress in the |
+ | selected mode down |
+ | 1 : Counter progress in the |
+ | selected mode up |
+ | PULONG_ pul_ReadValue : Return the number of |
+ | increments in the defined |
+ | time base. |
+ +----------------------------------------------------------------------------+
+ | Return Value : 0: No error |
+ | -1: The handle parameter of the board is wrong |
+ | -2: The selected module number is wrong |
+ | -3: Counter not initialised see function |
+ | "i_APCI1710_InitCounter" |
+ | -4: Frequency measurement logic not initialised. |
+ | See function "i_APCI1710_InitFrequencyMeasurement" |
+ +----------------------------------------------------------------------------+
+ */
+
+INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ PBYTE pb_Status, PBYTE pb_UDStatus, PULONG pul_ReadValue)
+{
+ INT i_ReturnValue = 0;
+ UINT ui_16BitValue;
+ DWORD dw_StatusReg;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
+ /********************************************/
+ /* Test if frequency mesurement initialised */
+ /********************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.b_FrequencyMeasurementInit == 1) {
+ /******************/
+ /* Test if enable */
+ /******************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SiemensCounterInfo.
+ s_InitFlag.
+ b_FrequencyMeasurementEnable == 1) {
+ /*******************/
+ /* Read the status */
+ /*******************/
+
+ dw_StatusReg =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 32 +
+ (64 * b_ModulNbr));
+
+ /**************************/
+ /* Test if frequency stop */
+ /**************************/
+
+ if (dw_StatusReg & 1) {
+ *pb_Status = 2;
+ *pb_UDStatus =
+ (BYTE) ((dw_StatusReg >>
+ 1) & 3);
+
+ /******************/
+ /* Read the value */
+ /******************/
+
+ *pul_ReadValue =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 28 +
+ (64 * b_ModulNbr));
+
+ if (*pb_UDStatus == 0) {
+ /*************************/
+ /* Test the counter mode */
+ /*************************/
+
+ if ((devpriv->s_ModuleInfo[b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER) {
+ /****************************************/
+ /* Test if 16-bit counter 1 pulse occur */
+ /****************************************/
+
+ if ((*pul_ReadValue & 0xFFFFU) != 0) {
+ ui_16BitValue
+ =
+ (UINT)
+ *
+ pul_ReadValue
+ &
+ 0xFFFFU;
+ *pul_ReadValue
+ =
+ (*pul_ReadValue
+ &
+ 0xFFFF0000UL)
+ |
+ (0xFFFFU
+ -
+ ui_16BitValue);
+ }
+
+ /****************************************/
+ /* Test if 16-bit counter 2 pulse occur */
+ /****************************************/
+
+ if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
+ ui_16BitValue
+ =
+ (UINT)
+ (
+ (*pul_ReadValue
+ >>
+ 16)
+ &
+ 0xFFFFU);
+ *pul_ReadValue
+ =
+ (*pul_ReadValue
+ &
+ 0xFFFFUL)
+ |
+ (
+ (0xFFFFU - ui_16BitValue) << 16);
+ }
+ } else {
+ if (*pul_ReadValue != 0) {
+ *pul_ReadValue
+ =
+ 0xFFFFFFFFUL
+ -
+ *pul_ReadValue;
+ }
+ }
+ } else {
+ if (*pb_UDStatus == 1) {
+ /****************************************/
+ /* Test if 16-bit counter 2 pulse occur */
+ /****************************************/
+
+ if ((*pul_ReadValue & 0xFFFF0000UL) != 0) {
+ ui_16BitValue
+ =
+ (UINT)
+ (
+ (*pul_ReadValue
+ >>
+ 16)
+ &
+ 0xFFFFU);
+ *pul_ReadValue
+ =
+ (*pul_ReadValue
+ &
+ 0xFFFFUL)
+ |
+ (
+ (0xFFFFU - ui_16BitValue) << 16);
+ }
+ } else {
+ if (*pb_UDStatus
+ == 2) {
+ /****************************************/
+ /* Test if 16-bit counter 1 pulse occur */
+ /****************************************/
+
+ if ((*pul_ReadValue & 0xFFFFU) != 0) {
+ ui_16BitValue
+ =
+ (UINT)
+ *
+ pul_ReadValue
+ &
+ 0xFFFFU;
+ *pul_ReadValue
+ =
+ (*pul_ReadValue
+ &
+ 0xFFFF0000UL)
+ |
+ (0xFFFFU
+ -
+ ui_16BitValue);
+ }
+ }
+ }
+ }
+ } else {
+ *pb_Status = 1;
+ *pb_UDStatus = 0;
+ }
+ } else {
+ *pb_Status = 0;
+ *pb_UDStatus = 0;
+ }
+ } else {
+ /***********************************************/
+ /* Frequency measurement logic not initialised */
+ /***********************************************/
+
+ DPRINTK("Frequency measurement logic not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /****************************************/
+ /* Counter not initialised see function */
+ /* "i_APCI1710_InitCounter" */
+ /****************************************/
+
+ DPRINTK("Counter not initialised\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*************************************************/
+ /* The selected module number parameter is wrong */
+ /*************************************************/
+
+ DPRINTK("The selected module number parameter is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
new file mode 100644
index 000000000000..5153cf686658
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
@@ -0,0 +1,271 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_16BIT_COUNTER 0x10
+#define APCI1710_32BIT_COUNTER 0x0
+#define APCI1710_QUADRUPLE_MODE 0x0
+#define APCI1710_DOUBLE_MODE 0x3
+#define APCI1710_SIMPLE_MODE 0xF
+#define APCI1710_DIRECT_MODE 0x80
+#define APCI1710_HYSTERESIS_ON 0x60
+#define APCI1710_HYSTERESIS_OFF 0x0
+#define APCI1710_INCREMENT 0x60
+#define APCI1710_DECREMENT 0x0
+#define APCI1710_LATCH_COUNTER 0x1
+#define APCI1710_CLEAR_COUNTER 0x0
+#define APCI1710_LOW 0x0
+#define APCI1710_HIGH 0x1
+
+/*********************/
+/* Version 0600-0229 */
+/*********************/
+#define APCI1710_HIGH_EDGE_CLEAR_COUNTER 0x0
+#define APCI1710_HIGH_EDGE_LATCH_COUNTER 0x1
+#define APCI1710_LOW_EDGE_CLEAR_COUNTER 0x2
+#define APCI1710_LOW_EDGE_LATCH_COUNTER 0x3
+#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER 0x4
+#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER 0x5
+#define APCI1710_SOURCE_0 0x0
+#define APCI1710_SOURCE_1 0x1
+
+#define APCI1710_30MHZ 30
+#define APCI1710_33MHZ 33
+#define APCI1710_40MHZ 40
+
+#define APCI1710_ENABLE_LATCH_INT 0x80
+#define APCI1710_DISABLE_LATCH_INT (~APCI1710_ENABLE_LATCH_INT)
+
+#define APCI1710_INDEX_LATCH_COUNTER 0x10
+#define APCI1710_INDEX_AUTO_MODE 0x8
+#define APCI1710_ENABLE_INDEX 0x4
+#define APCI1710_DISABLE_INDEX (~APCI1710_ENABLE_INDEX)
+#define APCI1710_ENABLE_LATCH_AND_CLEAR 0x8
+#define APCI1710_DISABLE_LATCH_AND_CLEAR (~APCI1710_ENABLE_LATCH_AND_CLEAR)
+#define APCI1710_SET_LOW_INDEX_LEVEL 0x4
+#define APCI1710_SET_HIGH_INDEX_LEVEL (~APCI1710_SET_LOW_INDEX_LEVEL)
+#define APCI1710_INVERT_INDEX_RFERENCE 0x2
+#define APCI1710_DEFAULT_INDEX_RFERENCE (~APCI1710_INVERT_INDEX_RFERENCE)
+
+#define APCI1710_ENABLE_INDEX_INT 0x1
+#define APCI1710_DISABLE_INDEX_INT (~APCI1710_ENABLE_INDEX_INT)
+
+#define APCI1710_ENABLE_FREQUENCY 0x4
+#define APCI1710_DISABLE_FREQUENCY (~APCI1710_ENABLE_FREQUENCY)
+
+#define APCI1710_ENABLE_FREQUENCY_INT 0x8
+#define APCI1710_DISABLE_FREQUENCY_INT (~APCI1710_ENABLE_FREQUENCY_INT)
+
+#define APCI1710_ENABLE_40MHZ_FREQUENCY 0x40
+#define APCI1710_DISABLE_40MHZ_FREQUENCY (~APCI1710_ENABLE_40MHZ_FREQUENCY)
+
+#define APCI1710_ENABLE_40MHZ_FILTER 0x80
+#define APCI1710_DISABLE_40MHZ_FILTER (~APCI1710_ENABLE_40MHZ_FILTER)
+
+#define APCI1710_ENABLE_COMPARE_INT 0x2
+#define APCI1710_DISABLE_COMPARE_INT (~APCI1710_ENABLE_COMPARE_INT)
+
+#define APCI1710_ENABLE_INDEX_ACTION 0x20
+#define APCI1710_DISABLE_INDEX_ACTION (~APCI1710_ENABLE_INDEX_ACTION)
+#define APCI1710_REFERENCE_HIGH 0x40
+#define APCI1710_REFERENCE_LOW (~APCI1710_REFERENCE_HIGH)
+
+#define APCI1710_TOR_GATE_LOW 0x40
+#define APCI1710_TOR_GATE_HIGH (~APCI1710_TOR_GATE_LOW)
+
+/* INSN CONFIG */
+#define APCI1710_INCCPT_INITCOUNTER 100
+#define APCI1710_INCCPT_COUNTERAUTOTEST 101
+#define APCI1710_INCCPT_INITINDEX 102
+#define APCI1710_INCCPT_INITREFERENCE 103
+#define APCI1710_INCCPT_INITEXTERNALSTROBE 104
+#define APCI1710_INCCPT_INITCOMPARELOGIC 105
+#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT 106
+
+/* INSN READ */
+#define APCI1710_INCCPT_READLATCHREGISTERSTATUS 200
+#define APCI1710_INCCPT_READLATCHREGISTERVALUE 201
+#define APCI1710_INCCPT_READ16BITCOUNTERVALUE 202
+#define APCI1710_INCCPT_READ32BITCOUNTERVALUE 203
+#define APCI1710_INCCPT_GETINDEXSTATUS 204
+#define APCI1710_INCCPT_GETREFERENCESTATUS 205
+#define APCI1710_INCCPT_GETUASSTATUS 206
+#define APCI1710_INCCPT_GETCBSTATUS 207
+#define APCI1710_INCCPT_GET16BITCBSTATUS 208
+#define APCI1710_INCCPT_GETUDSTATUS 209
+#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS 210
+#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT 211
+#define APCI1710_INCCPT_READINTERRUPT 212
+
+/* INSN BITS */
+#define APCI1710_INCCPT_CLEARCOUNTERVALUE 300
+#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE 301
+#define APCI1710_INCCPT_SETINPUTFILTER 302
+#define APCI1710_INCCPT_LATCHCOUNTER 303
+#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE 304
+#define APCI1710_INCCPT_SETDIGITALCHLON 305
+#define APCI1710_INCCPT_SETDIGITALCHLOFF 306
+
+/* INSN WRITE */
+#define APCI1710_INCCPT_ENABLELATCHINTERRUPT 400
+#define APCI1710_INCCPT_DISABLELATCHINTERRUPT 401
+#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE 402
+#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE 403
+#define APCI1710_INCCPT_ENABLEINDEX 404
+#define APCI1710_INCCPT_DISABLEINDEX 405
+#define APCI1710_INCCPT_ENABLECOMPARELOGIC 406
+#define APCI1710_INCCPT_DISABLECOMPARELOGIC 407
+#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT 408
+#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT 409
+
+/************ Main Functions *************/
+INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int * data);
+
+INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ struct comedi_insn *insn, unsigned int * data);
+
+INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ struct comedi_insn *insn, unsigned int * data);
+
+INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
+ struct comedi_insn *insn, unsigned int * data);
+
+/*********** Supplementary Functions********/
+
+/* INSN CONFIG */
+INT i_APCI1710_InitCounter(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_CounterRange,
+ BYTE b_FirstCounterModus,
+ BYTE b_FirstCounterOption,
+ BYTE b_SecondCounterModus,
+ BYTE b_SecondCounterOption);
+
+INT i_APCI1710_CounterAutoTest(struct comedi_device *dev, PBYTE pb_TestStatus);
+
+INT i_APCI1710_InitIndex(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_ReferenceAction,
+ BYTE b_IndexOperation, BYTE b_AutoMode,
+ BYTE b_InterruptEnable);
+
+INT i_APCI1710_InitReference(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_ReferenceLevel);
+
+INT i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_ExternalStrobe,
+ BYTE b_ExternalStrobeLevel);
+
+INT i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+ BYTE b_ModulNbr, UINT ui_CompareValue);
+
+INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_PCIInputClock,
+ BYTE b_TimingUnity,
+ ULONG ul_TimingInterval,
+ PULONG pul_RealTimingInterval);
+
+/* INSN BITS */
+INT i_APCI1710_ClearCounterValue(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_ClearAllCounterValue(struct comedi_device *dev);
+
+INT i_APCI1710_SetInputFilter(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_PCIInputClock,
+ BYTE b_Filter);
+
+INT i_APCI1710_LatchCounter(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_LatchReg);
+
+INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_SourceSelection);
+
+INT i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, BYTE b_ModulNbr);
+
+/* INSN WRITE */
+INT i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_SelectedCounter,
+ UINT ui_WriteValue);
+
+INT i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+ BYTE b_ModulNbr, ULONG ul_WriteValue);
+
+INT i_APCI1710_EnableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_DisableIndex(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_EnableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_DisableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr);
+
+INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_InterruptEnable);
+
+INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
+ BYTE b_ModulNbr);
+
+/* INSN READ */
+INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_LatchReg,
+ PBYTE pb_LatchStatus);
+
+INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_LatchReg,
+ PULONG pul_LatchValue);
+
+INT i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+ BYTE b_ModulNbr, BYTE b_SelectedCounter,
+ PUINT pui_CounterValue);
+
+INT i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+ BYTE b_ModulNbr, PULONG pul_CounterValue);
+
+INT i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_IndexStatus);
+
+INT i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_ReferenceStatus);
+
+INT i_APCI1710_GetUASStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_UASStatus);
+
+INT i_APCI1710_GetCBStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_CBStatus);
+
+INT i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0,
+ PBYTE pb_CBStatusCounter1);
+
+INT i_APCI1710_GetUDStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_UDStatus);
+
+INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+ BYTE b_ModulNbr, PBYTE pb_UDStatus);
+
+INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ PBYTE pb_Status, PBYTE pb_UDStatus,
+ PULONG pul_ReadValue);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
new file mode 100644
index 000000000000..3ac6a264ef54
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
@@ -0,0 +1,861 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : Inp_CPT.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 pulse encoder module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ |----------|-----------|------------------------------------------------|
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Inp_cpt.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitPulseEncoder |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PulseEncoderNbr, |
+| BYTE_ b_InputLevelSelection, |
+| BYTE_ b_TriggerOutputAction, |
+| ULONG_ ul_StartValue) |
++----------------------------------------------------------------------------+
+| Task : Configure the pulse encoder operating mode selected via|
+| b_ModulNbr and b_PulseEncoderNbr. The pulse encoder |
+| after each pulse decrement the counter value from 1. |
+| |
+| You must calling this function be for you call any |
+| other function witch access of pulse encoders. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
+| BYTE_ b_PulseEncoderNbr : Pulse encoder selection |
+| (0 to 3) |
+| BYTE_ b_InputLevelSelection : Input level selection |
+| (0 or 1) |
+| 0 : Set pulse encoder|
+| count the the low|
+| level pulse. |
+| 1 : Set pulse encoder|
+| count the the |
+| high level pulse.|
+| BYTE_ b_TriggerOutputAction : Digital TRIGGER output |
+| action |
+| 0 : No action |
+| 1 : Set the trigger |
+| output to "1" |
+| (high) after the |
+| passage from 1 to|
+| 0 from pulse |
+| encoder. |
+| 2 : Set the trigger |
+| output to "0" |
+| (low) after the |
+| passage from 1 to|
+| 0 from pulse |
+| encoder |
+| ULONG_ ul_StartValue : Pulse encoder start value|
+| (1 to 4294967295)
+ b_ModulNbr =(BYTE) CR_AREF(insn->chanspec);
+ b_PulseEncoderNbr =(BYTE) data[0];
+ b_InputLevelSelection =(BYTE) data[1];
+ b_TriggerOutputAction =(BYTE) data[2];
+ ul_StartValue =(ULONG) data[3];
+ |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module is not a pulse encoder module |
+| -3: Pulse encoder selection is wrong |
+| -4: Input level selection is wrong |
+| -5: Digital TRIGGER output action selection is wrong |
+| -6: Pulse encoder start value is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_IntRegister;
+
+ BYTE b_ModulNbr;
+ BYTE b_PulseEncoderNbr;
+ BYTE b_InputLevelSelection;
+ BYTE b_TriggerOutputAction;
+ ULONG ul_StartValue;
+
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_PulseEncoderNbr = (BYTE) data[0];
+ b_InputLevelSelection = (BYTE) data[1];
+ b_TriggerOutputAction = (BYTE) data[2];
+ ul_StartValue = (ULONG) data[3];
+
+ i_ReturnValue = insn->n;
+
+ /***********************************/
+ /* Test the selected module number */
+ /***********************************/
+
+ if (b_ModulNbr <= 3) {
+ /*************************/
+ /* Test if pulse encoder */
+ /*************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ APCI1710_PULSE_ENCODER) ==
+ APCI1710_PULSE_ENCODER) {
+ /******************************************/
+ /* Test the selected pulse encoder number */
+ /******************************************/
+
+ if (b_PulseEncoderNbr <= 3) {
+ /************************/
+ /* Test the input level */
+ /************************/
+
+ if ((b_InputLevelSelection == 0)
+ || (b_InputLevelSelection == 1)) {
+ /*******************************************/
+ /* Test the ouput TRIGGER action selection */
+ /*******************************************/
+
+ if ((b_TriggerOutputAction <= 2)
+ || (b_PulseEncoderNbr > 0)) {
+ if (ul_StartValue > 1) {
+
+ dw_IntRegister =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address +
+ 20 +
+ (64 * b_ModulNbr));
+
+ /***********************/
+ /* Set the start value */
+ /***********************/
+
+ outl(ul_StartValue,
+ devpriv->
+ s_BoardInfos.
+ ui_Address +
+ (b_PulseEncoderNbr
+ * 4) +
+ (64 * b_ModulNbr));
+
+ /***********************/
+ /* Set the input level */
+ /***********************/
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister =
+ (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister &
+ (0xFFFFFFFFUL -
+ (1UL << (8 + b_PulseEncoderNbr)))) | ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr));
+
+ /*******************************/
+ /* Test if output trigger used */
+ /*******************************/
+
+ if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1)) {
+ /****************************/
+ /* Enable the output action */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ | (1UL
+ << (4 + b_PulseEncoderNbr));
+
+ /*********************************/
+ /* Set the output TRIGGER action */
+ /*********************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ =
+ (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ &
+ (0xFFFFFFFFUL
+ -
+ (1UL << (12 + b_PulseEncoderNbr)))) | ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr));
+ } else {
+ /*****************************/
+ /* Disable the output action */
+ /*****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ &
+ (0xFFFFFFFFUL
+ -
+ (1UL << (4 + b_PulseEncoderNbr)));
+ }
+
+ /*************************/
+ /* Set the configuration */
+ /*************************/
+
+ outl(devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister,
+ devpriv->
+ s_BoardInfos.
+ ui_Address +
+ 20 +
+ (64 * b_ModulNbr));
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ s_PulseEncoderInfo
+ [b_PulseEncoderNbr].
+ b_PulseEncoderInit
+ = 1;
+ } else {
+ /**************************************/
+ /* Pulse encoder start value is wrong */
+ /**************************************/
+
+ DPRINTK("Pulse encoder start value is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /****************************************************/
+ /* Digital TRIGGER output action selection is wrong */
+ /****************************************************/
+
+ DPRINTK("Digital TRIGGER output action selection is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /**********************************/
+ /* Input level selection is wrong */
+ /**********************************/
+
+ DPRINTK("Input level selection is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /************************************/
+ /* Pulse encoder selection is wrong */
+ /************************************/
+
+ DPRINTK("Pulse encoder selection is wrong\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /********************************************/
+ /* The module is not a pulse encoder module */
+ /********************************************/
+
+ DPRINTK("The module is not a pulse encoder module\n");
+ i_ReturnValue = -2;
+ }
+ } else {
+ /********************************************/
+ /* The module is not a pulse encoder module */
+ /********************************************/
+
+ DPRINTK("The module is not a pulse encoder module\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnablePulseEncoder |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PulseEncoderNbr, |
+| BYTE_ b_CycleSelection, |
+| BYTE_ b_InterruptHandling) |
++----------------------------------------------------------------------------+
+| Task : Enableor disable the selected pulse encoder (b_PulseEncoderNbr) |
+| from selected module (b_ModulNbr). Each input pulse |
+| decrement the pulse encoder counter value from 1. |
+| If you enabled the interrupt (b_InterruptHandling), a |
+| interrupt is generated when the pulse encoder has run |
+| down. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
+| BYTE_ b_PulseEncoderNbr : Pulse encoder selection |
+| (0 to 3) |
+| BYTE_ b_CycleSelection : APCI1710_CONTINUOUS: |
+| Each time the |
+| counting value is set|
+| on "0", the pulse |
+| encoder load the |
+| start value after |
+| the next pulse. |
+| APCI1710_SINGLE: |
+| If the counter is set|
+| on "0", the pulse |
+| encoder is stopped. |
+| BYTE_ b_InterruptHandling : Interrupts can be |
+| generated, when the pulse|
+| encoder has run down. |
+| With this parameter the |
+| user decides if |
+| interrupts are used or |
+| not. |
+| APCI1710_ENABLE: |
+| Interrupts are enabled |
+| APCI1710_DISABLE: |
+| Interrupts are disabled
+
+ b_ModulNbr =(BYTE) CR_AREF(insn->chanspec);
+ b_Action =(BYTE) data[0];
+ b_PulseEncoderNbr =(BYTE) data[1];
+ b_CycleSelection =(BYTE) data[2];
+ b_InterruptHandling =(BYTE) data[3];|
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection is wrong |
+| -3: Pulse encoder selection is wrong |
+| -4: Pulse encoder not initialised. |
+| See function "i_APCI1710_InitPulseEncoder" |
+| -5: Cycle selection mode is wrong |
+| -6: Interrupt handling mode is wrong |
+| -7: Interrupt routine not installed. |
+| See function "i_APCI1710_SetBoardIntRoutineX" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ BYTE b_ModulNbr;
+ BYTE b_PulseEncoderNbr;
+ BYTE b_CycleSelection;
+ BYTE b_InterruptHandling;
+ BYTE b_Action;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_Action = (BYTE) data[0];
+ b_PulseEncoderNbr = (BYTE) data[1];
+ b_CycleSelection = (BYTE) data[2];
+ b_InterruptHandling = (BYTE) data[3];
+
+ /***********************************/
+ /* Test the selected module number */
+ /***********************************/
+
+ if (b_ModulNbr <= 3) {
+ /******************************************/
+ /* Test the selected pulse encoder number */
+ /******************************************/
+
+ if (b_PulseEncoderNbr <= 3) {
+ /*************************************/
+ /* Test if pulse encoder initialised */
+ /*************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ s_PulseEncoderInfo[b_PulseEncoderNbr].
+ b_PulseEncoderInit == 1) {
+ switch (b_Action) {
+
+ case APCI1710_ENABLE:
+ /****************************/
+ /* Test the cycle selection */
+ /****************************/
+
+ if (b_CycleSelection ==
+ APCI1710_CONTINUOUS
+ || b_CycleSelection ==
+ APCI1710_SINGLE) {
+ /*******************************/
+ /* Test the interrupt handling */
+ /*******************************/
+
+ if (b_InterruptHandling ==
+ APCI1710_ENABLE
+ || b_InterruptHandling
+ == APCI1710_DISABLE) {
+ /******************************/
+ /* Test if interrupt not used */
+ /******************************/
+
+ if (b_InterruptHandling
+ ==
+ APCI1710_DISABLE)
+ {
+ /*************************/
+ /* Disable the interrupt */
+ /*************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ &
+ (0xFFFFFFFFUL
+ -
+ (1UL << b_PulseEncoderNbr));
+ } else {
+
+ /************************/
+ /* Enable the interrupt */
+ /************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister
+ | (1UL
+ <<
+ b_PulseEncoderNbr);
+ devpriv->tsk_Current = current; // Save the current process task structure
+
+ }
+
+ if (i_ReturnValue >= 0) {
+ /***********************************/
+ /* Enable or disable the interrupt */
+ /***********************************/
+
+ outl(devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_SetRegister,
+ devpriv->
+ s_BoardInfos.
+ ui_Address
+ + 20 +
+ (64 * b_ModulNbr));
+
+ /****************************/
+ /* Enable the pulse encoder */
+ /****************************/
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister
+ =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister
+ | (1UL
+ <<
+ b_PulseEncoderNbr);
+
+ /**********************/
+ /* Set the cycle mode */
+ /**********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister
+ =
+ (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister
+ &
+ (0xFFFFFFFFUL
+ -
+ (1 << (b_PulseEncoderNbr + 4)))) | ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr));
+
+ /****************************/
+ /* Enable the pulse encoder */
+ /****************************/
+
+ outl(devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister,
+ devpriv->
+ s_BoardInfos.
+ ui_Address
+ + 16 +
+ (64 * b_ModulNbr));
+ }
+ } else {
+ /************************************/
+ /* Interrupt handling mode is wrong */
+ /************************************/
+
+ DPRINTK("Interrupt handling mode is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /*********************************/
+ /* Cycle selection mode is wrong */
+ /*********************************/
+
+ DPRINTK("Cycle selection mode is wrong\n");
+ i_ReturnValue = -5;
+ }
+ break;
+
+ case APCI1710_DISABLE:
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister =
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister &
+ (0xFFFFFFFFUL -
+ (1UL << b_PulseEncoderNbr));
+
+ /*****************************/
+ /* Disable the pulse encoder */
+ /*****************************/
+
+ outl(devpriv->s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_ControlRegister,
+ devpriv->s_BoardInfos.
+ ui_Address + 16 +
+ (64 * b_ModulNbr));
+
+ break;
+ } // switch End
+
+ } else {
+ /*********************************/
+ /* Pulse encoder not initialised */
+ /*********************************/
+
+ DPRINTK("Pulse encoder not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /************************************/
+ /* Pulse encoder selection is wrong */
+ /************************************/
+
+ DPRINTK("Pulse encoder selection is wrong\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*****************************/
+ /* Module selection is wrong */
+ /*****************************/
+
+ DPRINTK("Module selection is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadPulseEncoderStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PulseEncoderNbr, |
+| PBYTE_ pb_Status) |
++----------------------------------------------------------------------------+
+| Task APCI1710_PULSEENCODER_READ : Reads the pulse encoder status
+ and valuefrom selected pulse |
+| encoder (b_PulseEncoderNbr) from selected module |
+| (b_ModulNbr). |
++----------------------------------------------------------------------------+
+ BYTE b_Type; data[0]
+ APCI1710_PULSEENCODER_WRITE
+ Writes a 32-bit value (ul_WriteValue) into the selected|
+| pulse encoder (b_PulseEncoderNbr) from selected module |
+| (b_ModulNbr). This operation set the new start pulse |
+| encoder value.
+ APCI1710_PULSEENCODER_READ
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| CRAREF() BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
+| data[1] BYTE_ b_PulseEncoderNbr : Pulse encoder selection |
+| (0 to 3)
+ APCI1710_PULSEENCODER_WRITE
+ data[2] ULONG_ ul_WriteValue : 32-bit value to be |
+| written |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_Status : Pulse encoder status. |
+| 0 : No overflow occur|
+| 1 : Overflow occur
+ PULONG_ pul_ReadValue : Pulse encoder value | |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection is wrong |
+| -3: Pulse encoder selection is wrong |
+| -4: Pulse encoder not initialised. |
+| See function "i_APCI1710_InitPulseEncoder" |
++----------------------------------------------------------------------------+
+*/
+
+/*_INT_ i_APCI1710_ReadPulseEncoderStatus (BYTE_ b_BoardHandle,
+ BYTE_ b_ModulNbr,
+ BYTE_ b_PulseEncoderNbr,
+
+ PBYTE_ pb_Status)
+ */
+INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusRegister;
+ BYTE b_ModulNbr;
+ BYTE b_PulseEncoderNbr;
+ PBYTE pb_Status;
+ BYTE b_Type;
+ PULONG pul_ReadValue;
+ ULONG ul_WriteValue;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_Type = (BYTE) data[0];
+ b_PulseEncoderNbr = (BYTE) data[1];
+ pb_Status = (PBYTE) & data[0];
+ pul_ReadValue = (PULONG) & data[1];
+
+ /***********************************/
+ /* Test the selected module number */
+ /***********************************/
+
+ if (b_ModulNbr <= 3) {
+ /******************************************/
+ /* Test the selected pulse encoder number */
+ /******************************************/
+
+ if (b_PulseEncoderNbr <= 3) {
+ /*************************************/
+ /* Test if pulse encoder initialised */
+ /*************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ s_PulseEncoderInfo[b_PulseEncoderNbr].
+ b_PulseEncoderInit == 1) {
+
+ switch (b_Type) {
+ case APCI1710_PULSEENCODER_READ:
+ /****************************/
+ /* Read the status register */
+ /****************************/
+
+ dw_StatusRegister =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 16 +
+ (64 * b_ModulNbr));
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_StatusRegister = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_StatusRegister |
+ dw_StatusRegister;
+
+ *pb_Status =
+ (BYTE) (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_StatusRegister >> (1 +
+ b_PulseEncoderNbr)) & 1;
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_StatusRegister =
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_PulseEncoderModuleInfo.
+ dw_StatusRegister &
+ (0xFFFFFFFFUL - (1 << (1 +
+ b_PulseEncoderNbr)));
+
+ /******************/
+ /* Read the value */
+ /******************/
+
+ *pul_ReadValue =
+ inl(devpriv->s_BoardInfos.
+ ui_Address +
+ (4 * b_PulseEncoderNbr) +
+ (64 * b_ModulNbr));
+ break;
+
+ case APCI1710_PULSEENCODER_WRITE:
+ ul_WriteValue = (ULONG) data[2];
+ /*******************/
+ /* Write the value */
+ /*******************/
+
+ outl(ul_WriteValue,
+ devpriv->s_BoardInfos.
+ ui_Address +
+ (4 * b_PulseEncoderNbr) +
+ (64 * b_ModulNbr));
+
+ } //end of switch
+ } else {
+ /*********************************/
+ /* Pulse encoder not initialised */
+ /*********************************/
+
+ DPRINTK("Pulse encoder not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /************************************/
+ /* Pulse encoder selection is wrong */
+ /************************************/
+
+ DPRINTK("Pulse encoder selection is wrong\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*****************************/
+ /* Module selection is wrong */
+ /*****************************/
+
+ DPRINTK("Module selection is wrong\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+
+ data[0] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].b_OldModuleMask;
+ data[1] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+ data[2] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+ /***************************/
+ /* Increment the read FIFO */
+ /***************************/
+
+ devpriv->s_InterruptParameters.
+ ui_Read = (devpriv->
+ s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+ return insn->n;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
new file mode 100644
index 000000000000..28252873e862
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_SINGLE 0
+#define APCI1710_CONTINUOUS 1
+
+#define APCI1710_PULSEENCODER_READ 0
+#define APCI1710_PULSEENCODER_WRITE 1
+
+INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+/*
+ * READ PULSE ENCODER FUNCTIONS
+ */
+INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+/*
+ * WRITE PULSE ENCODER FUNCTIONS
+ */
+INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
new file mode 100644
index 000000000000..5ddd092a656a
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
@@ -0,0 +1,3588 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : PWM.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 Wulse wide modulation module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +-----------------------------------------------------------------------+
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Pwm.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name :INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev,
+struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Pwm Init and Get Pwm Initialisation |
++----------------------------------------------------------------------------+
+| Input Parameters :
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_ConfigType;
+ INT i_ReturnValue = 0;
+ b_ConfigType = CR_CHAN(insn->chanspec);
+
+ switch (b_ConfigType) {
+ case APCI1710_PWM_INIT:
+ i_ReturnValue = i_APCI1710_InitPWM(dev, (BYTE) CR_AREF(insn->chanspec), // b_ModulNbr
+ (BYTE) data[0], //b_PWM
+ (BYTE) data[1], // b_ClockSelection
+ (BYTE) data[2], // b_TimingUnit
+ (ULONG) data[3], //ul_LowTiming
+ (ULONG) data[4], //ul_HighTiming
+ (PULONG) & data[0], //pul_RealLowTiming
+ (PULONG) & data[1] //pul_RealHighTiming
+ );
+ break;
+
+ case APCI1710_PWM_GETINITDATA:
+ i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (BYTE) CR_AREF(insn->chanspec), // b_ModulNbr
+ (BYTE) data[0], //b_PWM
+ (PBYTE) & data[0], //pb_TimingUnit
+ (PULONG) & data[1], //pul_LowTiming
+ (PULONG) & data[2], //pul_HighTiming
+ (PBYTE) & data[3], // pb_StartLevel
+ (PBYTE) & data[4], // pb_StopMode
+ (PBYTE) & data[5], // pb_StopLevel
+ (PBYTE) & data[6], // pb_ExternGate
+ (PBYTE) & data[7], // pb_InterruptEnable
+ (PBYTE) & data[8] // pb_Enable
+ );
+ break;
+
+ default:
+ printk(" Config Parameter Wrong\n");
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitPWM |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PWM, |
+| BYTE_ b_ClockSelection, |
+| BYTE_ b_TimingUnit, |
+| ULONG_ ul_LowTiming, |
+| ULONG_ ul_HighTiming, |
+| PULONG_ pul_RealLowTiming, |
+| PULONG_ pul_RealHighTiming) |
++----------------------------------------------------------------------------+
+| Task : Configure the selected PWM (b_PWM) from selected module|
+| (b_ModulNbr). The ul_LowTiming, ul_HighTiming and |
+| ul_TimingUnit determine the low/high timing base for |
+| the period. pul_RealLowTiming, pul_RealHighTiming |
+| return the real timing value. |
+| You must calling this function be for you call any |
+| other function witch access of the PWM. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure|
+| (0 to 3) |
+| BYTE_ b_PWM : Selected PWM (0 or 1). |
+| BYTE_ b_ClockSelection : Selection from PCI bus |
+| clock |
+| - APCI1710_30MHZ : |
+| The PC have a 30 MHz |
+| PCI bus clock |
+| - APCI1710_33MHZ : |
+| The PC have a 33 MHz |
+| PCI bus clock |
+| - APCI1710_40MHZ |
+| The APCI-1710 have a |
+| integrated 40Mhz |
+| quartz. |
+| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) |
+| 0 : ns |
+| 1 : æs |
+| 2 : ms |
+| 3 : s |
+| 4 : mn |
+| ULONG_ ul_LowTiming : Low base timing value. |
+| ULONG_ ul_HighTiming : High base timing value. |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_RealLowTiming : Real low base timing |
+| value. |
+| PULONG_ pul_RealHighTiming : Real high base timing |
+| value. |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a PWM module |
+| -4: PWM selection is wrong |
+| -5: The selected input clock is wrong |
+| -6: Timing Unit selection is wrong |
+| -7: Low base timing selection is wrong |
+| -8: High base timing selection is wrong |
+| -9: You can not used the 40MHz clock selection with |
+| this board |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InitPWM(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM,
+ BYTE b_ClockSelection,
+ BYTE b_TimingUnit,
+ ULONG ul_LowTiming,
+ ULONG ul_HighTiming,
+ PULONG pul_RealLowTiming, PULONG pul_RealHighTiming)
+{
+ INT i_ReturnValue = 0;
+ ULONG ul_LowTimerValue = 0;
+ ULONG ul_HighTimerValue = 0;
+ DWORD dw_Command;
+ double d_RealLowTiming = 0;
+ double d_RealHighTiming = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***************/
+ /* Test if PWM */
+ /***************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_PWM) {
+ /**************************/
+ /* Test the PWM selection */
+ /**************************/
+
+ if (b_PWM <= 1) {
+ /******************/
+ /* Test the clock */
+ /******************/
+
+ if ((b_ClockSelection == APCI1710_30MHZ) ||
+ (b_ClockSelection == APCI1710_33MHZ) ||
+ (b_ClockSelection == APCI1710_40MHZ)) {
+ /************************/
+ /* Test the timing unit */
+ /************************/
+
+ if (b_TimingUnit <= 4) {
+ /*********************************/
+ /* Test the low timing selection */
+ /*********************************/
+
+ if (((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 0)
+ && (ul_LowTiming
+ >= 266)
+ && (ul_LowTiming
+ <=
+ 0xFFFFFFFFUL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 1)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 571230650UL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 2)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 571230UL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 3)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 571UL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 4)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <= 9UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 0)
+ && (ul_LowTiming
+ >= 242)
+ && (ul_LowTiming
+ <=
+ 0xFFFFFFFFUL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 1)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 519691043UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 2)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 519691UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 3)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 520UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 4)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <= 8UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 0)
+ && (ul_LowTiming
+ >= 200)
+ && (ul_LowTiming
+ <=
+ 0xFFFFFFFFUL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 1)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 429496729UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 2)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 429496UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 3)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 429UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 4)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 7UL))) {
+ /**********************************/
+ /* Test the High timing selection */
+ /**********************************/
+
+ if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
+ /**************************/
+ /* Test the board version */
+ /**************************/
+
+ if (((b_ClockSelection == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_ClockSelection != APCI1710_40MHZ)) {
+
+ /************************************/
+ /* Calculate the low division fator */
+ /************************************/
+
+ fpu_begin
+ ();
+
+ switch (b_TimingUnit) {
+ /******/
+ /* ns */
+ /******/
+
+ case 0:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (ul_LowTiming
+ *
+ (0.00025 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (0.00025 * (double)b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (0.00025
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+ *pul_RealLowTiming
+ =
+ *pul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* æs */
+ /******/
+
+ case 1:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (ul_LowTiming
+ *
+ (0.25 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (0.25 * (double)b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (
+ (double)
+ 0.25
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+ *pul_RealLowTiming
+ =
+ *pul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* ms */
+ /******/
+
+ case 2:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ ul_LowTiming
+ *
+ (250.0
+ *
+ b_ClockSelection);
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (250.0 * (double)b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (250.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+ *pul_RealLowTiming
+ =
+ *pul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /*****/
+ /* s */
+ /*****/
+
+ case 3:
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (ul_LowTiming
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+ *pul_RealLowTiming
+ =
+ *pul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* mn */
+ /******/
+
+ case 4:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (ul_LowTiming
+ *
+ 60)
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60;
+ d_RealLowTiming
+ =
+ (
+ (double)
+ ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60.0;
+
+ if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealLowTiming + 0.5)) {
+ *pul_RealLowTiming
+ =
+ *pul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+ }
+
+ /*************************************/
+ /* Calculate the high division fator */
+ /*************************************/
+
+ switch (b_TimingUnit) {
+ /******/
+ /* ns */
+ /******/
+
+ case 0:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (ul_HighTiming
+ *
+ (0.00025 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (0.00025 * (double)b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (0.00025
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+ *pul_RealHighTiming
+ =
+ *pul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* æs */
+ /******/
+
+ case 1:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (ul_HighTiming
+ *
+ (0.25 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (0.25 * (double)b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (
+ (double)
+ 0.25
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+ *pul_RealHighTiming
+ =
+ *pul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* ms */
+ /******/
+
+ case 2:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ ul_HighTiming
+ *
+ (250.0
+ *
+ b_ClockSelection);
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (250.0 * (double)b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (250.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+ *pul_RealHighTiming
+ =
+ *pul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /*****/
+ /* s */
+ /*****/
+
+ case 3:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (ul_HighTiming
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+ *pul_RealHighTiming
+ =
+ *pul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* mn */
+ /******/
+
+ case 4:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (ul_HighTiming
+ *
+ 60)
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ *pul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60;
+ d_RealHighTiming
+ =
+ (
+ (double)
+ ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60.0;
+
+ if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealHighTiming + 0.5)) {
+ *pul_RealHighTiming
+ =
+ *pul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+ }
+
+ fpu_end();
+ /****************************/
+ /* Save the clock selection */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ b_ClockSelection
+ =
+ b_ClockSelection;
+
+ /************************/
+ /* Save the timing unit */
+ /************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ b_TimingUnit
+ =
+ b_TimingUnit;
+
+ /****************************/
+ /* Save the low base timing */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ d_LowTiming
+ =
+ d_RealLowTiming;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ ul_RealLowTiming
+ =
+ *pul_RealLowTiming;
+
+ /****************************/
+ /* Save the high base timing */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ d_HighTiming
+ =
+ d_RealHighTiming;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ ul_RealHighTiming
+ =
+ *pul_RealHighTiming;
+
+ /************************/
+ /* Write the low timing */
+ /************************/
+
+ outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+ /*************************/
+ /* Write the high timing */
+ /*************************/
+
+ outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+ /***************************/
+ /* Set the clock selection */
+ /***************************/
+
+ dw_Command
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 8
+ +
+ (20 * b_PWM) + (64 * b_ModulNbr));
+
+ dw_Command
+ =
+ dw_Command
+ &
+ 0x7F;
+
+ if (b_ClockSelection == APCI1710_40MHZ) {
+ dw_Command
+ =
+ dw_Command
+ |
+ 0x80;
+ }
+
+ /***************************/
+ /* Set the clock selection */
+ /***************************/
+
+ outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+ /*************/
+ /* PWM init. */
+ /*************/
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ b_PWMInit
+ =
+ 1;
+ } else {
+ /***************************************************/
+ /* You can not used the 40MHz clock selection with */
+ /* this board */
+ /***************************************************/
+ DPRINTK("You can not used the 40MHz clock selection with this board\n");
+ i_ReturnValue
+ =
+ -9;
+ }
+ } else {
+ /***************************************/
+ /* High base timing selection is wrong */
+ /***************************************/
+ DPRINTK("High base timing selection is wrong\n");
+ i_ReturnValue =
+ -8;
+ }
+ } else {
+ /**************************************/
+ /* Low base timing selection is wrong */
+ /**************************************/
+ DPRINTK("Low base timing selection is wrong\n");
+ i_ReturnValue = -7;
+ }
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ else {
+ /**********************************/
+ /* Timing unit selection is wrong */
+ /**********************************/
+ DPRINTK("Timing unit selection is wrong\n");
+ i_ReturnValue = -6;
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ))
+ else {
+ /*******************************/
+ /* The selected clock is wrong */
+ /*******************************/
+ DPRINTK("The selected clock is wrong\n");
+ i_ReturnValue = -5;
+ } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ))
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ else {
+ /******************************/
+ /* Tor PWM selection is wrong */
+ /******************************/
+ DPRINTK("Tor PWM selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ } else {
+ /**********************************/
+ /* The module is not a PWM module */
+ /**********************************/
+ DPRINTK("The module is not a PWM module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetPWMInitialisation |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PWM, |
+| PBYTE_ pb_TimingUnit, |
+| PULONG_ pul_LowTiming, |
+| PULONG_ pul_HighTiming, |
+| PBYTE_ pb_StartLevel, |
+| PBYTE_ pb_StopMode, |
+| PBYTE_ pb_StopLevel, |
+| PBYTE_ pb_ExternGate, |
+| PBYTE_ pb_InterruptEnable, |
+| PBYTE_ pb_Enable) |
++----------------------------------------------------------------------------+
+| Task : Return the PWM (b_PWM) initialisation from selected |
+| module (b_ModulNbr). You must calling the |
+| "i_APCI1710_InitPWM" function be for you call this |
+| function. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
+| BYTE_ b_PWM : Selected PWM (0 or 1) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_TimingUnit : Base timing Unit (0 to 4) |
+| 0 : ns |
+| 1 : æs |
+| 2 : ms |
+| 3 : s |
+| 4 : mn |
+| PULONG_ pul_LowTiming : Low base timing value. |
+| PULONG_ pul_HighTiming : High base timing value. |
+| PBYTE_ pb_StartLevel : Start period level |
+| selection |
+| 0 : The period start |
+| with a low level |
+| 1 : The period start |
+| with a high level|
+| PBYTE_ pb_StopMode : Stop mode selection |
+| 0 : The PWM is stopped |
+| directly after the |
+| "i_APCI1710_DisablePWM"|
+| function and break the|
+| last period |
+| 1 : After the |
+| "i_APCI1710_DisablePWM"|
+| function the PWM is |
+| stopped at the end |
+| from last period cycle|
+| PBYTE_ pb_StopLevel : Stop PWM level selection |
+| 0 : The output signal |
+| keep the level after|
+| the |
+| "i_APCI1710_DisablePWM"|
+| function |
+| 1 : The output signal is|
+| set to low after the|
+| "i_APCI1710_DisablePWM"|
+| function |
+| 2 : The output signal is|
+| set to high after |
+| the |
+| "i_APCI1710_DisablePWM"|
+| function |
+| PBYTE_ pb_ExternGate : Extern gate action |
+| selection |
+| 0 : Extern gate signal |
+| not used. |
+| 1 : Extern gate signal |
+| used. |
+| PBYTE_ pb_InterruptEnable : Enable or disable the PWM |
+| interrupt. |
+| - APCI1710_ENABLE : |
+| Enable the PWM interrupt|
+| A interrupt occur after |
+| each period |
+| - APCI1710_DISABLE : |
+| Disable the PWM |
+| interrupt |
+| PBYTE_ pb_Enable : Indicate if the PWM is |
+| enabled or no |
+| 0 : PWM not enabled |
+| 1 : PWM enabled |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a PWM module |
+| -4: PWM selection is wrong |
+| -5: PWM not initialised see function |
+| "i_APCI1710_InitPWM" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM,
+ PBYTE pb_TimingUnit,
+ PULONG pul_LowTiming,
+ PULONG pul_HighTiming,
+ PBYTE pb_StartLevel,
+ PBYTE pb_StopMode,
+ PBYTE pb_StopLevel,
+ PBYTE pb_ExternGate, PBYTE pb_InterruptEnable, PBYTE pb_Enable)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+ DWORD dw_Command;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***************/
+ /* Test if PWM */
+ /***************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_PWM) {
+ /**************************/
+ /* Test the PWM selection */
+ /**************************/
+
+ if (b_PWM <= 1) {
+ /***************************/
+ /* Test if PWM initialised */
+ /***************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ if (dw_Status & 0x10) {
+ /***********************/
+ /* Read the low timing */
+ /***********************/
+
+ *pul_LowTiming =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 0 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ /************************/
+ /* Read the high timing */
+ /************************/
+
+ *pul_HighTiming =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 4 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ /********************/
+ /* Read the command */
+ /********************/
+
+ dw_Command = inl(devpriv->s_BoardInfos.
+ ui_Address + 8 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ *pb_StartLevel =
+ (BYTE) ((dw_Command >> 5) & 1);
+ *pb_StopMode =
+ (BYTE) ((dw_Command >> 0) & 1);
+ *pb_StopLevel =
+ (BYTE) ((dw_Command >> 1) & 1);
+ *pb_ExternGate =
+ (BYTE) ((dw_Command >> 4) & 1);
+ *pb_InterruptEnable =
+ (BYTE) ((dw_Command >> 3) & 1);
+
+ if (*pb_StopLevel) {
+ *pb_StopLevel =
+ *pb_StopLevel +
+ (BYTE) ((dw_Command >>
+ 2) & 1);
+ }
+
+ /********************/
+ /* Read the command */
+ /********************/
+
+ dw_Command = inl(devpriv->s_BoardInfos.
+ ui_Address + 8 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ *pb_Enable =
+ (BYTE) ((dw_Command >> 0) & 1);
+
+ *pb_TimingUnit = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo[b_PWM].b_TimingUnit;
+ } // if (dw_Status & 0x10)
+ else {
+ /***********************/
+ /* PWM not initialised */
+ /***********************/
+ DPRINTK("PWM not initialised\n");
+ i_ReturnValue = -5;
+ } // if (dw_Status & 0x10)
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ else {
+ /******************************/
+ /* Tor PWM selection is wrong */
+ /******************************/
+ DPRINTK("Tor PWM selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ } else {
+ /**********************************/
+ /* The module is not a PWM module */
+ /**********************************/
+ DPRINTK("The module is not a PWM module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name :INT i_APCI1710_InsnWritePWM(struct comedi_device *dev,
+struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Pwm Enable Disable and Set New Timing |
++----------------------------------------------------------------------------+
+| Input Parameters :
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_WriteType;
+ INT i_ReturnValue = 0;
+ b_WriteType = CR_CHAN(insn->chanspec);
+
+ switch (b_WriteType) {
+ case APCI1710_PWM_ENABLE:
+ i_ReturnValue = i_APCI1710_EnablePWM(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (BYTE) data[0],
+ (BYTE) data[1],
+ (BYTE) data[2],
+ (BYTE) data[3], (BYTE) data[4], (BYTE) data[5]);
+ break;
+
+ case APCI1710_PWM_DISABLE:
+ i_ReturnValue = i_APCI1710_DisablePWM(dev,
+ (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]);
+ break;
+
+ case APCI1710_PWM_NEWTIMING:
+ i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev,
+ (BYTE) CR_AREF(insn->chanspec),
+ (BYTE) data[0],
+ (BYTE) data[1], (ULONG) data[2], (ULONG) data[3]);
+ break;
+
+ default:
+ printk("Write Config Parameter Wrong\n");
+ }
+
+ if (i_ReturnValue >= 0)
+ i_ReturnValue = insn->n;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnablePWM |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PWM, |
+| BYTE_ b_StartLevel, |
+| BYTE_ b_StopMode, |
+| BYTE_ b_StopLevel, |
+| BYTE_ b_ExternGate, |
+| BYTE_ b_InterruptEnable) |
++----------------------------------------------------------------------------+
+| Task : Enable the selected PWM (b_PWM) from selected module |
+| (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"|
+| function be for you call this function. |
+| If you enable the PWM interrupt, the PWM generate a |
+| interrupt after each period. |
+| See function "i_APCI1710_SetBoardIntRoutineX" and the |
+| Interrupt mask description chapter. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number |
+| (0 to 3) |
+| BYTE_ b_PWM : Selected PWM (0 or 1) |
+| BYTE_ b_StartLevel : Start period level selection |
+| 0 : The period start with a |
+| low level |
+| 1 : The period start with a |
+| high level |
+| BYTE_ b_StopMode : Stop mode selection |
+| 0 : The PWM is stopped |
+| directly after the |
+| "i_APCI1710_DisablePWM" |
+| function and break the |
+| last period |
+| 1 : After the |
+| "i_APCI1710_DisablePWM" |
+| function the PWM is |
+| stopped at the end from|
+| last period cycle. |
+| BYTE_ b_StopLevel : Stop PWM level selection |
+| 0 : The output signal keep |
+| the level after the |
+| "i_APCI1710_DisablePWM" |
+| function |
+| 1 : The output signal is set|
+| to low after the |
+| "i_APCI1710_DisablePWM" |
+| function |
+| 2 : The output signal is set|
+| to high after the |
+| "i_APCI1710_DisablePWM" |
+| function |
+| BYTE_ b_ExternGate : Extern gate action selection |
+| 0 : Extern gate signal not |
+| used. |
+| 1 : Extern gate signal used.|
+| BYTE_ b_InterruptEnable : Enable or disable the PWM |
+| interrupt. |
+| - APCI1710_ENABLE : |
+| Enable the PWM interrupt |
+| A interrupt occur after |
+| each period |
+| - APCI1710_DISABLE : |
+| Disable the PWM interrupt |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a PWM module |
+| -4: PWM selection is wrong |
+| -5: PWM not initialised see function |
+| "i_APCI1710_InitPWM" |
+| -6: PWM start level selection is wrong |
+| -7: PWM stop mode selection is wrong |
+| -8: PWM stop level selection is wrong |
+| -9: Extern gate signal selection is wrong |
+| -10: Interrupt parameter is wrong |
+| -11: Interrupt function not initialised. |
+| See function "i_APCI1710_SetBoardIntRoutineX" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_EnablePWM(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM,
+ BYTE b_StartLevel,
+ BYTE b_StopMode,
+ BYTE b_StopLevel, BYTE b_ExternGate, BYTE b_InterruptEnable)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+ DWORD dw_Command;
+
+ devpriv->tsk_Current = current; // Save the current process task structure
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***************/
+ /* Test if PWM */
+ /***************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_PWM) {
+ /**************************/
+ /* Test the PWM selection */
+ /**************************/
+
+ if (b_PWM <= 1) {
+ /***************************/
+ /* Test if PWM initialised */
+ /***************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ if (dw_Status & 0x10) {
+ /**********************************/
+ /* Test the start level selection */
+ /**********************************/
+
+ if (b_StartLevel <= 1) {
+ /**********************/
+ /* Test the stop mode */
+ /**********************/
+
+ if (b_StopMode <= 1) {
+ /***********************/
+ /* Test the stop level */
+ /***********************/
+
+ if (b_StopLevel <= 2) {
+ /*****************************/
+ /* Test the extern gate mode */
+ /*****************************/
+
+ if (b_ExternGate
+ <= 1) {
+ /*****************************/
+ /* Test the interrupt action */
+ /*****************************/
+
+ if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) {
+ /******************************************/
+ /* Test if interrupt function initialised */
+ /******************************************/
+
+ /********************/
+ /* Read the command */
+ /********************/
+
+ dw_Command
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 8
+ +
+ (20 * b_PWM) + (64 * b_ModulNbr));
+
+ dw_Command
+ =
+ dw_Command
+ &
+ 0x80;
+
+ /********************/
+ /* Make the command */
+ /********************/
+
+ dw_Command
+ =
+ dw_Command
+ |
+ b_StopMode
+ |
+ (b_InterruptEnable
+ <<
+ 3)
+ |
+ (b_ExternGate
+ <<
+ 4)
+ |
+ (b_StartLevel
+ <<
+ 5);
+
+ if (b_StopLevel & 3) {
+ dw_Command
+ =
+ dw_Command
+ |
+ 2;
+
+ if (b_StopLevel & 2) {
+ dw_Command
+ =
+ dw_Command
+ |
+ 4;
+ }
+ }
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ b_InterruptEnable
+ =
+ b_InterruptEnable;
+
+ /*******************/
+ /* Set the command */
+ /*******************/
+
+ outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+ /******************/
+ /* Enable the PWM */
+ /******************/
+ outl(1, devpriv->s_BoardInfos.ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr));
+ } // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE)
+ else {
+ /********************************/
+ /* Interrupt parameter is wrong */
+ /********************************/
+ DPRINTK("Interrupt parameter is wrong\n");
+ i_ReturnValue
+ =
+ -10;
+ } // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE)
+ } // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+ else {
+ /*****************************************/
+ /* Extern gate signal selection is wrong */
+ /*****************************************/
+ DPRINTK("Extern gate signal selection is wrong\n");
+ i_ReturnValue
+ =
+ -9;
+ } // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+ } // if (b_StopLevel >= 0 && b_StopLevel <= 2)
+ else {
+ /*************************************/
+ /* PWM stop level selection is wrong */
+ /*************************************/
+ DPRINTK("PWM stop level selection is wrong\n");
+ i_ReturnValue =
+ -8;
+ } // if (b_StopLevel >= 0 && b_StopLevel <= 2)
+ } // if (b_StopMode >= 0 && b_StopMode <= 1)
+ else {
+ /************************************/
+ /* PWM stop mode selection is wrong */
+ /************************************/
+ DPRINTK("PWM stop mode selection is wrong\n");
+ i_ReturnValue = -7;
+ } // if (b_StopMode >= 0 && b_StopMode <= 1)
+ } // if (b_StartLevel >= 0 && b_StartLevel <= 1)
+ else {
+ /**************************************/
+ /* PWM start level selection is wrong */
+ /**************************************/
+ DPRINTK("PWM start level selection is wrong\n");
+ i_ReturnValue = -6;
+ } // if (b_StartLevel >= 0 && b_StartLevel <= 1)
+ } // if (dw_Status & 0x10)
+ else {
+ /***********************/
+ /* PWM not initialised */
+ /***********************/
+ DPRINTK("PWM not initialised\n");
+ i_ReturnValue = -5;
+ } // if (dw_Status & 0x10)
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ else {
+ /******************************/
+ /* Tor PWM selection is wrong */
+ /******************************/
+ DPRINTK("Tor PWM selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ } else {
+ /**********************************/
+ /* The module is not a PWM module */
+ /**********************************/
+ DPRINTK("The module is not a PWM module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_DisablePWM (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PWM) |
++----------------------------------------------------------------------------+
+| Task : Disable the selected PWM (b_PWM) from selected module |
+| (b_ModulNbr). The output signal level depend of the |
+| initialisation by the "i_APCI1710_EnablePWM". |
+| See the b_StartLevel, b_StopMode and b_StopLevel |
+| parameters from this function. |
++----------------------------------------------------------------------------+
+| Input Parameters :BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
+| BYTE_ b_PWM : Selected PWM (0 or 1) |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a PWM module |
+| -4: PWM selection is wrong |
+| -5: PWM not initialised see function |
+| "i_APCI1710_InitPWM" |
+| -6: PWM not enabled see function |
+| "i_APCI1710_EnablePWM" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***************/
+ /* Test if PWM */
+ /***************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_PWM) {
+ /**************************/
+ /* Test the PWM selection */
+ /**************************/
+
+ if (b_PWM <= 1) {
+ /***************************/
+ /* Test if PWM initialised */
+ /***************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ if (dw_Status & 0x10) {
+ /***********************/
+ /* Test if PWM enabled */
+ /***********************/
+
+ if (dw_Status & 0x1) {
+ /*******************/
+ /* Disable the PWM */
+ /*******************/
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 12 +
+ (20 * b_PWM) +
+ (64 * b_ModulNbr));
+ } // if (dw_Status & 0x1)
+ else {
+ /*******************/
+ /* PWM not enabled */
+ /*******************/
+ DPRINTK("PWM not enabled\n");
+ i_ReturnValue = -6;
+ } // if (dw_Status & 0x1)
+ } // if (dw_Status & 0x10)
+ else {
+ /***********************/
+ /* PWM not initialised */
+ /***********************/
+ DPRINTK(" PWM not initialised\n");
+ i_ReturnValue = -5;
+ } // if (dw_Status & 0x10)
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ else {
+ /******************************/
+ /* Tor PWM selection is wrong */
+ /******************************/
+ DPRINTK("Tor PWM selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ } else {
+ /**********************************/
+ /* The module is not a PWM module */
+ /**********************************/
+ DPRINTK("The module is not a PWM module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_SetNewPWMTiming |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PWM, |
+| BYTE_ b_ClockSelection, |
+| BYTE_ b_TimingUnit, |
+| ULONG_ ul_LowTiming, |
+| ULONG_ ul_HighTiming) |
++----------------------------------------------------------------------------+
+| Task : Set a new timing. The ul_LowTiming, ul_HighTiming and |
+| ul_TimingUnit determine the low/high timing base for |
+| the period. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Module number to configure|
+| (0 to 3) |
+| BYTE_ b_PWM : Selected PWM (0 or 1). |
+| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) |
+| 0 : ns |
+| 1 : æs |
+| 2 : ms |
+| 3 : s |
+| 4 : mn |
+| ULONG_ ul_LowTiming : Low base timing value. |
+| ULONG_ ul_HighTiming : High base timing value. |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a PWM module |
+| -4: PWM selection is wrong |
+| -5: PWM not initialised |
+| -6: Timing Unit selection is wrong |
+| -7: Low base timing selection is wrong |
+| -8: High base timing selection is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM, BYTE b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming)
+{
+ BYTE b_ClockSelection;
+ INT i_ReturnValue = 0;
+ ULONG ul_LowTimerValue = 0;
+ ULONG ul_HighTimerValue = 0;
+ ULONG ul_RealLowTiming = 0;
+ ULONG ul_RealHighTiming = 0;
+ DWORD dw_Status;
+ DWORD dw_Command;
+ double d_RealLowTiming = 0;
+ double d_RealHighTiming = 0;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***************/
+ /* Test if PWM */
+ /***************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_PWM) {
+ /**************************/
+ /* Test the PWM selection */
+ /**************************/
+
+ if (b_PWM <= 1) {
+ /***************************/
+ /* Test if PWM initialised */
+ /***************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ if (dw_Status & 0x10) {
+ b_ClockSelection = devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_PWMModuleInfo.
+ b_ClockSelection;
+
+ /************************/
+ /* Test the timing unit */
+ /************************/
+
+ if (b_TimingUnit <= 4) {
+ /*********************************/
+ /* Test the low timing selection */
+ /*********************************/
+
+ if (((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 0)
+ && (ul_LowTiming
+ >= 266)
+ && (ul_LowTiming
+ <=
+ 0xFFFFFFFFUL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 1)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 571230650UL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 2)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 571230UL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 3)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 571UL))
+ || ((b_ClockSelection ==
+ APCI1710_30MHZ)
+ && (b_TimingUnit
+ == 4)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <= 9UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 0)
+ && (ul_LowTiming
+ >= 242)
+ && (ul_LowTiming
+ <=
+ 0xFFFFFFFFUL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 1)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 519691043UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 2)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 519691UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 3)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 520UL))
+ || ((b_ClockSelection ==
+ APCI1710_33MHZ)
+ && (b_TimingUnit
+ == 4)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <= 8UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 0)
+ && (ul_LowTiming
+ >= 200)
+ && (ul_LowTiming
+ <=
+ 0xFFFFFFFFUL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 1)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 429496729UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 2)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 429496UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 3)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 429UL))
+ || ((b_ClockSelection ==
+ APCI1710_40MHZ)
+ && (b_TimingUnit
+ == 4)
+ && (ul_LowTiming
+ >= 1)
+ && (ul_LowTiming
+ <=
+ 7UL))) {
+ /**********************************/
+ /* Test the High timing selection */
+ /**********************************/
+
+ if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) {
+ /************************************/
+ /* Calculate the low division fator */
+ /************************************/
+
+ fpu_begin();
+ switch (b_TimingUnit) {
+ /******/
+ /* ns */
+ /******/
+
+ case 0:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (ul_LowTiming
+ *
+ (0.00025 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (0.00025 * (double)b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (0.00025
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+ ul_RealLowTiming
+ =
+ ul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* æs */
+ /******/
+
+ case 1:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (ul_LowTiming
+ *
+ (0.25 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (0.25 * (double)b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (
+ (double)
+ 0.25
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+ ul_RealLowTiming
+ =
+ ul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* ms */
+ /******/
+
+ case 2:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ ul_LowTiming
+ *
+ (250.0
+ *
+ b_ClockSelection);
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (250.0 * (double)b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (250.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+ ul_RealLowTiming
+ =
+ ul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /*****/
+ /* s */
+ /*****/
+
+ case 3:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (ul_LowTiming
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection));
+ d_RealLowTiming
+ =
+ (double)
+ ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) {
+ ul_RealLowTiming
+ =
+ ul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* mn */
+ /******/
+
+ case 4:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (ul_LowTiming
+ *
+ 60)
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) {
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealLowTiming
+ =
+ (ULONG)
+ (ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60;
+ d_RealLowTiming
+ =
+ (
+ (double)
+ ul_LowTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60.0;
+
+ if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealLowTiming + 0.5)) {
+ ul_RealLowTiming
+ =
+ ul_RealLowTiming
+ +
+ 1;
+ }
+
+ ul_LowTiming
+ =
+ ul_LowTiming
+ -
+ 1;
+ ul_LowTimerValue
+ =
+ ul_LowTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_LowTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_LowTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+ }
+
+ /*************************************/
+ /* Calculate the high division fator */
+ /*************************************/
+
+ switch (b_TimingUnit) {
+ /******/
+ /* ns */
+ /******/
+
+ case 0:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (ul_HighTiming
+ *
+ (0.00025 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (0.00025 * (double)b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (0.00025
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+ ul_RealHighTiming
+ =
+ ul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* æs */
+ /******/
+
+ case 1:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (ul_HighTiming
+ *
+ (0.25 * b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (0.25 * (double)b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (
+ (double)
+ 0.25
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+ ul_RealHighTiming
+ =
+ ul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* ms */
+ /******/
+
+ case 2:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ ul_HighTiming
+ *
+ (250.0
+ *
+ b_ClockSelection);
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (250.0 * (double)b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (250.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+ ul_RealHighTiming
+ =
+ ul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /*****/
+ /* s */
+ /*****/
+
+ case 3:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (ul_HighTiming
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection));
+ d_RealHighTiming
+ =
+ (double)
+ ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection);
+
+ if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) {
+ ul_RealHighTiming
+ =
+ ul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* mn */
+ /******/
+
+ case 4:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (ul_HighTiming
+ *
+ 60)
+ *
+ (250000.0
+ *
+ b_ClockSelection));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) {
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealHighTiming
+ =
+ (ULONG)
+ (ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60;
+ d_RealHighTiming
+ =
+ (
+ (double)
+ ul_HighTimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_ClockSelection))
+ /
+ 60.0;
+
+ if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealHighTiming + 0.5)) {
+ ul_RealHighTiming
+ =
+ ul_RealHighTiming
+ +
+ 1;
+ }
+
+ ul_HighTiming
+ =
+ ul_HighTiming
+ -
+ 1;
+ ul_HighTimerValue
+ =
+ ul_HighTimerValue
+ -
+ 2;
+
+ if (b_ClockSelection != APCI1710_40MHZ) {
+ ul_HighTimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_HighTimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+ }
+
+ fpu_end();
+
+ /************************/
+ /* Save the timing unit */
+ /************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ b_TimingUnit
+ =
+ b_TimingUnit;
+
+ /****************************/
+ /* Save the low base timing */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ d_LowTiming
+ =
+ d_RealLowTiming;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ ul_RealLowTiming
+ =
+ ul_RealLowTiming;
+
+ /****************************/
+ /* Save the high base timing */
+ /****************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ d_HighTiming
+ =
+ d_RealHighTiming;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_PWMModuleInfo.
+ s_PWMInfo
+ [b_PWM].
+ ul_RealHighTiming
+ =
+ ul_RealHighTiming;
+
+ /************************/
+ /* Write the low timing */
+ /************************/
+
+ outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+ /*************************/
+ /* Write the high timing */
+ /*************************/
+
+ outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr));
+
+ /***************************/
+ /* Set the clock selection */
+ /***************************/
+
+ dw_Command =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ + 8 +
+ (20 * b_PWM) + (64 * b_ModulNbr));
+
+ dw_Command =
+ dw_Command
+ & 0x7F;
+
+ if (b_ClockSelection == APCI1710_40MHZ) {
+ dw_Command
+ =
+ dw_Command
+ |
+ 0x80;
+ }
+
+ /***************************/
+ /* Set the clock selection */
+ /***************************/
+
+ outl(dw_Command,
+ devpriv->
+ s_BoardInfos.
+ ui_Address
+ + 8 +
+ (20 * b_PWM) + (64 * b_ModulNbr));
+ } else {
+ /***************************************/
+ /* High base timing selection is wrong */
+ /***************************************/
+ DPRINTK("High base timing selection is wrong\n");
+ i_ReturnValue =
+ -8;
+ }
+ } else {
+ /**************************************/
+ /* Low base timing selection is wrong */
+ /**************************************/
+ DPRINTK("Low base timing selection is wrong\n");
+ i_ReturnValue = -7;
+ }
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ else {
+ /**********************************/
+ /* Timing unit selection is wrong */
+ /**********************************/
+ DPRINTK("Timing unit selection is wrong\n");
+ i_ReturnValue = -6;
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ } // if (dw_Status & 0x10)
+ else {
+ /***********************/
+ /* PWM not initialised */
+ /***********************/
+ DPRINTK("PWM not initialised\n");
+ i_ReturnValue = -5;
+ } // if (dw_Status & 0x10)
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ else {
+ /******************************/
+ /* Tor PWM selection is wrong */
+ /******************************/
+ DPRINTK("Tor PWM selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ } else {
+ /**********************************/
+ /* The module is not a PWM module */
+ /**********************************/
+ DPRINTK("The module is not a PWM module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetPWMStatus |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PWM, |
+| PBYTE_ pb_PWMOutputStatus, |
+| PBYTE_ pb_ExternGateStatus) |
++----------------------------------------------------------------------------+
+| Task : Return the status from selected PWM (b_PWM) from |
+| selected module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_PWM : Selected PWM (0 or 1) |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3)
+ b_ModulNbr =(BYTE) CR_AREF(insn->chanspec);
+ b_PWM =(BYTE) data[0];
+
+ |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_PWMOutputStatus : Return the PWM output |
+| level status. |
+| 0 : The PWM output level|
+| is low. |
+| 1 : The PWM output level|
+| is high. |
+| PBYTE_ pb_ExternGateStatus : Return the extern gate |
+| level status. |
+| 0 : The extern gate is |
+| low. |
+| 1 : The extern gate is |
+| high.
+ pb_PWMOutputStatus =(PBYTE) data[0];
+ pb_ExternGateStatus =(PBYTE) data[1]; |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a PWM module |
+| -4: PWM selection is wrong |
+| -5: PWM not initialised see function |
+| "i_APCI1710_InitPWM" |
+| -6: PWM not enabled see function "i_APCI1710_EnablePWM"|
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+
+ BYTE b_ModulNbr;
+ BYTE b_PWM;
+ PBYTE pb_PWMOutputStatus;
+ PBYTE pb_ExternGateStatus;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_PWM = (BYTE) CR_CHAN(insn->chanspec);
+ pb_PWMOutputStatus = (PBYTE) & data[0];
+ pb_ExternGateStatus = (PBYTE) & data[1];
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***************/
+ /* Test if PWM */
+ /***************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_PWM) {
+ /**************************/
+ /* Test the PWM selection */
+ /**************************/
+
+ if (b_PWM <= 1) {
+ /***************************/
+ /* Test if PWM initialised */
+ /***************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (20 * b_PWM) +
+ (64 * b_ModulNbr));
+
+ if (dw_Status & 0x10) {
+ /***********************/
+ /* Test if PWM enabled */
+ /***********************/
+
+ if (dw_Status & 0x1) {
+ *pb_PWMOutputStatus =
+ (BYTE) ((dw_Status >> 7)
+ & 1);
+ *pb_ExternGateStatus =
+ (BYTE) ((dw_Status >> 6)
+ & 1);
+ } // if (dw_Status & 0x1)
+ else {
+ /*******************/
+ /* PWM not enabled */
+ /*******************/
+
+ DPRINTK("PWM not enabled \n");
+ i_ReturnValue = -6;
+ } // if (dw_Status & 0x1)
+ } // if (dw_Status & 0x10)
+ else {
+ /***********************/
+ /* PWM not initialised */
+ /***********************/
+
+ DPRINTK("PWM not initialised\n");
+ i_ReturnValue = -5;
+ } // if (dw_Status & 0x10)
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ else {
+ /******************************/
+ /* Tor PWM selection is wrong */
+ /******************************/
+
+ DPRINTK("Tor PWM selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_PWM >= 0 && b_PWM <= 1)
+ } else {
+ /**********************************/
+ /* The module is not a PWM module */
+ /**********************************/
+
+ DPRINTK("The module is not a PWM module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ data[0] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].b_OldModuleMask;
+ data[1] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+ data[2] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+ /**************************/
+ /* Increment the read FIFO */
+ /***************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Read = (devpriv->
+ s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+ return insn->n;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
new file mode 100644
index 000000000000..c1b7f4ca47c3
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_30MHZ 30
+#define APCI1710_33MHZ 33
+#define APCI1710_40MHZ 40
+
+#define APCI1710_PWM_INIT 0
+#define APCI1710_PWM_GETINITDATA 1
+
+#define APCI1710_PWM_DISABLE 0
+#define APCI1710_PWM_ENABLE 1
+#define APCI1710_PWM_NEWTIMING 2
+
+INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InitPWM(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM,
+ BYTE b_ClockSelection,
+ BYTE b_TimingUnit,
+ ULONG ul_LowTiming,
+ ULONG ul_HighTiming,
+ PULONG pul_RealLowTiming, PULONG pul_RealHighTiming);
+
+INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM,
+ PBYTE pb_TimingUnit,
+ PULONG pul_LowTiming,
+ PULONG pul_HighTiming,
+ PBYTE pb_StartLevel,
+ PBYTE pb_StopMode,
+ PBYTE pb_StopLevel,
+ PBYTE pb_ExternGate,
+ PBYTE pb_InterruptEnable, PBYTE pb_Enable);
+
+INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_EnablePWM(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM,
+ BYTE b_StartLevel,
+ BYTE b_StopMode,
+ BYTE b_StopLevel, BYTE b_ExternGate,
+ BYTE b_InterruptEnable);
+
+INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+ BYTE b_ModulNbr,
+ BYTE b_PWM, BYTE b_TimingUnit,
+ ULONG ul_LowTiming, ULONG ul_HighTiming);
+
+INT i_APCI1710_DisablePWM(struct comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM);
+
+INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
new file mode 100644
index 000000000000..bb6e1622e379
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
@@ -0,0 +1,848 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : SSI.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 SSI counter module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | 13/05/98 | S. Weber | SSI digital input / output implementation |
+ |----------|-----------|------------------------------------------------|
+ | 22/03/00 | C.Guinot | 0100/0226 -> 0200/0227 |
+ | | | Änderung in InitSSI Funktion |
+ | | | b_SSIProfile >= 2 anstatt b_SSIProfile > 2 |
+ | | | |
+ +-----------------------------------------------------------------------+
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Ssi.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitSSI |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_SSIProfile, |
+| BYTE_ b_PositionTurnLength, |
+| BYTE_ b_TurnCptLength, |
+| BYTE_ b_PCIInputClock, |
+| ULONG_ ul_SSIOutputClock, |
+| BYTE_ b_SSICountingMode) |
++----------------------------------------------------------------------------+
+| Task : Configure the SSI operating mode from selected module |
+| (b_ModulNbr). You must calling this function be for you|
+| call any other function witch access of SSI. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
+| BYTE_ b_SSIProfile : Selection from SSI |
+| profile length (2 to 32).|
+| BYTE_ b_PositionTurnLength : Selection from SSI |
+| position data length |
+| (1 to 31). |
+| BYTE_ b_TurnCptLength : Selection from SSI turn |
+| counter data length |
+| (1 to 31). |
+| BYTE b_PCIInputClock : Selection from PCI bus |
+| clock |
+| - APCI1710_30MHZ : |
+| The PC have a PCI bus |
+| clock from 30 MHz |
+| - APCI1710_33MHZ : |
+| The PC have a PCI bus |
+| clock from 33 MHz |
+| ULONG_ ul_SSIOutputClock : Selection from SSI output|
+| clock. |
+| From 229 to 5 000 000 Hz|
+| for 30 MHz selection. |
+| From 252 to 5 000 000 Hz|
+| for 33 MHz selection. |
+| BYTE b_SSICountingMode : SSI counting mode |
+| selection |
+| - APCI1710_BINARY_MODE : |
+| Binary counting mode. |
+| - APCI1710_GRAY_MODE : |
+| Gray counting mode.
+
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_SSIProfile = (BYTE) data[0];
+ b_PositionTurnLength= (BYTE) data[1];
+ b_TurnCptLength = (BYTE) data[2];
+ b_PCIInputClock = (BYTE) data[3];
+ ul_SSIOutputClock = (ULONG) data[4];
+ b_SSICountingMode = (BYTE) data[5]; |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a SSI module |
+| -4: The selected SSI profile length is wrong |
+| -5: The selected SSI position data length is wrong |
+| -6: The selected SSI turn counter data length is wrong |
+| -7: The selected PCI input clock is wrong |
+| -8: The selected SSI output clock is wrong |
+| -9: The selected SSI counting mode parameter is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ UINT ui_TimerValue;
+ BYTE b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
+ b_PCIInputClock, b_SSICountingMode;
+ ULONG ul_SSIOutputClock;
+
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_SSIProfile = (BYTE) data[0];
+ b_PositionTurnLength = (BYTE) data[1];
+ b_TurnCptLength = (BYTE) data[2];
+ b_PCIInputClock = (BYTE) data[3];
+ ul_SSIOutputClock = (ULONG) data[4];
+ b_SSICountingMode = (BYTE) data[5];
+
+ i_ReturnValue = insn->n;
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if SSI counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
+ /*******************************/
+ /* Test the SSI profile length */
+ /*******************************/
+
+ // CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2
+ if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
+ /*************************************/
+ /* Test the SSI position data length */
+ /*************************************/
+
+ if (b_PositionTurnLength > 0
+ && b_PositionTurnLength < 32) {
+ /*****************************************/
+ /* Test the SSI turn counter data length */
+ /*****************************************/
+
+ if (b_TurnCptLength > 0
+ && b_TurnCptLength < 32) {
+ /***************************/
+ /* Test the profile length */
+ /***************************/
+
+ if ((b_TurnCptLength +
+ b_PositionTurnLength)
+ <= b_SSIProfile) {
+ /****************************/
+ /* Test the PCI input clock */
+ /****************************/
+
+ if (b_PCIInputClock ==
+ APCI1710_30MHZ
+ ||
+ b_PCIInputClock
+ ==
+ APCI1710_33MHZ)
+ {
+ /*************************/
+ /* Test the output clock */
+ /*************************/
+
+ if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) {
+ if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) {
+ /**********************/
+ /* Save configuration */
+ /**********************/
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_SSIProfile
+ =
+ b_SSIProfile;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_PositionTurnLength
+ =
+ b_PositionTurnLength;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_TurnCptLength
+ =
+ b_TurnCptLength;
+
+ /*********************************/
+ /* Initialise the profile length */
+ /*********************************/
+
+ if (b_SSICountingMode == APCI1710_BINARY_MODE) {
+
+ outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
+ } else {
+
+ outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
+ }
+
+ /******************************/
+ /* Calculate the output clock */
+ /******************************/
+
+ ui_TimerValue
+ =
+ (UINT)
+ (
+ ((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
+
+ /************************/
+ /* Initialise the timer */
+ /************************/
+
+ outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
+
+ /********************************/
+ /* Initialise the counting mode */
+ /********************************/
+
+ outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_SSIInit
+ =
+ 1;
+ } else {
+ /*****************************************************/
+ /* The selected SSI counting mode parameter is wrong */
+ /*****************************************************/
+
+ DPRINTK("The selected SSI counting mode parameter is wrong\n");
+ i_ReturnValue
+ =
+ -9;
+ }
+ } else {
+ /******************************************/
+ /* The selected SSI output clock is wrong */
+ /******************************************/
+
+ DPRINTK("The selected SSI output clock is wrong\n");
+ i_ReturnValue
+ =
+ -8;
+ }
+ } else {
+ /*****************************************/
+ /* The selected PCI input clock is wrong */
+ /*****************************************/
+
+ DPRINTK("The selected PCI input clock is wrong\n");
+ i_ReturnValue =
+ -7;
+ }
+ } else {
+ /********************************************/
+ /* The selected SSI profile length is wrong */
+ /********************************************/
+
+ DPRINTK("The selected SSI profile length is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /******************************************************/
+ /* The selected SSI turn counter data length is wrong */
+ /******************************************************/
+
+ DPRINTK("The selected SSI turn counter data length is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /**************************************************/
+ /* The selected SSI position data length is wrong */
+ /**************************************************/
+
+ DPRINTK("The selected SSI position data length is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /********************************************/
+ /* The selected SSI profile length is wrong */
+ /********************************************/
+
+ DPRINTK("The selected SSI profile length is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /**********************************/
+ /* The module is not a SSI module */
+ /**********************************/
+
+ DPRINTK("The module is not a SSI module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_Read1SSIValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_SelectedSSI, |
+| PULONG_ pul_Position, |
+| PULONG_ pul_TurnCpt)
+ INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task :
+
+
+ Read the selected SSI counter (b_SelectedSSI) from |
+| selected module (b_ModulNbr).
+ or Read all SSI counter (b_SelectedSSI) from |
+| selected module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
+| BYTE_ b_SelectedSSI : Selection from SSI |
+| counter (0 to 2)
+
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec); (in case of single ssi)
+ b_ReadType = (BYTE) CR_RANGE(insn->chanspec);
+|
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_Position : SSI position in the turn |
+| PULONG_ pul_TurnCpt : Number of turns
+
+pul_Position = (PULONG) &data[0];
+ pul_TurnCpt = (PULONG) &data[1]; |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a SSI module |
+| -4: SSI not initialised see function |
+| "i_APCI1710_InitSSI" |
+| -5: The selected SSI is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ BYTE b_Cpt;
+ BYTE b_Length;
+ BYTE b_Schift;
+ BYTE b_SSICpt;
+ DWORD dw_And;
+ DWORD dw_And1;
+ DWORD dw_And2;
+ DWORD dw_StatusReg;
+ DWORD dw_CounterValue;
+ BYTE b_ModulNbr;
+ BYTE b_SelectedSSI;
+ BYTE b_ReadType;
+ PULONG pul_Position;
+ PULONG pul_TurnCpt;
+ PULONG pul_Position1;
+ PULONG pul_TurnCpt1;
+
+ i_ReturnValue = insn->n;
+ pul_Position1 = (PULONG) & data[0];
+// For Read1
+ pul_TurnCpt1 = (PULONG) & data[1];
+// For Read all
+ pul_Position = (PULONG) & data[0]; //0-2
+ pul_TurnCpt = (PULONG) & data[3]; //3-5
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec);
+ b_ReadType = (BYTE) CR_RANGE(insn->chanspec);
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if SSI counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
+ /***************************/
+ /* Test if SSI initialised */
+ /***************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_SSICounterInfo.b_SSIInit == 1) {
+
+ switch (b_ReadType) {
+
+ case APCI1710_SSI_READ1VALUE:
+ /****************************************/
+ /* Test the selected SSI counter number */
+ /****************************************/
+
+ if (b_SelectedSSI < 3) {
+ /************************/
+ /* Start the conversion */
+ /************************/
+
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 8 +
+ (64 * b_ModulNbr));
+
+ do {
+ /*******************/
+ /* Read the status */
+ /*******************/
+
+ dw_StatusReg =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address +
+ (64 * b_ModulNbr));
+ }
+ while ((dw_StatusReg & 0x1) !=
+ 0);
+
+ /******************************/
+ /* Read the SSI counter value */
+ /******************************/
+
+ dw_CounterValue =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 4 +
+ (b_SelectedSSI * 4) +
+ (64 * b_ModulNbr));
+
+ b_Length =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_SSIProfile / 2;
+
+ if ((b_Length * 2) !=
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_SSIProfile) {
+ b_Length++;
+ }
+
+ b_Schift =
+ b_Length -
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_PositionTurnLength;
+
+ *pul_Position1 =
+ dw_CounterValue >>
+ b_Schift;
+
+ dw_And = 1;
+
+ for (b_Cpt = 0;
+ b_Cpt <
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_PositionTurnLength;
+ b_Cpt++) {
+ dw_And = dw_And * 2;
+ }
+
+ *pul_Position1 =
+ *pul_Position1 &
+ ((dw_And) - 1);
+
+ *pul_TurnCpt1 =
+ dw_CounterValue >>
+ b_Length;
+
+ dw_And = 1;
+
+ for (b_Cpt = 0;
+ b_Cpt <
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_TurnCptLength;
+ b_Cpt++) {
+ dw_And = dw_And * 2;
+ }
+
+ *pul_TurnCpt1 =
+ *pul_TurnCpt1 &
+ ((dw_And) - 1);
+ } else {
+ /*****************************/
+ /* The selected SSI is wrong */
+ /*****************************/
+
+ DPRINTK("The selected SSI is wrong\n");
+ i_ReturnValue = -5;
+ }
+ break;
+
+ case APCI1710_SSI_READALLVALUE:
+ dw_And1 = 1;
+
+ for (b_Cpt = 0;
+ b_Cpt <
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SSICounterInfo.
+ b_PositionTurnLength; b_Cpt++) {
+ dw_And1 = dw_And1 * 2;
+ }
+
+ dw_And2 = 1;
+
+ for (b_Cpt = 0;
+ b_Cpt <
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_SSICounterInfo.
+ b_TurnCptLength; b_Cpt++) {
+ dw_And2 = dw_And2 * 2;
+ }
+
+ /************************/
+ /* Start the conversion */
+ /************************/
+
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 8 +
+ (64 * b_ModulNbr));
+
+ do {
+ /*******************/
+ /* Read the status */
+ /*******************/
+
+ dw_StatusReg =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address +
+ (64 * b_ModulNbr));
+ }
+ while ((dw_StatusReg & 0x1) != 0);
+
+ for (b_SSICpt = 0; b_SSICpt < 3;
+ b_SSICpt++) {
+ /******************************/
+ /* Read the SSI counter value */
+ /******************************/
+
+ dw_CounterValue =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 4 +
+ (b_SSICpt * 4) +
+ (64 * b_ModulNbr));
+
+ b_Length =
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_SSIProfile / 2;
+
+ if ((b_Length * 2) !=
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_SSIProfile) {
+ b_Length++;
+ }
+
+ b_Schift =
+ b_Length -
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_SSICounterInfo.
+ b_PositionTurnLength;
+
+ pul_Position[b_SSICpt] =
+ dw_CounterValue >>
+ b_Schift;
+ pul_Position[b_SSICpt] =
+ pul_Position[b_SSICpt] &
+ ((dw_And1) - 1);
+
+ pul_TurnCpt[b_SSICpt] =
+ dw_CounterValue >>
+ b_Length;
+ pul_TurnCpt[b_SSICpt] =
+ pul_TurnCpt[b_SSICpt] &
+ ((dw_And2) - 1);
+ }
+ break;
+
+ default:
+ printk("Read Type Inputs Wrong\n");
+
+ } // switch ending
+
+ } else {
+ /***********************/
+ /* SSI not initialised */
+ /***********************/
+
+ DPRINTK("SSI not initialised\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /**********************************/
+ /* The module is not a SSI module */
+ /**********************************/
+
+ DPRINTK("The module is not a SSI module\n");
+ i_ReturnValue = -3;
+
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_InputChannel, |
+| PBYTE_ pb_ChannelStatus) |
++----------------------------------------------------------------------------+
+| Task :
+ (0) Set the digital output from selected SSI moule |
+| (b_ModuleNbr) ON
+ (1) Set the digital output from selected SSI moule |
+| (b_ModuleNbr) OFF
+ (2)Read the status from selected SSI digital input |
+| (b_InputChannel)
+ (3)Read the status from all SSI digital inputs from |
+| selected SSI module (b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr CR_AREF : Module number to |
+| configure (0 to 3) |
+| BYTE_ b_InputChannel CR_CHAN : Selection from digital |
+| data[0] which IOTYPE input ( 0 to 2) |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel |
+| data[0] status |
+| 0 : Channle is not active|
+| 1 : Channle is active |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a SSI module |
+| -4: The selected SSI digital input is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg;
+ BYTE b_ModulNbr;
+ BYTE b_InputChannel;
+ PBYTE pb_ChannelStatus;
+ PBYTE pb_InputStatus;
+ BYTE b_IOType;
+ i_ReturnValue = insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_IOType = (BYTE) data[0];
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if SSI counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
+ switch (b_IOType) {
+ case APCI1710_SSI_SET_CHANNELON:
+ /*****************************/
+ /* Set the digital output ON */
+ /*****************************/
+
+ outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
+ (64 * b_ModulNbr));
+ break;
+
+ case APCI1710_SSI_SET_CHANNELOFF:
+ /******************************/
+ /* Set the digital output OFF */
+ /******************************/
+
+ outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
+ (64 * b_ModulNbr));
+ break;
+
+ case APCI1710_SSI_READ_1CHANNEL:
+ /******************************************/
+ /* Test the digital imnput channel number */
+ /******************************************/
+
+ b_InputChannel = (BYTE) CR_CHAN(insn->chanspec);
+ pb_ChannelStatus = (PBYTE) & data[0];
+
+ if (b_InputChannel <= 2) {
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+
+ dw_StatusReg =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulNbr));
+ *pb_ChannelStatus =
+ (BYTE) (((~dw_StatusReg) >> (4 +
+ b_InputChannel))
+ & 1);
+ } else {
+ /********************************/
+ /* Selected digital input error */
+ /********************************/
+
+ DPRINTK("Selected digital input error\n");
+ i_ReturnValue = -4;
+ }
+ break;
+
+ case APCI1710_SSI_READ_ALLCHANNEL:
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+ pb_InputStatus = (PBYTE) & data[0];
+
+ dw_StatusReg =
+ inl(devpriv->s_BoardInfos.ui_Address +
+ (64 * b_ModulNbr));
+ *pb_InputStatus =
+ (BYTE) (((~dw_StatusReg) >> 4) & 7);
+ break;
+
+ default:
+ printk("IO type wrong\n");
+
+ } //switch end
+ } else {
+ /**********************************/
+ /* The module is not a SSI module */
+ /**********************************/
+
+ DPRINTK("The module is not a SSI module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
new file mode 100644
index 000000000000..88daad1a3912
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_30MHZ 30
+#define APCI1710_33MHZ 33
+#define APCI1710_40MHZ 40
+
+#define APCI1710_BINARY_MODE 0x1
+#define APCI1710_GRAY_MODE 0x0
+
+#define APCI1710_SSI_READ1VALUE 1
+#define APCI1710_SSI_READALLVALUE 2
+
+#define APCI1710_SSI_SET_CHANNELON 0
+#define APCI1710_SSI_SET_CHANNELOFF 1
+#define APCI1710_SSI_READ_1CHANNEL 2
+#define APCI1710_SSI_READ_ALLCHANNEL 3
+
+/*
+ * SSI INISIALISATION FUNCTION
+ */
+INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
new file mode 100644
index 000000000000..90316e10a3bd
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
@@ -0,0 +1,2049 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : TOR.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 tor counter module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | 27/01/99 | S. Weber | 40 MHz implementation |
+ +-----------------------------------------------------------------------+
+ | 28/04/00 | S. Weber | Simple,double and quadruple mode implementation|
+ | | | Extern clock implementation |
+ +-----------------------------------------------------------------------+
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Tor.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitTorCounter |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TorCounter, |
+| BYTE_ b_PCIInputClock, |
+| BYTE_ b_TimingUnit, |
+| ULONG_ ul_TimingInterval, |
+| PULONG_ pul_RealTimingInterval) |
++----------------------------------------------------------------------------+
+| Task : Configure the selected tor counter (b_TorCounter) |
+| from selected module (b_ModulNbr). |
+| The ul_TimingInterval and ul_TimingUnit determine the |
+| timing base for the measurement. |
+| The pul_RealTimingInterval return the real timing |
+| value. You must calling this function be for you call |
+| any other function witch access of the tor counter. |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : |
+|
+ CR_AREF BYTE_ b_ModulNbr : Module number to configure |
+| (0 to 3) |
+| data[0] BYTE_ b_TorCounter : Tor counter selection |
+| (0 or 1). |
+| data[1] BYTE_ b_PCIInputClock : Selection from PCI bus clock|
+| - APCI1710_30MHZ : |
+| The PC have a PCI bus |
+| clock from 30 MHz |
+| - APCI1710_33MHZ : |
+| The PC have a PCI bus |
+| clock from 33 MHz |
+| - APCI1710_40MHZ |
+| The APCI-1710 have a |
+| integrated 40Mhz |
+| quartz. |
+| - APCI1710_GATE_INPUT |
+| Used the gate input for |
+| the base clock. If you |
+| have selected this option,|
+| than it is not possibl to |
+| used the gate input for |
+| enabled the acquisition |
+| data[2] BYTE_ b_TimingUnit : Base timing unit (0 to 4) |
+| 0 : ns |
+| 1 : µs |
+| 2 : ms |
+| 3 : s |
+| 4 : mn |
+| data[3] ULONG_ ul_TimingInterval : Base timing value. |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing |
+| data[0] value. |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a tor counter module |
+| -4: Tor counter selection is wrong |
+| -5: The selected PCI input clock is wrong |
+| -6: Timing unit selection is wrong |
+| -7: Base timing selection is wrong |
+| -8: You can not used the 40MHz clock selection wich |
+| this board |
+| -9: You can not used the 40MHz clock selection wich |
+| this TOR version |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ ULONG ul_TimerValue = 0;
+ DWORD dw_Command;
+ double d_RealTimingInterval = 0;
+ BYTE b_ModulNbr;
+ BYTE b_TorCounter;
+ BYTE b_PCIInputClock;
+ BYTE b_TimingUnit;
+ ULONG ul_TimingInterval;
+ ULONG ul_RealTimingInterval = 0;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+
+ b_TorCounter = (BYTE) data[0];
+ b_PCIInputClock = (BYTE) data[1];
+ b_TimingUnit = (BYTE) data[2];
+ ul_TimingInterval = (ULONG) data[3];
+ printk("INPUT clock %d\n", b_PCIInputClock);
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if tor counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+ /**********************************/
+ /* Test the tor counter selection */
+ /**********************************/
+
+ if (b_TorCounter <= 1) {
+ /**************************/
+ /* Test the PCI bus clock */
+ /**************************/
+
+ if ((b_PCIInputClock == APCI1710_30MHZ) ||
+ (b_PCIInputClock == APCI1710_33MHZ) ||
+ (b_PCIInputClock == APCI1710_40MHZ) ||
+ (b_PCIInputClock ==
+ APCI1710_GATE_INPUT)) {
+ /************************/
+ /* Test the timing unit */
+ /************************/
+
+ if ((b_TimingUnit <= 4)
+ || (b_PCIInputClock ==
+ APCI1710_GATE_INPUT)) {
+ /**********************************/
+ /* Test the base timing selection */
+ /**********************************/
+
+ if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 133) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230650UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 9UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 121) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691043UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 520UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 8UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 100) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496729UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 7UL)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && (ul_TimingInterval >= 2))) {
+ /**************************/
+ /* Test the board version */
+ /**************************/
+
+ if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) {
+ /************************/
+ /* Test the TOR version */
+ /************************/
+
+ if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3132)) || (b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) {
+ /*********************************/
+ /* Test if not extern clock used */
+ /*********************************/
+
+ if (b_PCIInputClock != APCI1710_GATE_INPUT) {
+ fpu_begin
+ ();
+ /****************************************/
+ /* Calculate the timer 0 division fator */
+ /****************************************/
+
+ switch (b_TimingUnit) {
+ /******/
+ /* ns */
+ /******/
+
+ case 0:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (0.00025 * b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (0.00025 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (0.00025
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* æs */
+ /******/
+
+ case 1:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (0.25 * b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (0.25 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (
+ (double)
+ 0.25
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* ms */
+ /******/
+
+ case 2:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ ul_TimingInterval
+ *
+ (250.0
+ *
+ b_PCIInputClock);
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (250.0 * (double)b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (250.0
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /*****/
+ /* s */
+ /*****/
+
+ case 3:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (ul_TimingInterval
+ *
+ (250000.0
+ *
+ b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)ul_TimingInterval * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_PCIInputClock));
+ d_RealTimingInterval
+ =
+ (double)
+ ul_TimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_PCIInputClock);
+
+ if ((double)((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+
+ /******/
+ /* mn */
+ /******/
+
+ case 4:
+
+ /******************/
+ /* Timer 0 factor */
+ /******************/
+
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (ul_TimingInterval
+ *
+ 60)
+ *
+ (250000.0
+ *
+ b_PCIInputClock));
+
+ /*******************/
+ /* Round the value */
+ /*******************/
+
+ if ((double)((double)(ul_TimingInterval * 60.0) * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) {
+ ul_TimerValue
+ =
+ ul_TimerValue
+ +
+ 1;
+ }
+
+ /*****************************/
+ /* Calculate the real timing */
+ /*****************************/
+
+ ul_RealTimingInterval
+ =
+ (ULONG)
+ (ul_TimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_PCIInputClock))
+ /
+ 60;
+ d_RealTimingInterval
+ =
+ (
+ (double)
+ ul_TimerValue
+ /
+ (250000.0
+ *
+ (double)
+ b_PCIInputClock))
+ /
+ 60.0;
+
+ if ((double)(((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) {
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval
+ +
+ 1;
+ }
+
+ ul_TimingInterval
+ =
+ ul_TimingInterval
+ -
+ 1;
+ ul_TimerValue
+ =
+ ul_TimerValue
+ -
+ 2;
+
+ if (b_PCIInputClock != APCI1710_40MHZ) {
+ ul_TimerValue
+ =
+ (ULONG)
+ (
+ (double)
+ (ul_TimerValue)
+ *
+ 1.007752288);
+ }
+
+ break;
+ }
+
+ fpu_end();
+ } // if (b_PCIInputClock != APCI1710_GATE_INPUT)
+ else {
+ /*************************************************************/
+ /* 2 Clock used for the overflow and the reload from counter */
+ /*************************************************************/
+
+ ul_TimerValue
+ =
+ ul_TimingInterval
+ -
+ 2;
+ } // if (b_PCIInputClock != APCI1710_GATE_INPUT)
+
+ /****************************/
+ /* Save the PCI input clock */
+ /****************************/
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TorCounterModuleInfo.
+ b_PCIInputClock
+ =
+ b_PCIInputClock;
+
+ /************************/
+ /* Save the timing unit */
+ /************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo
+ [b_TorCounter].
+ b_TimingUnit
+ =
+ b_TimingUnit;
+
+ /************************/
+ /* Save the base timing */
+ /************************/
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo
+ [b_TorCounter].
+ d_TimingInterval
+ =
+ d_RealTimingInterval;
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo
+ [b_TorCounter].
+ ul_RealTimingInterval
+ =
+ ul_RealTimingInterval;
+
+ /*******************/
+ /* Get the command */
+ /*******************/
+
+ dw_Command
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 4
+ +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ dw_Command
+ =
+ (dw_Command
+ >>
+ 4)
+ &
+ 0xF;
+
+ /******************/
+ /* Test if 40 MHz */
+ /******************/
+
+ if (b_PCIInputClock == APCI1710_40MHZ) {
+ /****************************/
+ /* Set the 40 MHz selection */
+ /****************************/
+
+ dw_Command
+ =
+ dw_Command
+ |
+ 0x10;
+ }
+
+ /*****************************/
+ /* Test if extern clock used */
+ /*****************************/
+
+ if (b_PCIInputClock == APCI1710_GATE_INPUT) {
+ /****************************/
+ /* Set the 40 MHz selection */
+ /****************************/
+
+ dw_Command
+ =
+ dw_Command
+ |
+ 0x20;
+ }
+
+ /*************************/
+ /* Write the new command */
+ /*************************/
+
+ outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ /*******************/
+ /* Disable the tor */
+ /*******************/
+
+ outl(0, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+ /*************************/
+ /* Set the timer 1 value */
+ /*************************/
+
+ outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ /*********************/
+ /* Tor counter init. */
+ /*********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo
+ [b_TorCounter].
+ b_TorCounterInit
+ =
+ 1;
+ } else {
+ /***********************************************/
+ /* TOR version error for 40MHz clock selection */
+ /***********************************************/
+
+ DPRINTK("TOR version error for 40MHz clock selection\n");
+ i_ReturnValue
+ =
+ -9;
+ }
+ } else {
+ /**************************************************************/
+ /* You can not used the 40MHz clock selection wich this board */
+ /**************************************************************/
+
+ DPRINTK("You can not used the 40MHz clock selection wich this board\n");
+ i_ReturnValue =
+ -8;
+ }
+ } else {
+ /**********************************/
+ /* Base timing selection is wrong */
+ /**********************************/
+
+ DPRINTK("Base timing selection is wrong\n");
+ i_ReturnValue = -7;
+ }
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ else {
+ /**********************************/
+ /* Timing unit selection is wrong */
+ /**********************************/
+
+ DPRINTK("Timing unit selection is wrong\n");
+ i_ReturnValue = -6;
+ } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4))
+ } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+ else {
+ /*****************************************/
+ /* The selected PCI input clock is wrong */
+ /*****************************************/
+
+ DPRINTK("The selected PCI input clock is wrong\n");
+ i_ReturnValue = -5;
+ } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ))
+ } // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)
+ else {
+ /**********************************/
+ /* Tor Counter selection is wrong */
+ /**********************************/
+
+ DPRINTK("Tor Counter selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7)
+ } else {
+ /******************************************/
+ /* The module is not a tor counter module */
+ /******************************************/
+
+ DPRINTK("The module is not a tor counter module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+ data[0] = (UINT) ul_RealTimingInterval;
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_EnableTorCounter |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TorCounter, |
+| BYTE_ b_InputMode, |
+| BYTE_ b_ExternGate, |
+| BYTE_ b_CycleMode, |
+| BYTE_ b_InterruptEnable) |
++----------------------------------------------------------------------------+
+| Task : Enable the tor counter (b_TorCounter) from selected |
+| module (b_ModulNbr). You must calling the |
+| "i_APCI1710_InitTorCounter" function be for you call |
+| this function. |
+| If you enable the tor counter interrupt, the |
+| tor counter generate a interrupt after the timing cycle|
+| See function "i_APCI1710_SetBoardIntRoutineX" and the |
+| Interrupt mask description chapter from this manual. |
+| The b_CycleMode parameter determine if you will |
+| measured a single or more cycle. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
+| BYTE_ b_TorCounter : Tor counter selection (0 or 1). |
+| BYTE_ b_InputMode : Input signal level selection |
+| 0 : Tor count each low level |
+| 1 : Tor count each high level|
+| BYTE_ b_ExternGate : Extern gate action selection |
+| 0 : Extern gate signal not |
+| used |
+| 1 : Extern gate signal used. |
+| If you selected the |
+| single mode, each high |
+| level signal start the |
+| counter. |
+| If you selected the |
+| continuous mode, the |
+| first high level signal |
+| start the tor counter |
+| |
+| APCI1710_TOR_QUADRUPLE _MODE : |
+| In the quadruple mode, the edge|
+| analysis circuit generates a |
+| counting pulse from each edge |
+| of 2 signals which are phase |
+| shifted in relation to each |
+| other. |
+| The gate input is used for the |
+| signal B |
+| |
+| APCI1710_TOR_DOUBLE_MODE: |
+| Functions in the same way as |
+| the quadruple mode, except that|
+| only two of the four edges are |
+| analysed per period. |
+| The gate input is used for the |
+| signal B |
+| |
+| APCI1710_TOR_SIMPLE_MODE: |
+| Functions in the same way as |
+| the quadruple mode, except that|
+| only one of the four edges is |
+| analysed per period. |
+| The gate input is used for the |
+| signal B |
+| |
+| BYTE_ b_CycleMode : Selected the tor counter |
+| acquisition mode |
+| BYTE_ b_InterruptEnable : Enable or disable the |
+| tor counter interrupt. |
+| APCI1710_ENABLE: |
+| Enable the tor counter |
+| interrupt |
+| APCI1710_DISABLE: |
+| Disable the tor counter |
+| interrupt |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a tor counter module |
+| -4: Tor counter selection is wrong |
+| -5: Tor counter not initialised see function |
+| "i_APCI1710_InitTorCounter" |
+| -6: Tor input signal selection is wrong |
+| -7: Extern gate signal mode is wrong |
+| -8: Tor counter acquisition mode cycle is wrong |
+| -9: Interrupt parameter is wrong |
+| -10:Interrupt function not initialised. |
+| See function "i_APCI1710_SetBoardIntRoutineX" |
++----------------------------------------------------------------------------+
+*/
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_DisableTorCounter |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TorCounter) |
++----------------------------------------------------------------------------+
+| Task : Disable the tor counter (b_TorCounter) from selected |
+| module (b_ModulNbr). If you disable the tor counter |
+| after a start cycle occur and you restart the tor |
+| counter witch the " i_APCI1710_EnableTorCounter" |
+| function, the status register is cleared |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
+| BYTE_ b_TorCounter : Tor counter selection (0 or 1). |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a tor counter module |
+| -4: Tor counter selection is wrong |
+| -5: Tor counter not initialised see function |
+| "i_APCI1710_InitTorCounter" |
+| -6: Tor counter not enabled see function |
+| "i_APCI1710_EnableTorCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+ DWORD dw_DummyRead;
+ DWORD dw_ConfigReg;
+ BYTE b_ModulNbr, b_Action;
+ BYTE b_TorCounter;
+ BYTE b_InputMode;
+ BYTE b_ExternGate;
+ BYTE b_CycleMode;
+ BYTE b_InterruptEnable;
+
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_Action = (BYTE) data[0]; // enable or disable
+ b_TorCounter = (BYTE) data[1];
+ b_InputMode = (BYTE) data[2];
+ b_ExternGate = (BYTE) data[3];
+ b_CycleMode = (BYTE) data[4];
+ b_InterruptEnable = (BYTE) data[5];
+ i_ReturnValue = insn->n;;
+ devpriv->tsk_Current = current; // Save the current process task structure
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if tor counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+ /**********************************/
+ /* Test the tor counter selection */
+ /**********************************/
+
+ if (b_TorCounter <= 1) {
+ switch (b_Action) // Enable or Disable
+ {
+ case APCI1710_ENABLE:
+ /***********************************/
+ /* Test if tor counter initialised */
+ /***********************************/
+
+ dw_Status =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 8 +
+ (16 * b_TorCounter) +
+ (64 * b_ModulNbr));
+
+ if (dw_Status & 0x10) {
+ /******************************/
+ /* Test the input signal mode */
+ /******************************/
+
+ if (b_InputMode == 0 ||
+ b_InputMode == 1 ||
+ b_InputMode ==
+ APCI1710_TOR_SIMPLE_MODE
+ || b_InputMode ==
+ APCI1710_TOR_DOUBLE_MODE
+ || b_InputMode ==
+ APCI1710_TOR_QUADRUPLE_MODE)
+ {
+ /************************************/
+ /* Test the extern gate signal mode */
+ /************************************/
+
+ if (b_ExternGate == 0
+ || b_ExternGate
+ == 1
+ || b_InputMode >
+ 1) {
+ /*********************************/
+ /* Test the cycle mode parameter */
+ /*********************************/
+
+ if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) {
+ /***************************/
+ /* Test the interrupt flag */
+ /***************************/
+
+ if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) {
+
+ /***************************/
+ /* Save the interrupt mode */
+ /***************************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo
+ [b_TorCounter].
+ b_InterruptEnable
+ =
+ b_InterruptEnable;
+
+ /*******************/
+ /* Get the command */
+ /*******************/
+
+ dw_ConfigReg
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 4
+ +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ dw_ConfigReg
+ =
+ (dw_ConfigReg
+ >>
+ 4)
+ &
+ 0x30;
+
+ /********************************/
+ /* Test if not direct mode used */
+ /********************************/
+
+ if (b_InputMode > 1) {
+ /*******************************/
+ /* Extern gate can not be used */
+ /*******************************/
+
+ b_ExternGate
+ =
+ 0;
+
+ /*******************************************/
+ /* Enable the extern gate for the Signal B */
+ /*******************************************/
+
+ dw_ConfigReg
+ =
+ dw_ConfigReg
+ |
+ 0x40;
+
+ /***********************/
+ /* Test if simple mode */
+ /***********************/
+
+ if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) {
+ /**************************/
+ /* Enable the sinple mode */
+ /**************************/
+
+ dw_ConfigReg
+ =
+ dw_ConfigReg
+ |
+ 0x780;
+
+ } // if (b_InputMode == APCI1710_TOR_SIMPLE_MODE)
+
+ /***********************/
+ /* Test if double mode */
+ /***********************/
+
+ if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) {
+ /**************************/
+ /* Enable the double mode */
+ /**************************/
+
+ dw_ConfigReg
+ =
+ dw_ConfigReg
+ |
+ 0x180;
+
+ } // if (b_InputMode == APCI1710_TOR_DOUBLE_MODE)
+
+ b_InputMode
+ =
+ 0;
+ } // if (b_InputMode > 1)
+
+ /*******************/
+ /* Set the command */
+ /*******************/
+
+ dw_ConfigReg
+ =
+ dw_ConfigReg
+ |
+ b_CycleMode
+ |
+ (b_InterruptEnable
+ *
+ 2)
+ |
+ (b_InputMode
+ *
+ 4)
+ |
+ (b_ExternGate
+ *
+ 8);
+
+ /*****************************/
+ /* Clear the status register */
+ /*****************************/
+
+ dw_DummyRead
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 0
+ +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ /***************************************/
+ /* Clear the interrupt status register */
+ /***************************************/
+
+ dw_DummyRead
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 12
+ +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ /********************/
+ /* Set the commando */
+ /********************/
+
+ outl(dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ /****************/
+ /* Set the gate */
+ /****************/
+
+ outl(1, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+ else {
+ /********************************/
+ /* Interrupt parameter is wrong */
+ /********************************/
+
+ DPRINTK("Interrupt parameter is wrong\n");
+ i_ReturnValue
+ =
+ -9;
+ } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE))
+ } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+ else {
+ /***********************************************/
+ /* Tor counter acquisition mode cycle is wrong */
+ /***********************************************/
+
+ DPRINTK("Tor counter acquisition mode cycle is wrong\n");
+ i_ReturnValue
+ =
+ -8;
+ } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS))
+ } // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+ else {
+ /***********************************/
+ /* Extern gate input mode is wrong */
+ /***********************************/
+
+ DPRINTK("Extern gate input mode is wrong\n");
+ i_ReturnValue =
+ -7;
+ } // if (b_ExternGate >= 0 && b_ExternGate <= 1)
+ } // if (b_InputMode >= 0 && b_InputMode <= 1)
+ else {
+ /***************************************/
+ /* Tor input signal selection is wrong */
+ /***************************************/
+
+ DPRINTK("Tor input signal selection is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /*******************************/
+ /* Tor counter not initialised */
+ /*******************************/
+
+ DPRINTK("Tor counter not initialised\n");
+ i_ReturnValue = -5;
+ }
+ break;
+
+ case APCI1710_DISABLE:
+ /***********************************/
+ /* Test if tor counter initialised */
+ /***********************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 8 +
+ (16 * b_TorCounter) +
+ (64 * b_ModulNbr));
+
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (dw_Status & 0x10) {
+ /***************************/
+ /* Test if counter enabled */
+ /***************************/
+
+ if (dw_Status & 0x1) {
+ /****************************/
+ /* Clear the interrupt mode */
+ /****************************/
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo
+ [b_TorCounter].
+ b_InterruptEnable
+ =
+ APCI1710_DISABLE;
+
+ /******************/
+ /* Clear the gate */
+ /******************/
+
+ outl(0, devpriv->
+ s_BoardInfos.
+ ui_Address + 8 +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+ } // if (dw_Status & 0x1)
+ else {
+ /***************************/
+ /* Tor counter not enabled */
+ /***************************/
+
+ DPRINTK("Tor counter not enabled \n");
+ i_ReturnValue = -6;
+ } // if (dw_Status & 0x1)
+ } // if (dw_Status & 0x10)
+ else {
+ /*******************************/
+ /* Tor counter not initialised */
+ /*******************************/
+
+ DPRINTK("Tor counter not initialised\n");
+ i_ReturnValue = -5;
+ } // // if (dw_Status & 0x10)
+
+ } // switch
+ } // if (b_TorCounter <= 1)
+ else {
+ /**********************************/
+ /* Tor counter selection is wrong */
+ /**********************************/
+
+ DPRINTK("Tor counter selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_TorCounter <= 1)
+ } else {
+ /******************************************/
+ /* The module is not a tor counter module */
+ /******************************************/
+
+ DPRINTK("The module is not a tor counter module \n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error \n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_GetTorCounterInitialisation |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TorCounter, |
+| PBYTE_ pb_TimingUnit, |
+| PULONG_ pul_TimingInterval, |
+| PBYTE_ pb_InputMode, |
+| PBYTE_ pb_ExternGate, |
+| PBYTE_ pb_CycleMode, |
+| PBYTE_ pb_Enable, |
+| PBYTE_ pb_InterruptEnable)|
++----------------------------------------------------------------------------+
+| Task : Enable the tor counter (b_TorCounter) from selected |
+| module (b_ModulNbr). You must calling the |
+| "i_APCI1710_InitTorCounter" function be for you call |
+| this function. |
+| If you enable the tor counter interrupt, the |
+| tor counter generate a interrupt after the timing cycle|
+| See function "i_APCI1710_SetBoardIntRoutineX" and the |
+| Interrupt mask description chapter from this manual. |
+| The b_CycleMode parameter determine if you will |
+| measured a single or more cycle. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
+| BYTE_ b_TorCounter : Tor counter selection (0 or 1)
+
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_TorCounter = CR_CHAN(insn->chanspec);
+. |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_TimingUnit : Base timing unit (0 to 4) |
+| 0 : ns |
+| 1 : µs |
+| 2 : ms |
+| 3 : s |
+| 4 : mn |
+| PULONG_ pul_TimingInterval : Base timing value. |
+| PBYTE_ pb_InputMode : Input signal level |
+| selection |
+| 0 : Tor count each low level |
+| 1 : Tor count each high level|
+| PBYTE_ pb_ExternGate : Extern gate action |
+| selection |
+| 0 : Extern gate signal not |
+| used |
+| 1 : Extern gate signal used|
+| PBYTE_ pb_CycleMode : Tor counter acquisition |
+| mode |
+| PBYTE_ pb_Enable : Indicate if the tor counter|
+| is enabled or no |
+| 0 : Tor counter disabled |
+| 1 : Tor counter enabled |
+| PBYTE_ pb_InterruptEnable : Enable or disable the |
+| tor counter interrupt. |
+| APCI1710_ENABLE: |
+| Enable the tor counter |
+| interrupt |
+| APCI1710_DISABLE: |
+| Disable the tor counter |
+| interrupt
+ pb_TimingUnit = (PBYTE) &data[0];
+ pul_TimingInterval = (PULONG) &data[1];
+ pb_InputMode = (PBYTE) &data[2];
+ pb_ExternGate = (PBYTE) &data[3];
+ pb_CycleMode = (PBYTE) &data[4];
+ pb_Enable = (PBYTE) &data[5];
+ pb_InterruptEnable = (PBYTE) &data[6];
+ |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a tor counter module |
+| -4: Tor counter selection is wrong |
+| -5: Tor counter not initialised see function |
+| "i_APCI1710_InitTorCounter" |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+ BYTE b_ModulNbr;
+ BYTE b_TorCounter;
+ PBYTE pb_TimingUnit;
+ PULONG pul_TimingInterval;
+ PBYTE pb_InputMode;
+ PBYTE pb_ExternGate;
+ PBYTE pb_CycleMode;
+ PBYTE pb_Enable;
+ PBYTE pb_InterruptEnable;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_TorCounter = CR_CHAN(insn->chanspec);
+
+ pb_TimingUnit = (PBYTE) & data[0];
+ pul_TimingInterval = (PULONG) & data[1];
+ pb_InputMode = (PBYTE) & data[2];
+ pb_ExternGate = (PBYTE) & data[3];
+ pb_CycleMode = (PBYTE) & data[4];
+ pb_Enable = (PBYTE) & data[5];
+ pb_InterruptEnable = (PBYTE) & data[6];
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if tor counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+ /**********************************/
+ /* Test the tor counter selection */
+ /**********************************/
+
+ if (b_TorCounter <= 1) {
+
+ /***********************************/
+ /* Test if tor counter initialised */
+ /***********************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 8 + (16 * b_TorCounter) +
+ (64 * b_ModulNbr));
+
+ if (dw_Status & 0x10) {
+ *pb_Enable = dw_Status & 1;
+
+ /********************/
+ /* Get the commando */
+ /********************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 4 +
+ (16 * b_TorCounter) +
+ (64 * b_ModulNbr));
+
+ *pb_CycleMode =
+ (BYTE) ((dw_Status >> 4) & 1);
+ *pb_InterruptEnable =
+ (BYTE) ((dw_Status >> 5) & 1);
+
+ /******************************************************/
+ /* Test if extern gate used for clock or for signal B */
+ /******************************************************/
+
+ if (dw_Status & 0x600) {
+ /*****************************************/
+ /* Test if extern gate used for signal B */
+ /*****************************************/
+
+ if (dw_Status & 0x400) {
+ /***********************/
+ /* Test if simple mode */
+ /***********************/
+
+ if ((dw_Status & 0x7800)
+ == 0x7800) {
+ *pb_InputMode =
+ APCI1710_TOR_SIMPLE_MODE;
+ }
+
+ /***********************/
+ /* Test if double mode */
+ /***********************/
+
+ if ((dw_Status & 0x7800)
+ == 0x1800) {
+ *pb_InputMode =
+ APCI1710_TOR_DOUBLE_MODE;
+ }
+
+ /**************************/
+ /* Test if quadruple mode */
+ /**************************/
+
+ if ((dw_Status & 0x7800)
+ == 0x0000) {
+ *pb_InputMode =
+ APCI1710_TOR_QUADRUPLE_MODE;
+ }
+ } // if (dw_Status & 0x400)
+ else {
+ *pb_InputMode = 1;
+ } // // if (dw_Status & 0x400)
+
+ /************************/
+ /* Extern gate not used */
+ /************************/
+
+ *pb_ExternGate = 0;
+ } // if (dw_Status & 0x600)
+ else {
+ *pb_InputMode =
+ (BYTE) ((dw_Status >> 6)
+ & 1);
+ *pb_ExternGate =
+ (BYTE) ((dw_Status >> 7)
+ & 1);
+ } // if (dw_Status & 0x600)
+
+ *pb_TimingUnit =
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo[b_TorCounter].
+ b_TimingUnit;
+
+ *pul_TimingInterval =
+ devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo[b_TorCounter].
+ ul_RealTimingInterval;
+ } else {
+ /*******************************/
+ /* Tor counter not initialised */
+ /*******************************/
+
+ DPRINTK("Tor counter not initialised\n");
+ i_ReturnValue = -5;
+ }
+
+ } // if (b_TorCounter <= 1)
+ else {
+ /**********************************/
+ /* Tor counter selection is wrong */
+ /**********************************/
+
+ DPRINTK("Tor counter selection is wrong \n");
+ i_ReturnValue = -4;
+ } // if (b_TorCounter <= 1)
+ } else {
+ /******************************************/
+ /* The module is not a tor counter module */
+ /******************************************/
+
+ DPRINTK("The module is not a tor counter module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadTorCounterValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_TorCounter, |
+| UINT_ ui_TimeOut, |
+| PBYTE_ pb_TorCounterStatus, |
+| PULONG_ pul_TorCounterValue) |
++----------------------------------------------------------------------------+
+| Task case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter
+(b_TorCounter) status (pb_TorCounterStatus) from selected tor counter |
+| module (b_ModulNbr).
+
+ case APCI1710_TOR_GETCOUNTERVALUE :
+ Return the tor counter (b_TorCounter) status |
+| (pb_TorCounterStatus) and the timing value |
+| (pul_TorCounterValue) after a conting cycle stop |
+| from selected tor counter module (b_ModulNbr). |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3) |
+| BYTE_ b_TorCounter : Tor counter selection (0 or 1).
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_ReadType = (BYTE) data[0];
+ b_TorCounter = (BYTE) data[1];
+ ui_TimeOut = (UINT) data[2]; |
++----------------------------------------------------------------------------+
+| Output Parameters : PBYTE_ pb_TorCounterStatus : Return the tor counter |
+| status. |
+| 0 : Conting cycle not started|
+| Software gate not set. |
+| 1 : Conting cycle started. |
+| Software gate set. |
+| 2 : Conting cycle stopped. |
+| The conting cycle is |
+| terminate. |
+| 3 : A overflow occur. You |
+| must change the base |
+| timing witch the |
+| function |
+| "i_APCI1710_InitTorCounter"|
+| 4 : Timeeout occur |
+| PULONG pul_TorCounterValue : Tor counter value.
+ pb_TorCounterStatus=(PBYTE) &data[0];
+ pul_TorCounterValue=(PULONG) &data[1]; |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: Module selection wrong |
+| -3: The module is not a tor counter module |
+| -4: Tor counter selection is wrong |
+| -5: Tor counter not initialised see function |
+| "i_APCI1710_InitTorCounter" |
+| -6: Tor counter not enabled see function |
+| "i_APCI1710_EnableTorCounter" |
+| -7: Timeout parameter is wrong (0 to 65535) |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_Status;
+ DWORD dw_TimeOut = 0;
+
+ BYTE b_ModulNbr;
+ BYTE b_TorCounter;
+ BYTE b_ReadType;
+ UINT ui_TimeOut;
+ PBYTE pb_TorCounterStatus;
+ PULONG pul_TorCounterValue;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_ReadType = (BYTE) data[0];
+ b_TorCounter = (BYTE) data[1];
+ ui_TimeOut = (UINT) data[2];
+ pb_TorCounterStatus = (PBYTE) & data[0];
+ pul_TorCounterValue = (PULONG) & data[1];
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ReadType == APCI1710_TOR_READINTERRUPT) {
+
+ data[0] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].b_OldModuleMask;
+ data[1] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+ data[2] = devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+ /**************************/
+ /* Increment the read FIFO */
+ /***************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Read = (devpriv->
+ s_InterruptParameters.
+ ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+ return insn->n;
+ }
+
+ if (b_ModulNbr < 4) {
+ /***********************/
+ /* Test if tor counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+ /**********************************/
+ /* Test the tor counter selection */
+ /**********************************/
+
+ if (b_TorCounter <= 1) {
+ /***********************************/
+ /* Test if tor counter initialised */
+ /***********************************/
+
+ dw_Status = inl(devpriv->s_BoardInfos.
+ ui_Address + 8 + (16 * b_TorCounter) +
+ (64 * b_ModulNbr));
+
+ /*******************************/
+ /* Test if counter initialised */
+ /*******************************/
+
+ if (dw_Status & 0x10) {
+ /***************************/
+ /* Test if counter enabled */
+ /***************************/
+
+ if (dw_Status & 0x1) {
+
+ switch (b_ReadType) {
+
+ case APCI1710_TOR_GETPROGRESSSTATUS:
+ /*******************/
+ /* Read the status */
+ /*******************/
+
+ dw_Status =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 4 +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ dw_Status =
+ dw_Status & 0xF;
+
+ /*****************/
+ /* Test if start */
+ /*****************/
+
+ if (dw_Status & 1) {
+ if (dw_Status &
+ 2) {
+ if (dw_Status & 4) {
+ /************************/
+ /* Tor counter owerflow */
+ /************************/
+
+ *pb_TorCounterStatus
+ =
+ 3;
+ } else {
+ /***********************/
+ /* Tor counter started */
+ /***********************/
+
+ *pb_TorCounterStatus
+ =
+ 2;
+ }
+ } else {
+ /***********************/
+ /* Tor counter started */
+ /***********************/
+
+ *pb_TorCounterStatus
+ =
+ 1;
+ }
+ } else {
+ /***************************/
+ /* Tor counter not started */
+ /***************************/
+
+ *pb_TorCounterStatus
+ = 0;
+ }
+ break;
+
+ case APCI1710_TOR_GETCOUNTERVALUE:
+
+ /*****************************/
+ /* Test the timout parameter */
+ /*****************************/
+
+ if ((ui_TimeOut >= 0)
+ && (ui_TimeOut
+ <=
+ 65535UL))
+ {
+ for (;;) {
+ /*******************/
+ /* Read the status */
+ /*******************/
+
+ dw_Status
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 4
+ +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+ /********************/
+ /* Test if overflow */
+ /********************/
+
+ if ((dw_Status & 4) == 4) {
+ /******************/
+ /* Overflow occur */
+ /******************/
+
+ *pb_TorCounterStatus
+ =
+ 3;
+
+ /******************/
+ /* Read the value */
+ /******************/
+
+ *pul_TorCounterValue
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 0
+ +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+ break;
+ } // if ((dw_Status & 4) == 4)
+ else {
+ /*******************************/
+ /* Test if measurement stopped */
+ /*******************************/
+
+ if ((dw_Status & 2) == 2) {
+ /***********************/
+ /* A stop signal occur */
+ /***********************/
+
+ *pb_TorCounterStatus
+ =
+ 2;
+
+ /******************/
+ /* Read the value */
+ /******************/
+
+ *pul_TorCounterValue
+ =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ 0
+ +
+ (16 * b_TorCounter) + (64 * b_ModulNbr));
+
+ break;
+ } // if ((dw_Status & 2) == 2)
+ else {
+ /*******************************/
+ /* Test if measurement started */
+ /*******************************/
+
+ if ((dw_Status & 1) == 1) {
+ /************************/
+ /* A start signal occur */
+ /************************/
+
+ *pb_TorCounterStatus
+ =
+ 1;
+ } // if ((dw_Status & 1) == 1)
+ else {
+ /***************************/
+ /* Measurement not started */
+ /***************************/
+
+ *pb_TorCounterStatus
+ =
+ 0;
+ } // if ((dw_Status & 1) == 1)
+ } // if ((dw_Status & 2) == 2)
+ } // if ((dw_Status & 8) == 8)
+
+ if (dw_TimeOut == ui_TimeOut) {
+ /*****************/
+ /* Timeout occur */
+ /*****************/
+
+ break;
+ } else {
+ /*************************/
+ /* Increment the timeout */
+ /*************************/
+
+ dw_TimeOut
+ =
+ dw_TimeOut
+ +
+ 1;
+
+ mdelay(1000);
+ }
+ } // for (;;)
+
+ /*************************/
+ /* Test if timeout occur */
+ /*************************/
+
+ if ((*pb_TorCounterStatus != 3) && (dw_TimeOut == ui_TimeOut) && (ui_TimeOut != 0)) {
+ /*****************/
+ /* Timeout occur */
+ /*****************/
+
+ *pb_TorCounterStatus
+ =
+ 4;
+ }
+ } else {
+ /******************************/
+ /* Timeout parameter is wrong */
+ /******************************/
+
+ DPRINTK("Timeout parameter is wrong\n");
+ i_ReturnValue =
+ -7;
+ }
+ break;
+
+ default:
+ printk("Inputs wrong\n");
+ } // switch end
+ } // if (dw_Status & 0x1)
+ else {
+ /***************************/
+ /* Tor counter not enabled */
+ /***************************/
+
+ DPRINTK("Tor counter not enabled\n");
+ i_ReturnValue = -6;
+ } // if (dw_Status & 0x1)
+ } else {
+ /*******************************/
+ /* Tor counter not initialised */
+ /*******************************/
+
+ DPRINTK("Tor counter not initialised\n");
+ i_ReturnValue = -5;
+ }
+ } // if (b_TorCounter <= 1)
+ else {
+ /**********************************/
+ /* Tor counter selection is wrong */
+ /**********************************/
+
+ DPRINTK("Tor counter selection is wrong\n");
+ i_ReturnValue = -4;
+ } // if (b_TorCounter <= 1)
+ } else {
+ /******************************************/
+ /* The module is not a tor counter module */
+ /******************************************/
+
+ DPRINTK("The module is not a tor counter module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
new file mode 100644
index 000000000000..c245d16207b8
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_30MHZ 30
+#define APCI1710_33MHZ 33
+#define APCI1710_40MHZ 40
+
+#define APCI1710_GATE_INPUT 10
+
+#define APCI1710_TOR_SIMPLE_MODE 2
+#define APCI1710_TOR_DOUBLE_MODE 3
+#define APCI1710_TOR_QUADRUPLE_MODE 4
+
+#define APCI1710_SINGLE 0
+#define APCI1710_CONTINUOUS 1
+
+#define APCI1710_TOR_GETPROGRESSSTATUS 0
+#define APCI1710_TOR_GETCOUNTERVALUE 1
+#define APCI1710_TOR_READINTERRUPT 2
+
+/*
+ * TOR_COUNTER INISIALISATION FUNCTION
+ */
+INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+/*
+ * TOR_COUNTER READ FUNCTION
+ */
+INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
new file mode 100644
index 000000000000..68b1d26bae13
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
@@ -0,0 +1,1038 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1710 | Compiler : gcc |
+ | Module name : TTL.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-1710 TTL I/O module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | 13/05/98 | S. Weber | TTL digital input / output implementation |
+ |----------|-----------|------------------------------------------------|
+ | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
+ | | | available |
+ +-----------------------------------------------------------------------+
+ | | | |
+ | | | |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "APCI1710_Ttl.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_InitTTLIODirection |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_PortAMode, |
+| BYTE_ b_PortBMode, |
+| BYTE_ b_PortCMode, |
+| BYTE_ b_PortDMode) |
++----------------------------------------------------------------------------+
+| Task APCI1710_TTL_INIT (using defaults) : Configure the TTL I/O operating mode from selected |
+| module (b_ModulNbr). You must calling this function be|
+| for you call any other function witch access of TTL. |
+ APCI1710_TTL_INITDIRECTION(user inputs for direction)
+
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3)
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_InitType = (BYTE) data[0];
+ b_PortAMode = (BYTE) data[1];
+ b_PortBMode = (BYTE) data[2];
+ b_PortCMode = (BYTE) data[3];
+ b_PortDMode = (BYTE) data[4];|
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a TTL module |
+| -4: Function not available for this version |
+| -5: Port A mode selection is wrong |
+| -6: Port B mode selection is wrong |
+| -7: Port C mode selection is wrong |
+| -8: Port D mode selection is wrong |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ BYTE b_ModulNbr;
+ BYTE b_InitType;
+ BYTE b_PortAMode;
+ BYTE b_PortBMode;
+ BYTE b_PortCMode;
+ BYTE b_PortDMode;
+
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ b_InitType = (BYTE) data[0];
+ i_ReturnValue = insn->n;
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /**************************/
+ /* Test if TTL I/O module */
+ /**************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TTL_IO) {
+ switch (b_InitType) {
+ case APCI1710_TTL_INIT:
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_TTLInit = 1;
+
+ /***************************/
+ /* Set TTL port A to input */
+ /***************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_PortConfiguration[0] = 0;
+
+ /***************************/
+ /* Set TTL port B to input */
+ /***************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_PortConfiguration[1] = 0;
+
+ /***************************/
+ /* Set TTL port C to input */
+ /***************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_PortConfiguration[2] = 0;
+
+ /****************************/
+ /* Set TTL port D to output */
+ /****************************/
+
+ devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_PortConfiguration[3] = 1;
+
+ /*************************/
+ /* Set the configuration */
+ /*************************/
+
+ outl(0x8,
+ devpriv->s_BoardInfos.ui_Address + 20 +
+ (64 * b_ModulNbr));
+ break;
+
+ case APCI1710_TTL_INITDIRECTION:
+
+ b_PortAMode = (BYTE) data[1];
+ b_PortBMode = (BYTE) data[2];
+ b_PortCMode = (BYTE) data[3];
+ b_PortDMode = (BYTE) data[4];
+
+ /********************/
+ /* Test the version */
+ /********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] & 0xFFFF) >=
+ 0x3230) {
+ /************************/
+ /* Test the port A mode */
+ /************************/
+
+ if ((b_PortAMode == 0)
+ || (b_PortAMode == 1)) {
+ /************************/
+ /* Test the port B mode */
+ /************************/
+
+ if ((b_PortBMode == 0)
+ || (b_PortBMode == 1)) {
+ /************************/
+ /* Test the port C mode */
+ /************************/
+
+ if ((b_PortCMode == 0)
+ || (b_PortCMode
+ == 1)) {
+ /************************/
+ /* Test the port D mode */
+ /************************/
+
+ if ((b_PortDMode == 0) || (b_PortDMode == 1)) {
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_TTLInit
+ =
+ 1;
+
+ /***********************/
+ /* Set TTL port A mode */
+ /***********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [0]
+ =
+ b_PortAMode;
+
+ /***********************/
+ /* Set TTL port B mode */
+ /***********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [1]
+ =
+ b_PortBMode;
+
+ /***********************/
+ /* Set TTL port C mode */
+ /***********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [2]
+ =
+ b_PortCMode;
+
+ /***********************/
+ /* Set TTL port D mode */
+ /***********************/
+
+ devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [3]
+ =
+ b_PortDMode;
+
+ /*************************/
+ /* Set the configuration */
+ /*************************/
+
+ outl((b_PortAMode << 0) | (b_PortBMode << 1) | (b_PortCMode << 2) | (b_PortDMode << 3), devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr));
+ } else {
+ /**********************************/
+ /* Port D mode selection is wrong */
+ /**********************************/
+
+ DPRINTK("Port D mode selection is wrong\n");
+ i_ReturnValue
+ =
+ -8;
+ }
+ } else {
+ /**********************************/
+ /* Port C mode selection is wrong */
+ /**********************************/
+
+ DPRINTK("Port C mode selection is wrong\n");
+ i_ReturnValue =
+ -7;
+ }
+ } else {
+ /**********************************/
+ /* Port B mode selection is wrong */
+ /**********************************/
+
+ DPRINTK("Port B mode selection is wrong\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /**********************************/
+ /* Port A mode selection is wrong */
+ /**********************************/
+
+ DPRINTK("Port A mode selection is wrong\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /*******************************************/
+ /* Function not available for this version */
+ /*******************************************/
+
+ DPRINTK("Function not available for this version\n");
+ i_ReturnValue = -4;
+ }
+ break;
+
+ DPRINTK("\n");
+ default:
+ printk("Bad Config Type\n");
+ } // switch end
+ } else {
+ /**********************************/
+ /* The module is not a TTL module */
+ /**********************************/
+
+ DPRINTK("The module is not a TTL module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| INPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_ReadTTLIOChannelValue |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_SelectedPort, |
+| BYTE_ b_InputChannel, |
+| PBYTE_ pb_ChannelStatus) |
++----------------------------------------------------------------------------+
+| Task : Read the status from selected TTL digital input |
+| (b_InputChannel)
++----------------------------------------------------------------------------+
+| Task : Read the status from digital input port |
+| (b_SelectedPort) from selected TTL module (b_ModulNbr) |
++----------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 7) |
+| BYTE_ b_SelectedPort, : Selection from TTL I/O |
+| port (0 to 2) |
+| 0 : Port A selection |
+| 1 : Port B selection |
+| 2 : Port C selection |
+| 3 : Port D selection |
+| BYTE_ b_InputChannel : Selection from digital |
+| input ( 0 to 2)
+APCI1710_TTL_READCHANNEL
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_SelectedPort= CR_RANGE(insn->chanspec);
+ b_InputChannel= CR_CHAN(insn->chanspec);
+ b_ReadType = (BYTE) data[0];
+
+ APCI1710_TTL_READPORT|
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_SelectedPort= CR_RANGE(insn->chanspec);
+ b_ReadType = (BYTE) data[0];
+
++----------------------------------------------------------------------------+
+| Output Parameters : data[0]
+
+ PBYTE_ pb_ChannelStatus : Digital input channel |
+| status |
+| 0 : Channle is not active|
+| 1 : Channle is active |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a TTL module |
+| -4: The selected TTL input port is wrong |
+| -5: The selected TTL digital input is wrong |
+| -6: TTL I/O not initialised |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg;
+ BYTE b_ModulNbr;
+ BYTE b_SelectedPort;
+ BYTE b_InputChannel;
+ BYTE b_ReadType;
+ PBYTE pb_ChannelStatus;
+ PBYTE pb_PortValue;
+
+ i_ReturnValue = insn->n;
+ b_ReadType = (BYTE) data[0];
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_SelectedPort = CR_RANGE(insn->chanspec);
+ b_InputChannel = CR_CHAN(insn->chanspec);
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /**************************/
+ /* Test if TTL I/O module */
+ /**************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TTL_IO) {
+ switch (b_ReadType) {
+
+ case APCI1710_TTL_READCHANNEL:
+ pb_ChannelStatus = (PBYTE) & data[0];
+ /********************************/
+ /* Test the TTL I/O port number */
+ /********************************/
+
+ if (((b_SelectedPort <= 2)
+ && ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] &
+ 0xFFFF) ==
+ 0x3130))
+ || ((b_SelectedPort <= 3)
+ && ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] &
+ 0xFFFF) >=
+ 0x3230))) {
+ /******************************************/
+ /* Test the digital imnput channel number */
+ /******************************************/
+
+ if (((b_InputChannel <= 7)
+ && (b_SelectedPort < 3))
+ || ((b_InputChannel <= 1)
+ && (b_SelectedPort ==
+ 3))) {
+ /******************************************/
+ /* Test if the TTL I/O module initialised */
+ /******************************************/
+
+ if (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.b_TTLInit ==
+ 1) {
+ /***********************************/
+ /* Test if TTL port used for input */
+ /***********************************/
+
+ if (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) == 0x3130) || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) {
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+
+ dw_StatusReg =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ (64 * b_ModulNbr));
+
+ *pb_ChannelStatus
+ =
+ (BYTE) (
+ (dw_StatusReg
+ >>
+ (8 * b_SelectedPort)) >> b_InputChannel) & 1;
+ } else {
+ /*******************************/
+ /* Selected TTL I/O port error */
+ /*******************************/
+
+ DPRINTK("Selected TTL I/O port error\n");
+ i_ReturnValue =
+ -4;
+ }
+ } else {
+ /***************************/
+ /* TTL I/O not initialised */
+ /***************************/
+
+ DPRINTK("TTL I/O not initialised\n");
+ i_ReturnValue = -6;
+ }
+ } else {
+ /********************************/
+ /* Selected digital input error */
+ /********************************/
+
+ DPRINTK("Selected digital input error\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /*******************************/
+ /* Selected TTL I/O port error */
+ /*******************************/
+
+ DPRINTK("Selected TTL I/O port error\n");
+ i_ReturnValue = -4;
+ }
+ break;
+
+ case APCI1710_TTL_READPORT:
+ pb_PortValue = (PBYTE) & data[0];
+ /********************************/
+ /* Test the TTL I/O port number */
+ /********************************/
+
+ if (((b_SelectedPort <= 2)
+ && ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] &
+ 0xFFFF) ==
+ 0x3130))
+ || ((b_SelectedPort <= 3)
+ && ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] &
+ 0xFFFF) >=
+ 0x3230))) {
+ /******************************************/
+ /* Test if the TTL I/O module initialised */
+ /******************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_TTLInit == 1) {
+ /***********************************/
+ /* Test if TTL port used for input */
+ /***********************************/
+
+ if (((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr]
+ &
+ 0xFFFF)
+ == 0x3130)
+ || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) {
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+
+ dw_StatusReg =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address +
+ (64 * b_ModulNbr));
+
+ *pb_PortValue =
+ (BYTE) (
+ (dw_StatusReg >>
+ (8 * b_SelectedPort)) & 0xFF);
+ } else {
+ /*******************************/
+ /* Selected TTL I/O port error */
+ /*******************************/
+
+ DPRINTK("Selected TTL I/O port error\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /***************************/
+ /* TTL I/O not initialised */
+ /***************************/
+
+ DPRINTK("TTL I/O not initialised\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /*******************************/
+ /* Selected TTL I/O port error */
+ /*******************************/
+
+ DPRINTK("Selected TTL I/O port error\n");
+ i_ReturnValue = -4;
+ }
+ break;
+
+ default:
+ printk("Bad ReadType\n");
+
+ } //End Switch
+ } else {
+ /**********************************/
+ /* The module is not a TTL module */
+ /**********************************/
+
+ DPRINTK("The module is not a TTL module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device
+*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read the status from all digital input ports |
+| (port A, port B and port C) from selected TTL |
+| module (b_ModulNbr) |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
+| BYTE_ b_ModulNbr : Module number to |
+| configure (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : PULONG_ pul_PortValue : Digital TTL inputs port |
+| status |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a TTL module |
+| -4: TTL I/O not initialised |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg;
+ BYTE b_ModulNbr;
+ PULONG pul_PortValue;
+
+ b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
+ i_ReturnValue = insn->n;
+ pul_PortValue = (PULONG) & data[0];
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /**************************/
+ /* Test if TTL I/O module */
+ /**************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TTL_IO) {
+ /******************************************/
+ /* Test if the TTL I/O module initialised */
+ /******************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_TTLInit == 1) {
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+
+ dw_StatusReg = inl(devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModulNbr));
+
+ /**********************/
+ /* Test if TTL Rev1.0 */
+ /**********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] & 0xFFFF) ==
+ 0x3130) {
+ *pul_PortValue =
+ dw_StatusReg & 0xFFFFFFUL;
+ } else {
+ /**************************************/
+ /* Test if port A not used for output */
+ /**************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration[0] == 1) {
+ *pul_PortValue =
+ dw_StatusReg &
+ 0x3FFFF00UL;
+ }
+
+ /**************************************/
+ /* Test if port B not used for output */
+ /**************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration[1] == 1) {
+ *pul_PortValue =
+ dw_StatusReg &
+ 0x3FF00FFUL;
+ }
+
+ /**************************************/
+ /* Test if port C not used for output */
+ /**************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration[2] == 1) {
+ *pul_PortValue =
+ dw_StatusReg &
+ 0x300FFFFUL;
+ }
+
+ /**************************************/
+ /* Test if port D not used for output */
+ /**************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration[3] == 1) {
+ *pul_PortValue =
+ dw_StatusReg &
+ 0xFFFFFFUL;
+ }
+ }
+ } else {
+ /***************************/
+ /* TTL I/O not initialised */
+ /***************************/
+ DPRINTK("TTL I/O not initialised\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /**********************************/
+ /* The module is not a TTL module */
+ /**********************************/
+ DPRINTK("The module is not a TTL module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| OUTPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : _INT_ i_APCI1710_SetTTLIOChlOn |
+| (BYTE_ b_BoardHandle, |
+| BYTE_ b_ModulNbr, |
+| BYTE_ b_OutputChannel)
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Sets or resets the output witch has been passed with the |
+| parameter b_Channel. Setting an output means setting |
+| an ouput high. |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 |
+| BYTE_ b_ModulNbr : Selected module number (0 to 3)|
+| BYTE_ b_OutputChannel : Selection from digital output |
+| channel (0 or 1) |
+| 0 : PD0 |
+| 1 : PD1 |
+| 2 to 9 : PA |
+| 10 to 17: PB |
+| 18 to 25: PC |
+
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_OutputChannel= CR_CHAN(insn->chanspec);
+ ui_State = data[0]; // ON or OFF
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -1: The handle parameter of the board is wrong |
+| -2: The module parameter is wrong |
+| -3: The module is not a TTL I/O module |
+| -4: The selected digital output is wrong |
+| -5: TTL I/O not initialised see function |
+| " i_APCI1710_InitTTLIO"
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = 0;
+ DWORD dw_StatusReg = 0;
+ BYTE b_ModulNbr;
+ BYTE b_OutputChannel;
+ UINT ui_State;
+
+ i_ReturnValue = insn->n;
+ b_ModulNbr = CR_AREF(insn->chanspec);
+ b_OutputChannel = CR_CHAN(insn->chanspec);
+ ui_State = data[0]; // ON or OFF
+
+ /**************************/
+ /* Test the module number */
+ /**************************/
+
+ if (b_ModulNbr < 4) {
+ /**************************/
+ /* Test if TTL I/O module */
+ /**************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModulNbr] &
+ 0xFFFF0000UL) == APCI1710_TTL_IO) {
+ /******************************************/
+ /* Test if the TTL I/O module initialised */
+ /******************************************/
+
+ if (devpriv->s_ModuleInfo[b_ModulNbr].
+ s_TTLIOInfo.b_TTLInit == 1) {
+ /***********************************/
+ /* Test the TTL I/O channel number */
+ /***********************************/
+
+ if (((b_OutputChannel <= 1)
+ && ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] &
+ 0xFFFF) ==
+ 0x3130))
+ || ((b_OutputChannel <= 25)
+ && ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration
+ [b_ModulNbr] &
+ 0xFFFF) >=
+ 0x3230))) {
+ /****************************************************/
+ /* Test if the selected channel is a output channel */
+ /****************************************************/
+
+ if (((b_OutputChannel <= 1)
+ && (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [3] == 1))
+ || ((b_OutputChannel >= 2)
+ && (b_OutputChannel <=
+ 9)
+ && (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [0] == 1))
+ || ((b_OutputChannel >= 10)
+ && (b_OutputChannel <=
+ 17)
+ && (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [1] == 1))
+ || ((b_OutputChannel >= 18)
+ && (b_OutputChannel <=
+ 25)
+ && (devpriv->
+ s_ModuleInfo
+ [b_ModulNbr].
+ s_TTLIOInfo.
+ b_PortConfiguration
+ [2] == 1))) {
+ /************************/
+ /* Test if PD0 selected */
+ /************************/
+
+ if (b_OutputChannel == 0) {
+
+ outl(ui_State,
+ devpriv->
+ s_BoardInfos.
+ ui_Address +
+ (64 * b_ModulNbr));
+ } else {
+ /************************/
+ /* Test if PD1 selected */
+ /************************/
+
+ if (b_OutputChannel ==
+ 1) {
+
+ outl(ui_State,
+ devpriv->
+ s_BoardInfos.
+ ui_Address
+ + 4 +
+ (64 * b_ModulNbr));
+ } else {
+ b_OutputChannel
+ =
+ b_OutputChannel
+ - 2;
+
+ /********************/
+ /* Read all channel */
+ /********************/
+
+ dw_StatusReg =
+ inl
+ (devpriv->
+ s_BoardInfos.
+ ui_Address
+ +
+ (64 * b_ModulNbr));
+ if (ui_State) // ON
+ {
+ dw_StatusReg
+ =
+ (dw_StatusReg
+ >>
+ ((b_OutputChannel / 8) * 8)) & 0xFF;
+ dw_StatusReg
+ =
+ dw_StatusReg
+ |
+ (1
+ <<
+ (b_OutputChannel
+ %
+ 8));
+ } else // Off
+ {
+ dw_StatusReg
+ =
+ (dw_StatusReg
+ >>
+ ((b_OutputChannel / 8) * 8)) & 0xFF;
+ dw_StatusReg
+ =
+ dw_StatusReg
+ &
+ (0xFF
+ -
+ (1 << (b_OutputChannel % 8)));
+
+ }
+
+ /****************************/
+ /* Set the new output value */
+ /****************************/
+
+ outl(dw_StatusReg, devpriv->s_BoardInfos.ui_Address + 8 + ((b_OutputChannel / 8) * 4) + (64 * b_ModulNbr));
+ }
+ }
+ } else {
+ /************************************/
+ /* The selected TTL output is wrong */
+ /************************************/
+
+ DPRINTK(" The selected TTL output is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /************************************/
+ /* The selected TTL output is wrong */
+ /************************************/
+
+ DPRINTK("The selected TTL output is wrong\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /***************************/
+ /* TTL I/O not initialised */
+ /***************************/
+
+ DPRINTK("TTL I/O not initialised\n");
+ i_ReturnValue = -5;
+ }
+ } else {
+ /**************************************/
+ /* The module is not a TTL I/O module */
+ /**************************************/
+
+ DPRINTK("The module is not a TTL I/O module\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /***********************/
+ /* Module number error */
+ /***********************/
+
+ DPRINTK("Module number error\n");
+ i_ReturnValue = -2;
+ }
+
+ return (i_ReturnValue);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
new file mode 100644
index 000000000000..00915ddf9218
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#define APCI1710_TTL_INIT 0
+#define APCI1710_TTL_INITDIRECTION 1
+
+#define APCI1710_TTL_READCHANNEL 0
+#define APCI1710_TTL_READPORT 1
+
+/*
+ * TTL INISIALISATION FUNCTION
+ */
+INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*
+ * TTL INPUT FUNCTION
+ */
+INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*
+ * TTL OUTPUT FUNCTIONS
+ */
+INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
new file mode 100644
index 000000000000..b0907ec14667
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
@@ -0,0 +1,203 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : ADDI HEADER READ WRITER | Compiler : Visual C++ |
+ | Module name : S5920.cpp | Version : 6.0 |
+ +-------------------------------+---------------------------------------+
+ | Author : E. LIBS Date : 02/05/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : DLL with the S5920 PCI Controller functions |
+ +-----------------------------------------------------------------------+
+ | UPDATE'S |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | 28/08/02 | LIBS Eric | Add return codes each time a function of the |
+ | | | Addi Library is called |
+ +-----------------------------------------------------------------------+
+ | 31/07/03 | KRAUTH J. | Changes for the MSX-Box |
+ +-----------------------------------------------------------------------+
+*/
+
+#include "addi_amcc_S5920.h"
+
+/*+----------------------------------------------------------------------------+*/
+/*| Function Name : INT i_AddiHeaderRW_ReadEeprom |*/
+/*| (INT i_NbOfWordsToRead, |*/
+/*| DWORD dw_PCIBoardEepromAddress, |*/
+/*| WORD w_EepromStartAddress, |*/
+/*| PWORD pw_DataRead) |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Task : Read word from the 5920 eeprom. |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Input Parameters : INT i_NbOfWordsToRead : Nbr. of word to read |*/
+/*| DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/
+/*| WORD w_EepromStartAddress : Eeprom strat address |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Output Parameters : PWORD pw_DataRead : Read data |*/
+/*+----------------------------------------------------------------------------+*/
+/*| Return Value : - |*/
+/*+----------------------------------------------------------------------------+*/
+
+INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ DWORD dw_PCIBoardEepromAddress,
+ WORD w_EepromStartAddress, PWORD pw_DataRead)
+{
+ DWORD dw_eeprom_busy = 0;
+ INT i_Counter = 0;
+ INT i_WordCounter;
+ INT i;
+ BYTE pb_ReadByte[1];
+ BYTE b_ReadLowByte = 0;
+ BYTE b_ReadHighByte = 0;
+ BYTE b_SelectedAddressLow = 0;
+ BYTE b_SelectedAddressHigh = 0;
+ WORD w_ReadWord = 0;
+
+ for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead;
+ i_WordCounter++) {
+ do {
+ dw_eeprom_busy =
+ inl(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR);
+ dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+ }
+ while (dw_eeprom_busy == EEPROM_BUSY);
+
+ for (i_Counter = 0; i_Counter < 2; i_Counter++) {
+ b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256; //Read the low 8 bit part
+ b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256; //Read the high 8 bit part
+
+ //Select the load low address mode
+ outb(NVCMD_LOAD_LOW,
+ dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 3);
+
+ //Wait on busy
+ do {
+ dw_eeprom_busy =
+ inl(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR);
+ dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+ }
+ while (dw_eeprom_busy == EEPROM_BUSY);
+
+ //Load the low address
+ outb(b_SelectedAddressLow,
+ dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 2);
+
+ //Wait on busy
+ do {
+ dw_eeprom_busy =
+ inl(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR);
+ dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+ }
+ while (dw_eeprom_busy == EEPROM_BUSY);
+
+ //Select the load high address mode
+ outb(NVCMD_LOAD_HIGH,
+ dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 3);
+
+ //Wait on busy
+ do {
+ dw_eeprom_busy =
+ inl(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR);
+ dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+ }
+ while (dw_eeprom_busy == EEPROM_BUSY);
+
+ //Load the high address
+ outb(b_SelectedAddressHigh,
+ dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 2);
+
+ //Wait on busy
+ do {
+ dw_eeprom_busy =
+ inl(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR);
+ dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+ }
+ while (dw_eeprom_busy == EEPROM_BUSY);
+
+ //Select the READ mode
+ outb(NVCMD_BEGIN_READ,
+ dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR +
+ 3);
+
+ //Wait on busy
+ do {
+ dw_eeprom_busy =
+ inl(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR);
+ dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+ }
+ while (dw_eeprom_busy == EEPROM_BUSY);
+
+ //Read data into the EEPROM
+ *pb_ReadByte =
+ inb(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR + 2);
+
+ //Wait on busy
+ do {
+ dw_eeprom_busy =
+ inl(dw_PCIBoardEepromAddress +
+ AMCC_OP_REG_MCSR);
+ dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY;
+ }
+ while (dw_eeprom_busy == EEPROM_BUSY);
+
+ //Select the upper address part
+ if (i_Counter == 0) {
+ b_ReadLowByte = pb_ReadByte[0];
+ } else {
+ b_ReadHighByte = pb_ReadByte[0];
+ }
+
+ //Sleep
+ for (i = 0; i < 10000; i++) ;
+
+ }
+ w_ReadWord =
+ (b_ReadLowByte | (((unsigned short)b_ReadHighByte) *
+ 256));
+
+ pw_DataRead[i_WordCounter] = w_ReadWord;
+
+ w_EepromStartAddress += 2; // to read the next word
+
+ } // for (...) i_NbOfWordsToRead
+ return (0);
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
new file mode 100644
index 000000000000..9ae56bc3adad
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#define AMCC_OP_REG_MCSR 0x3c
+#define EEPROM_BUSY 0x80000000
+#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */
+#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */
+#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */
+#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */
+
+INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead,
+ DWORD dw_PCIBoardEepromAddress,
+ WORD w_EepromStartAddress, PWORD pw_DataRead);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
new file mode 100644
index 000000000000..b50774cdcf77
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
@@ -0,0 +1,476 @@
+/*
+ * 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.
+ */
+
+/* Header file for AMCC s 5933 */
+
+#ifndef _AMCC_S5933_H_
+#define _AMCC_S5933_H_
+
+#include "../../comedidev.h"
+
+#include "../comedi_pci.h"
+
+#ifdef PCI_SUPPORT_VER1
+#error No support for 2.1.55 and older
+#endif
+
+/* written on base0 */
+#define FIFO_ADVANCE_ON_BYTE_2 0x20000000
+
+/* added for step 6 dma written on base2 */
+#define AMWEN_ENABLE 0x02
+
+#define A2P_FIFO_WRITE_ENABLE 0x01
+
+/* for transfer count enable bit */
+#define AGCSTS_TC_ENABLE 0x10000000
+
+/*
+ * ADDON RELATED ADDITIONS
+ */
+/* Constant */
+#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00
+#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200
+#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L
+#define APCI3120_AMWEN_ENABLE 0x02
+#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01
+#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L
+#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L
+#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L
+#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
+#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0
+#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0
+
+/* ADD_ON ::: this needed since apci supports 16 bit interface to add on */
+#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C
+#define APCI3120_ADD_ON_AGCSTS_HIGH (APCI3120_ADD_ON_AGCSTS_LOW + 2)
+#define APCI3120_ADD_ON_MWAR_LOW 0x24
+#define APCI3120_ADD_ON_MWAR_HIGH (APCI3120_ADD_ON_MWAR_LOW + 2)
+#define APCI3120_ADD_ON_MWTC_LOW 0x058
+#define APCI3120_ADD_ON_MWTC_HIGH (APCI3120_ADD_ON_MWTC_LOW + 2)
+
+/* AMCC */
+#define APCI3120_AMCC_OP_MCSR 0x3C
+#define APCI3120_AMCC_OP_REG_INTCSR 0x38
+
+/*
+ * AMCC Operation Register Offsets - PCI
+ */
+#define AMCC_OP_REG_OMB1 0x00
+#define AMCC_OP_REG_OMB2 0x04
+#define AMCC_OP_REG_OMB3 0x08
+#define AMCC_OP_REG_OMB4 0x0c
+#define AMCC_OP_REG_IMB1 0x10
+#define AMCC_OP_REG_IMB2 0x14
+#define AMCC_OP_REG_IMB3 0x18
+#define AMCC_OP_REG_IMB4 0x1c
+#define AMCC_OP_REG_FIFO 0x20
+#define AMCC_OP_REG_MWAR 0x24
+#define AMCC_OP_REG_MWTC 0x28
+#define AMCC_OP_REG_MRAR 0x2c
+#define AMCC_OP_REG_MRTC 0x30
+#define AMCC_OP_REG_MBEF 0x34
+#define AMCC_OP_REG_INTCSR 0x38
+/* INT source */
+#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2)
+/* FIFO ctrl */
+#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3)
+#define AMCC_OP_REG_MCSR 0x3c
+/* Data in byte 2 */
+#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2)
+/* Command in byte 3 */
+#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3)
+
+#define AMCC_FIFO_DEPTH_DWORD 8
+#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof(u32))
+
+/*
+ * AMCC Operation Registers Size - PCI
+ */
+#define AMCC_OP_REG_SIZE 64 /* in bytes */
+
+/*
+ * AMCC Operation Register Offsets - Add-on
+ */
+#define AMCC_OP_REG_AIMB1 0x00
+#define AMCC_OP_REG_AIMB2 0x04
+#define AMCC_OP_REG_AIMB3 0x08
+#define AMCC_OP_REG_AIMB4 0x0c
+#define AMCC_OP_REG_AOMB1 0x10
+#define AMCC_OP_REG_AOMB2 0x14
+#define AMCC_OP_REG_AOMB3 0x18
+#define AMCC_OP_REG_AOMB4 0x1c
+#define AMCC_OP_REG_AFIFO 0x20
+#define AMCC_OP_REG_AMWAR 0x24
+#define AMCC_OP_REG_APTA 0x28
+#define AMCC_OP_REG_APTD 0x2c
+#define AMCC_OP_REG_AMRAR 0x30
+#define AMCC_OP_REG_AMBEF 0x34
+#define AMCC_OP_REG_AINT 0x38
+#define AMCC_OP_REG_AGCSTS 0x3c
+#define AMCC_OP_REG_AMWTC 0x58
+#define AMCC_OP_REG_AMRTC 0x5c
+
+/*
+ * AMCC - Add-on General Control/Status Register
+ */
+#define AGCSTS_CONTROL_MASK 0xfffff000
+#define AGCSTS_NV_ACC_MASK 0xe0000000
+#define AGCSTS_RESET_MASK 0x0e000000
+#define AGCSTS_NV_DA_MASK 0x00ff0000
+#define AGCSTS_BIST_MASK 0x0000f000
+#define AGCSTS_STATUS_MASK 0x000000ff
+#define AGCSTS_TCZERO_MASK 0x000000c0
+#define AGCSTS_FIFO_ST_MASK 0x0000003f
+
+#define AGCSTS_RESET_MBFLAGS 0x08000000
+#define AGCSTS_RESET_P2A_FIFO 0x04000000
+#define AGCSTS_RESET_A2P_FIFO 0x02000000
+#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
+
+#define AGCSTS_A2P_TCOUNT 0x00000080
+#define AGCSTS_P2A_TCOUNT 0x00000040
+
+#define AGCSTS_FS_P2A_EMPTY 0x00000020
+#define AGCSTS_FS_P2A_HALF 0x00000010
+#define AGCSTS_FS_P2A_FULL 0x00000008
+
+#define AGCSTS_FS_A2P_EMPTY 0x00000004
+#define AGCSTS_FS_A2P_HALF 0x00000002
+#define AGCSTS_FS_A2P_FULL 0x00000001
+
+/*
+ * AMCC - Add-on Interrupt Control/Status Register
+ */
+#define AINT_INT_MASK 0x00ff0000
+#define AINT_SEL_MASK 0x0000ffff
+#define AINT_IS_ENSEL_MASK 0x00001f1f
+
+#define AINT_INT_ASSERTED 0x00800000
+#define AINT_BM_ERROR 0x00200000
+#define AINT_BIST_INT 0x00100000
+
+#define AINT_RT_COMPLETE 0x00080000
+#define AINT_WT_COMPLETE 0x00040000
+
+#define AINT_OUT_MB_INT 0x00020000
+#define AINT_IN_MB_INT 0x00010000
+
+#define AINT_READ_COMPL 0x00008000
+#define AINT_WRITE_COMPL 0x00004000
+
+#define AINT_OMB_ENABLE 0x00001000
+#define AINT_OMB_SELECT 0x00000c00
+#define AINT_OMB_BYTE 0x00000300
+
+#define AINT_IMB_ENABLE 0x00000010
+#define AINT_IMB_SELECT 0x0000000c
+#define AINT_IMB_BYTE 0x00000003
+
+/* Enable Bus Mastering */
+#define EN_A2P_TRANSFERS 0x00000400
+/* FIFO Flag Reset */
+#define RESET_A2P_FLAGS 0x04000000L
+/* FIFO Relative Priority */
+#define A2P_HI_PRIORITY 0x00000100L
+/* Identify Interrupt Sources */
+#define ANY_S593X_INT 0x00800000L
+#define READ_TC_INT 0x00080000L
+#define WRITE_TC_INT 0x00040000L
+#define IN_MB_INT 0x00020000L
+#define MASTER_ABORT_INT 0x00100000L
+#define TARGET_ABORT_INT 0x00200000L
+#define BUS_MASTER_INT 0x00200000L
+
+/****************************************************************************/
+
+struct pcilst_struct {
+ struct pcilst_struct *next;
+ int used;
+ struct pci_dev *pcidev;
+ unsigned short vendor;
+ unsigned short device;
+ unsigned char pci_bus;
+ unsigned char pci_slot;
+ unsigned char pci_func;
+ resource_size_t io_addr[5];
+ unsigned int irq;
+};
+
+/* ptr to root list of all amcc devices */
+struct pcilst_struct *amcc_devices;
+
+static const int i_ADDIDATADeviceID[] = { 0x15B8, 0x10E8 };
+
+/****************************************************************************/
+
+void v_pci_card_list_init(unsigned short pci_vendor, char display);
+void v_pci_card_list_cleanup(unsigned short pci_vendor);
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+ unsigned short
+ device_id);
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot,
+ struct pcilst_struct **card);
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot,
+ int i_Master);
+
+int pci_card_alloc(struct pcilst_struct *amcc, int master);
+int i_pci_card_free(struct pcilst_struct *amcc);
+void v_pci_card_list_display(void);
+int i_pci_card_data(struct pcilst_struct *amcc,
+ unsigned char *pci_bus, unsigned char *pci_slot,
+ unsigned char *pci_func, resource_size_t * io_addr,
+ unsigned int *irq);
+
+/****************************************************************************/
+
+/* build list of amcc cards in this system */
+void v_pci_card_list_init(unsigned short pci_vendor, char display)
+{
+ struct pci_dev *pcidev;
+ struct pcilst_struct *amcc, *last;
+ int i;
+ int i_Count = 0;
+ amcc_devices = NULL;
+ last = NULL;
+
+ for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ pcidev != NULL;
+ pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+ for (i_Count = 0; i_Count < 2; i_Count++) {
+ pci_vendor = i_ADDIDATADeviceID[i_Count];
+ if (pcidev->vendor == pci_vendor) {
+ amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
+ memset(amcc, 0, sizeof(*amcc));
+
+ amcc->pcidev = pcidev;
+ if (last)
+ last->next = amcc;
+ else
+ amcc_devices = amcc;
+ last = amcc;
+
+ amcc->vendor = pcidev->vendor;
+ amcc->device = pcidev->device;
+ amcc->pci_bus = pcidev->bus->number;
+ amcc->pci_slot = PCI_SLOT(pcidev->devfn);
+ amcc->pci_func = PCI_FUNC(pcidev->devfn);
+ /* Note: resources may be invalid if PCI device
+ * not enabled, but they are corrected in
+ * pci_card_alloc. */
+ for (i = 0; i < 5; i++)
+ amcc->io_addr[i] =
+ pci_resource_start(pcidev, i);
+ amcc->irq = pcidev->irq;
+
+ }
+ }
+ }
+
+ if (display)
+ v_pci_card_list_display();
+}
+
+/****************************************************************************/
+/* free up list of amcc cards in this system */
+void v_pci_card_list_cleanup(unsigned short pci_vendor)
+{
+ struct pcilst_struct *amcc, *next;
+
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ kfree(amcc);
+ }
+
+ amcc_devices = NULL;
+}
+
+/****************************************************************************/
+/* find first unused card with this device_id */
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+ unsigned short device_id)
+{
+ struct pcilst_struct *amcc, *next;
+
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ if ((!amcc->used) && (amcc->device == device_id)
+ && (amcc->vendor == vendor_id))
+ return amcc;
+
+ }
+
+ return NULL;
+}
+
+/****************************************************************************/
+/* find card on requested position */
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot,
+ struct pcilst_struct **card)
+{
+ struct pcilst_struct *amcc, *next;
+
+ *card = NULL;
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
+ && (amcc->pci_bus == pci_bus)
+ && (amcc->pci_slot == pci_slot)) {
+ if (!(amcc->used)) {
+ *card = amcc;
+ return 0; /* ok, card is found */
+ } else {
+ rt_printk(" - \nCard on requested position is used b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return 2; /* card exist but is used */
+ }
+ }
+ }
+
+ /* no card found */
+ return 1;
+}
+
+/****************************************************************************/
+/* mark card as used */
+int pci_card_alloc(struct pcilst_struct *amcc, int master)
+{
+ int i;
+
+ if (!amcc)
+ return -1;
+
+ if (amcc->used)
+ return 1;
+ if (comedi_pci_enable(amcc->pcidev, "addi_amcc_s5933"))
+ return -1;
+ /* Resources will be accurate now. */
+ for (i = 0; i < 5; i++)
+ amcc->io_addr[i] = pci_resource_start(amcc->pcidev, i);
+ if (master)
+ pci_set_master(amcc->pcidev);
+ amcc->used = 1;
+
+ return 0;
+}
+
+/****************************************************************************/
+/* mark card as free */
+int i_pci_card_free(struct pcilst_struct *amcc)
+{
+ if (!amcc)
+ return -1;
+
+ if (!amcc->used)
+ return 1;
+ amcc->used = 0;
+ comedi_pci_disable(amcc->pcidev);
+ return 0;
+}
+
+/****************************************************************************/
+/* display list of found cards */
+void v_pci_card_list_display(void)
+{
+ struct pcilst_struct *amcc, *next;
+
+ printk(KERN_DEBUG "List of pci cards\n");
+ printk(KERN_DEBUG "bus:slot:func vendor device io_amcc io_daq irq used\n");
+
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ printk
+ ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n",
+ amcc->pci_bus, amcc->pci_slot, amcc->pci_func,
+ amcc->vendor, amcc->device,
+ (unsigned long long)amcc->io_addr[0],
+ (unsigned long long)amcc->io_addr[2], amcc->irq,
+ amcc->used);
+
+ }
+}
+
+/****************************************************************************/
+/* return all card information for driver */
+int i_pci_card_data(struct pcilst_struct *amcc,
+ unsigned char *pci_bus, unsigned char *pci_slot,
+ unsigned char *pci_func, resource_size_t * io_addr,
+ unsigned int *irq)
+{
+ int i;
+
+ if (!amcc)
+ return -1;
+ *pci_bus = amcc->pci_bus;
+ *pci_slot = amcc->pci_slot;
+ *pci_func = amcc->pci_func;
+ for (i = 0; i < 5; i++)
+ io_addr[i] = amcc->io_addr[i];
+ *irq = amcc->irq;
+ return 0;
+}
+
+/****************************************************************************/
+/* select and alloc card */
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot,
+ int i_Master)
+{
+ struct pcilst_struct *card;
+
+ if ((pci_bus < 1) & (pci_slot < 1)) {
+ /* use autodetection */
+ card = ptr_find_free_pci_card_by_device(vendor_id, device_id);
+ if (card == NULL) {
+ rt_printk(" - Unused card not found in system!\n");
+ return NULL;
+ }
+ } else {
+ switch (i_find_free_pci_card_by_position(vendor_id, device_id,
+ pci_bus, pci_slot,
+ &card)) {
+ case 1:
+ rt_printk(" - Card not found on requested position b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return NULL;
+ case 2:
+ rt_printk(" - Card on requested position is used b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return NULL;
+ }
+ }
+
+ if (pci_card_alloc(card, i_Master) != 0) {
+ rt_printk(" - Can't allocate card!\n");
+ return NULL;
+
+ }
+
+ return card;
+}
+#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
new file mode 100644
index 000000000000..618c69b6838d
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -0,0 +1,3062 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : ADDI DATA | Compiler : GCC |
+ | Modulname : addi_common.c | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Author : | Date : |
+ +-----------------------------------------------------------------------+
+ | Description : ADDI COMMON Main Module |
+ +-----------------------------------------------------------------------+
+ | CONFIG OPTIONS |
+ | option[0] - PCI bus number - if bus number and slot number are 0, |
+ | then driver search for first unused card |
+ | option[1] - PCI slot number |
+ | |
+ | option[2] = 0 - DMA ENABLE |
+ | = 1 - DMA DISABLE |
+ +----------+-----------+------------------------------------------------+
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include "../../comedidev.h"
+#include <asm/io.h>
+#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
+#include <asm/i387.h>
+#endif
+#include "../comedi_fc.h"
+
+#include "addi_common.h"
+#include "addi_amcc_s5933.h"
+
+//Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>");
+//Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module");
+//Update-0.7.57->0.7.68MODULE_LICENSE("GPL");
+
+#define devpriv ((addi_private *)dev->private)
+#define this_board ((boardtype *)dev->board_ptr)
+
+#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
+//BYTE b_SaveFPUReg [94];
+
+void fpu_begin(void)
+{
+ //asm ("fstenv b_SaveFPUReg");
+ kernel_fpu_begin();
+}
+
+void fpu_end(void)
+{
+ // asm ("frstor b_SaveFPUReg");
+ kernel_fpu_end();
+}
+#endif
+
+#include "addi_eeprom.c"
+#if (defined (CONFIG_APCI_3120) || defined (CONFIG_APCI_3001))
+#include "hwdrv_apci3120.c"
+#endif
+#ifdef CONFIG_APCI_1032
+#include "hwdrv_apci1032.c"
+#endif
+#ifdef CONFIG_APCI_1516
+#include "hwdrv_apci1516.c"
+#endif
+#ifdef CONFIG_APCI_2016
+#include "hwdrv_apci2016.c"
+#endif
+#ifdef CONFIG_APCI_2032
+#include "hwdrv_apci2032.c"
+#endif
+#ifdef CONFIG_APCI_2200
+#include "hwdrv_apci2200.c"
+#endif
+#ifdef CONFIG_APCI_1564
+#include "hwdrv_apci1564.c"
+#endif
+#ifdef CONFIG_APCI_1500
+#include "hwdrv_apci1500.c"
+#endif
+#ifdef CONFIG_APCI_3501
+#include "hwdrv_apci3501.c"
+#endif
+#ifdef CONFIG_APCI_035
+#include "hwdrv_apci035.c"
+#endif
+#if (defined (CONFIG_APCI_3200) || defined (CONFIG_APCI_3300))
+#include "hwdrv_apci3200.c"
+#endif
+#ifdef CONFIG_APCI_1710
+#include "hwdrv_APCI1710.c"
+#endif
+#ifdef CONFIG_APCI_16XX
+#include "hwdrv_apci16xx.c"
+#endif
+#ifdef CONFIG_APCI_3XXX
+#include "hwdrv_apci3xxx.c"
+#endif
+
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(addi_apci_tbl) = {
+#ifdef CONFIG_APCI_3120
+ {APCI3120_BOARD_VENDOR_ID, 0x818D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1032
+ {APCI1032_BOARD_VENDOR_ID, 0x1003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1516
+ {APCI1516_BOARD_VENDOR_ID, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_2016
+ {APCI2016_BOARD_VENDOR_ID, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_2032
+ {APCI2032_BOARD_VENDOR_ID, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_2200
+ {APCI2200_BOARD_VENDOR_ID, 0x1005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1564
+ {APCI1564_BOARD_VENDOR_ID, 0x1006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1500
+ {APCI1500_BOARD_VENDOR_ID, 0x80fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3001
+ {APCI3120_BOARD_VENDOR_ID, 0x828D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3501
+ {APCI3501_BOARD_VENDOR_ID, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_035
+ {APCI035_BOARD_VENDOR_ID, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3200
+ {APCI3200_BOARD_VENDOR_ID, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3300
+ {APCI3200_BOARD_VENDOR_ID, 0x3007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_1710
+ {APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_16XX
+ {0x15B8, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x100A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#ifdef CONFIG_APCI_3XXX
+ {0x15B8, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x300F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x300E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x301A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x301B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x301C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x301D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x301E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x301F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x300B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0x15B8, 0x3024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, addi_apci_tbl);
+
+static const boardtype boardtypes[] = {
+#ifdef CONFIG_APCI_3120
+ {"apci3120",
+ APCI3120_BOARD_VENDOR_ID,
+ 0x818D,
+ AMCC_OP_REG_SIZE,
+ APCI3120_ADDRESS_RANGE,
+ 8,
+ 0,
+ ADDIDATA_NO_EEPROM,
+ NULL,
+ 16,
+ 8,
+ 16,
+ 8,
+ 0xffff,
+ 0x3fff,
+ &range_apci3120_ai,
+ &range_apci3120_ao,
+ 4,
+ 4,
+ 0x0f,
+ 0,
+ NULL,
+ 1,
+ 1,
+ 1,
+ 10000,
+ 100000,
+ v_APCI3120_Interrupt,
+ i_APCI3120_Reset,
+ i_APCI3120_InsnConfigAnalogInput,
+ i_APCI3120_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ i_APCI3120_CommandTestAnalogInput,
+ i_APCI3120_CommandAnalogInput,
+ i_APCI3120_StopCyclicAcquisition,
+ NULL,
+ i_APCI3120_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ i_APCI3120_InsnReadDigitalInput,
+ NULL,
+ i_APCI3120_InsnBitsDigitalInput,
+ i_APCI3120_InsnConfigDigitalOutput,
+ i_APCI3120_InsnWriteDigitalOutput,
+ i_APCI3120_InsnBitsDigitalOutput,
+ NULL,
+ i_APCI3120_InsnConfigTimer,
+ i_APCI3120_InsnWriteTimer,
+ i_APCI3120_InsnReadTimer,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_1032
+ {"apci1032",
+ APCI1032_BOARD_VENDOR_ID,
+ 0x1003,
+ 4,
+ APCI1032_ADDRESS_RANGE,
+ 0,
+ 0,
+ ADDIDATA_EEPROM,
+ ADDIDATA_93C76,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 32,
+ 0,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ v_APCI1032_Interrupt,
+ i_APCI1032_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI1032_ConfigDigitalInput,
+ i_APCI1032_Read1DigitalInput,
+ NULL,
+ i_APCI1032_ReadMoreDigitalInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_1516
+ {"apci1516",
+ APCI1516_BOARD_VENDOR_ID,
+ 0x1001,
+ 128,
+ APCI1516_ADDRESS_RANGE,
+ 32,
+ 0,
+ ADDIDATA_EEPROM,
+ ADDIDATA_S5920,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 8,
+ 8,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ NULL,
+ i_APCI1516_Reset,
+ NULL, NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI1516_Read1DigitalInput,
+ NULL,
+ i_APCI1516_ReadMoreDigitalInput,
+ i_APCI1516_ConfigDigitalOutput,
+ i_APCI1516_WriteDigitalOutput,
+ i_APCI1516_ReadDigitalOutput,
+ NULL,
+ i_APCI1516_ConfigWatchdog,
+ i_APCI1516_StartStopWriteWatchdog,
+ i_APCI1516_ReadWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_2016
+ {"apci2016",
+ APCI2016_BOARD_VENDOR_ID,
+ 0x1002,
+ 128,
+ APCI2016_ADDRESS_RANGE,
+ 32,
+ 0,
+ ADDIDATA_EEPROM,
+ ADDIDATA_S5920,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 0,
+ 16,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ NULL,
+ i_APCI2016_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI2016_ConfigDigitalOutput,
+ i_APCI2016_WriteDigitalOutput,
+ i_APCI2016_BitsDigitalOutput,
+ NULL,
+ i_APCI2016_ConfigWatchdog,
+ i_APCI2016_StartStopWriteWatchdog,
+ i_APCI2016_ReadWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_2032
+ {"apci2032",
+ APCI2032_BOARD_VENDOR_ID,
+ 0x1004,
+ 4,
+ APCI2032_ADDRESS_RANGE,
+ 0,
+ 0,
+ ADDIDATA_EEPROM,
+ ADDIDATA_93C76,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 0,
+ 32,
+ 0xffffffff,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ v_APCI2032_Interrupt,
+ i_APCI2032_Reset,
+ NULL, NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI2032_ConfigDigitalOutput,
+ i_APCI2032_WriteDigitalOutput,
+ i_APCI2032_ReadDigitalOutput,
+ i_APCI2032_ReadInterruptStatus,
+ i_APCI2032_ConfigWatchdog,
+ i_APCI2032_StartStopWriteWatchdog,
+ i_APCI2032_ReadWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_2200
+ {"apci2200",
+ APCI2200_BOARD_VENDOR_ID,
+ 0x1005,
+ 4,
+ APCI2200_ADDRESS_RANGE,
+ 0,
+ 0,
+ ADDIDATA_EEPROM,
+ ADDIDATA_93C76,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 8,
+ 16,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ NULL,
+ i_APCI2200_Reset,
+ NULL, NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI2200_Read1DigitalInput,
+ NULL,
+ i_APCI2200_ReadMoreDigitalInput,
+ i_APCI2200_ConfigDigitalOutput,
+ i_APCI2200_WriteDigitalOutput,
+ i_APCI2200_ReadDigitalOutput,
+ NULL,
+ i_APCI2200_ConfigWatchdog,
+ i_APCI2200_StartStopWriteWatchdog,
+ i_APCI2200_ReadWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_1564
+ {"apci1564",
+ APCI1564_BOARD_VENDOR_ID,
+ 0x1006,
+ 128,
+ APCI1564_ADDRESS_RANGE,
+ 0,
+ 0,
+ ADDIDATA_EEPROM,
+ ADDIDATA_93C76,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 32,
+ 32,
+ 0xffffffff,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ v_APCI1564_Interrupt,
+ i_APCI1564_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI1564_ConfigDigitalInput,
+ i_APCI1564_Read1DigitalInput,
+ NULL,
+ i_APCI1564_ReadMoreDigitalInput,
+ i_APCI1564_ConfigDigitalOutput,
+ i_APCI1564_WriteDigitalOutput,
+ i_APCI1564_ReadDigitalOutput,
+ i_APCI1564_ReadInterruptStatus,
+ i_APCI1564_ConfigTimerCounterWatchdog,
+ i_APCI1564_StartStopWriteTimerCounterWatchdog,
+ i_APCI1564_ReadTimerCounterWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_1500
+ {"apci1500",
+ APCI1500_BOARD_VENDOR_ID,
+ 0x80fc,
+ 128,
+ APCI1500_ADDRESS_RANGE,
+ 4,
+ 0,
+ ADDIDATA_NO_EEPROM,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 16,
+ 16,
+ 0xffff,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ v_APCI1500_Interrupt,
+ i_APCI1500_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI1500_ConfigDigitalInputEvent,
+ i_APCI1500_Initialisation,
+ i_APCI1500_StartStopInputEvent,
+ i_APCI1500_ReadMoreDigitalInput,
+ i_APCI1500_ConfigDigitalOutputErrorInterrupt,
+ i_APCI1500_WriteDigitalOutput,
+ i_APCI1500_ConfigureInterrupt,
+ NULL,
+ i_APCI1500_ConfigCounterTimerWatchdog,
+ i_APCI1500_StartStopTriggerTimerCounterWatchdog,
+ i_APCI1500_ReadInterruptMask,
+ i_APCI1500_ReadCounterTimerWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_3001
+ {"apci3001",
+ APCI3120_BOARD_VENDOR_ID,
+ 0x828D,
+ AMCC_OP_REG_SIZE,
+ APCI3120_ADDRESS_RANGE,
+ 8,
+ 0,
+ ADDIDATA_NO_EEPROM,
+ NULL,
+ 16,
+ 8,
+ 16,
+ 0,
+ 0xfff,
+ 0,
+ &range_apci3120_ai,
+ NULL,
+ 4,
+ 4,
+ 0x0f,
+ 0,
+ NULL,
+ 1,
+ 1,
+ 1,
+ 10000,
+ 100000,
+ v_APCI3120_Interrupt,
+ i_APCI3120_Reset,
+ i_APCI3120_InsnConfigAnalogInput,
+ i_APCI3120_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ i_APCI3120_CommandTestAnalogInput,
+ i_APCI3120_CommandAnalogInput,
+ i_APCI3120_StopCyclicAcquisition,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3120_InsnReadDigitalInput,
+ NULL,
+ i_APCI3120_InsnBitsDigitalInput,
+ i_APCI3120_InsnConfigDigitalOutput,
+ i_APCI3120_InsnWriteDigitalOutput,
+ i_APCI3120_InsnBitsDigitalOutput,
+ NULL,
+ i_APCI3120_InsnConfigTimer,
+ i_APCI3120_InsnWriteTimer,
+ i_APCI3120_InsnReadTimer,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_3501
+ {"apci3501",
+ APCI3501_BOARD_VENDOR_ID,
+ 0x3001,
+ 64,
+ APCI3501_ADDRESS_RANGE,
+ 0,
+ 0,
+ ADDIDATA_EEPROM,
+ ADDIDATA_S5933,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 16383,
+ NULL,
+ &range_apci3501_ao,
+ 2,
+ 2,
+ 0x3,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ v_APCI3501_Interrupt,
+ i_APCI3501_Reset,
+ NULL, NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3501_ConfigAnalogOutput,
+ i_APCI3501_WriteAnalogOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3501_ReadDigitalInput,
+ i_APCI3501_ConfigDigitalOutput,
+ i_APCI3501_WriteDigitalOutput,
+ i_APCI3501_ReadDigitalOutput,
+ NULL,
+ i_APCI3501_ConfigTimerCounterWatchdog,
+ i_APCI3501_StartStopWriteTimerCounterWatchdog,
+ i_APCI3501_ReadTimerCounterWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_035
+ {"apci035",
+ APCI035_BOARD_VENDOR_ID,
+ 0x0300,
+ 127,
+ APCI035_ADDRESS_RANGE,
+ 0,
+ 0,
+ 1,
+ ADDIDATA_S5920,
+ 16,
+ 8,
+ 16,
+ 0,
+ 0xff,
+ 0,
+ &range_apci035_ai,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 1,
+ 0,
+ 10000,
+ 100000,
+ v_APCI035_Interrupt,
+ i_APCI035_Reset,
+ i_APCI035_ConfigAnalogInput,
+ i_APCI035_ReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI035_ConfigTimerWatchdog,
+ i_APCI035_StartStopWriteTimerWatchdog,
+ i_APCI035_ReadTimerWatchdog,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_3200
+ {"apci3200",
+ APCI3200_BOARD_VENDOR_ID,
+ 0x3000,
+ 128,
+ 256,
+ 4,
+ 4,
+ ADDIDATA_EEPROM,
+ ADDIDATA_S5920,
+ 16,
+ 8,
+ 16,
+ 0,
+ 0x3ffff,
+ 0,
+ &range_apci3200_ai,
+ NULL,
+ 4,
+ 4,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 10000,
+ 100000,
+ v_APCI3200_Interrupt,
+ i_APCI3200_Reset,
+ i_APCI3200_ConfigAnalogInput,
+ i_APCI3200_ReadAnalogInput,
+ i_APCI3200_InsnWriteReleaseAnalogInput,
+ i_APCI3200_InsnBits_AnalogInput_Test,
+ i_APCI3200_CommandTestAnalogInput,
+ i_APCI3200_CommandAnalogInput,
+ i_APCI3200_StopCyclicAcquisition,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3200_ReadDigitalInput,
+ i_APCI3200_ConfigDigitalOutput,
+ i_APCI3200_WriteDigitalOutput,
+ i_APCI3200_ReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_3300
+ //Begin JK 20.10.2004: APCI-3300 integration
+ {"apci3300",
+ APCI3200_BOARD_VENDOR_ID,
+ 0x3007,
+ 128,
+ 256,
+ 4,
+ 4,
+ ADDIDATA_EEPROM,
+ ADDIDATA_S5920,
+ 0,
+ 8,
+ 8,
+ 0,
+ 0x3ffff,
+ 0,
+ &range_apci3300_ai,
+ NULL,
+ 4,
+ 4,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 10000,
+ 100000,
+ v_APCI3200_Interrupt,
+ i_APCI3200_Reset,
+ i_APCI3200_ConfigAnalogInput,
+ i_APCI3200_ReadAnalogInput,
+ i_APCI3200_InsnWriteReleaseAnalogInput,
+ i_APCI3200_InsnBits_AnalogInput_Test,
+ i_APCI3200_CommandTestAnalogInput,
+ i_APCI3200_CommandAnalogInput,
+ i_APCI3200_StopCyclicAcquisition,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3200_ReadDigitalInput,
+ i_APCI3200_ConfigDigitalOutput,
+ i_APCI3200_WriteDigitalOutput,
+ i_APCI3200_ReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_1710
+ {"apci1710", APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID,
+ 128,
+ 8,
+ 256,
+ 0,
+ ADDIDATA_NO_EEPROM,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ v_APCI1710_Interrupt,
+ i_APCI1710_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+#endif
+#ifdef CONFIG_APCI_16XX
+ {"apci1648",
+ 0x15B8,
+ 0x1009,
+ 128,
+ 0,
+ 0,
+ 0,
+ ADDIDATA_NO_EEPROM,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 48,
+ &range_apci16xx_ttl,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ i_APCI16XX_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI16XX_InsnConfigInitTTLIO,
+ i_APCI16XX_InsnBitsReadTTLIO,
+ i_APCI16XX_InsnReadTTLIOAllPortValue,
+ i_APCI16XX_InsnBitsWriteTTLIO},
+
+ {"apci1696",
+ 0x15B8,
+ 0x100A,
+ 128,
+ 0,
+ 0,
+ 0,
+ ADDIDATA_NO_EEPROM,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 96,
+ &range_apci16xx_ttl,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ i_APCI16XX_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI16XX_InsnConfigInitTTLIO,
+ i_APCI16XX_InsnBitsReadTTLIO,
+ i_APCI16XX_InsnReadTTLIOAllPortValue,
+ i_APCI16XX_InsnBitsWriteTTLIO},
+#endif
+#ifdef CONFIG_APCI_3XXX
+ {"apci3000-16",
+ 0x15B8,
+ 0x3010,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 0,
+ 4095,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3000-8",
+ 0x15B8,
+ 0x300F,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 0,
+ 4095,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3000-4",
+ 0x15B8,
+ 0x300E,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 4,
+ 2,
+ 4,
+ 0,
+ 4095,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3006-16",
+ 0x15B8,
+ 0x3013,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3006-8",
+ 0x15B8,
+ 0x3014,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3006-4",
+ 0x15B8,
+ 0x3015,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 4,
+ 2,
+ 4,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3010-16",
+ 0x15B8,
+ 0x3016,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 0,
+ 4095,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3010-8",
+ 0x15B8,
+ 0x3017,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 0,
+ 4095,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3010-4",
+ 0x15B8,
+ 0x3018,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 4,
+ 2,
+ 4,
+ 0,
+ 4095,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3016-16",
+ 0x15B8,
+ 0x3019,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3016-8",
+ 0x15B8,
+ 0x301A,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3016-4",
+ 0x15B8,
+ 0x301B,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 4,
+ 2,
+ 4,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3100-16-4",
+ 0x15B8,
+ 0x301C,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 4,
+ 4095,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3100-8-4",
+ 0x15B8,
+ 0x301D,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 4,
+ 4095,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3106-16-4",
+ 0x15B8,
+ 0x301E,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 4,
+ 65535,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3106-8-4",
+ 0x15B8,
+ 0x301F,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 4,
+ 65535,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 10000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3110-16-4",
+ 0x15B8,
+ 0x3020,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 4,
+ 4095,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3110-8-4",
+ 0x15B8,
+ 0x3021,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 4,
+ 4095,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3116-16-4",
+ 0x15B8,
+ 0x3022,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 16,
+ 8,
+ 16,
+ 4,
+ 65535,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3116-8-4",
+ 0x15B8,
+ 0x3023,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 8,
+ 4,
+ 8,
+ 4,
+ 65535,
+ 4095,
+ &range_apci3XXX_ai,
+ &range_apci3XXX_ao,
+ 4,
+ 4,
+ 1,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+
+ {"apci3003",
+ 0x15B8,
+ 0x300B,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 0,
+ 4,
+ 4,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 7,
+ 2500,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+
+ {"apci3002-16",
+ 0x15B8,
+ 0x3002,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 0,
+ 16,
+ 16,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+
+ {"apci3002-8",
+ 0x15B8,
+ 0x3003,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 0,
+ 8,
+ 8,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+
+ {"apci3002-4",
+ 0x15B8,
+ 0x3004,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 0,
+ 4,
+ 4,
+ 0,
+ 65535,
+ 0,
+ &range_apci3XXX_ai,
+ NULL,
+ 4,
+ 4,
+ 1,
+ 0,
+ NULL,
+ 0,
+ 0,
+ 6,
+ 5000,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ i_APCI3XXX_InsnConfigAnalogInput,
+ i_APCI3XXX_InsnReadAnalogInput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnReadDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnBitsDigitalInput,
+ NULL,
+ i_APCI3XXX_InsnWriteDigitalOutput,
+ i_APCI3XXX_InsnBitsDigitalOutput,
+ i_APCI3XXX_InsnReadDigitalOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL},
+
+ {"apci3500",
+ 0x15B8,
+ 0x3024,
+ 256,
+ 256,
+ 256,
+ 256,
+ ADDIDATA_NO_EEPROM,
+ ADDIDATA_9054,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 4095,
+ NULL,
+ &range_apci3XXX_ao,
+ 0,
+ 0,
+ 0,
+ 24,
+ &range_apci3XXX_ttl,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ v_APCI3XXX_Interrupt,
+ i_APCI3XXX_Reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnWriteAnalogOutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ i_APCI3XXX_InsnConfigInitTTLIO,
+ i_APCI3XXX_InsnBitsTTLIO,
+ i_APCI3XXX_InsnReadTTLIO,
+ i_APCI3XXX_InsnWriteTTLIO},
+#endif
+};
+
+#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+
+struct comedi_driver driver_addi = {
+ driver_name:"addi_common",
+ module:THIS_MODULE,
+ attach:i_ADDI_Attach,
+ detach:i_ADDI_Detach,
+ num_names:n_boardtypes,
+ board_name:&boardtypes[0].pc_DriverName,
+ offset:sizeof(boardtype),
+};
+
+COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
+
+/*
++----------------------------------------------------------------------------+
+| Function name :static int i_ADDI_Attach(struct comedi_device *dev, |
+| struct comedi_devconfig *it) |
+| |
++----------------------------------------------------------------------------+
+| Task :Detects the card. |
+| Configure the driver for a particular board. |
+| This function does all the initializations and memory |
+| allocation of data structures for the driver. |
++----------------------------------------------------------------------------+
+| Input Parameters :struct comedi_device *dev |
+| struct comedi_devconfig *it |
+| |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
+| |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * it)
+{
+ struct comedi_subdevice *s;
+ int ret, pages, i, n_subdevices;
+ DWORD dw_Dummy;
+ resource_size_t io_addr[5];
+ unsigned int irq;
+ resource_size_t iobase_a, iobase_main, iobase_addon, iobase_reserved;
+ struct pcilst_struct *card = NULL;
+ unsigned char pci_bus, pci_slot, pci_func;
+ int i_Dma = 0;
+ static char c_Identifier[150];
+
+ sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
+ this_board->pc_DriverName);
+
+ if ((ret = alloc_private(dev, sizeof(addi_private))) < 0) {
+ return -ENOMEM;
+ }
+
+ if (!pci_list_builded) {
+ v_pci_card_list_init(this_board->i_VendorId, 1); //1 for displaying the list..
+ pci_list_builded = 1;
+ }
+ //rt_printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName);
+
+ if ((this_board->i_Dma) && (it->options[2] == 0)) {
+ i_Dma = 1;
+ }
+
+ if ((card = ptr_select_and_alloc_pci_card(this_board->i_VendorId,
+ this_board->i_DeviceId,
+ it->options[0],
+ it->options[1], i_Dma)) == NULL) {
+ return -EIO;
+ }
+ devpriv->allocated = 1;
+
+ if ((i_pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0],
+ &irq)) < 0) {
+ i_pci_card_free(card);
+ printk(" - Can't get AMCC data!\n");
+ return -EIO;
+ }
+
+ iobase_a = io_addr[0];
+ iobase_main = io_addr[1];
+ iobase_addon = io_addr[2];
+ iobase_reserved = io_addr[3];
+ printk("\nBus %d: Slot %d: Funct%d\nBase0: 0x%8llx\nBase1: 0x%8llx\nBase2: 0x%8llx\nBase3: 0x%8llx\n", pci_bus, pci_slot, pci_func, (unsigned long long)io_addr[0], (unsigned long long)io_addr[1], (unsigned long long)io_addr[2], (unsigned long long)io_addr[3]);
+
+ if ((this_board->pc_EepromChip == NULL)
+ || (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) {
+ /************************************/
+ /* Test if more that 1 address used */
+ /************************************/
+
+ if (this_board->i_IorangeBase1 != 0) {
+ dev->iobase = (unsigned long)iobase_main; // DAQ base address...
+ } else {
+ dev->iobase = (unsigned long)iobase_a; // DAQ base address...
+ }
+
+ dev->board_name = this_board->pc_DriverName;
+ devpriv->amcc = card;
+ devpriv->iobase = (INT) dev->iobase;
+ devpriv->i_IobaseAmcc = (INT) iobase_a; //AMCC base address...
+ devpriv->i_IobaseAddon = (INT) iobase_addon; //ADD ON base address....
+ devpriv->i_IobaseReserved = (INT) iobase_reserved;
+ devpriv->ps_BoardInfo = this_board;
+ } else {
+ dev->board_name = this_board->pc_DriverName;
+ dev->iobase = (unsigned long)io_addr[2];
+ devpriv->amcc = card;
+ devpriv->iobase = (INT) io_addr[2];
+ devpriv->ps_BoardInfo = this_board;
+ devpriv->i_IobaseReserved = (INT) io_addr[3];
+ printk("\nioremap begin");
+ devpriv->dw_AiBase =
+ (ULONG_PTR) ioremap(io_addr[3],
+ this_board->i_IorangeBase3);
+ printk("\nioremap end");
+ }
+
+ //##
+
+ if (irq > 0) {
+ if (comedi_request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
+ c_Identifier, dev) < 0) {
+ printk(", unable to allocate IRQ %u, DISABLING IT",
+ irq);
+ irq = 0; /* Can't use IRQ */
+ } else {
+ rt_printk("\nirq=%u", irq);
+ }
+ } else {
+ rt_printk(", IRQ disabled");
+ }
+
+ printk("\nOption %d %d %d\n", it->options[0], it->options[1],
+ it->options[2]);
+ dev->irq = irq;
+
+ // Read eepeom and fill boardtype Structure
+
+ if (this_board->i_PCIEeprom) {
+ printk("\nPCI Eeprom used");
+ if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
+ // Set 3 wait stait
+ if (!(strcmp(this_board->pc_DriverName, "apci035"))) {
+ outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
+ } else {
+ outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
+ }
+ // Enable the interrupt for the controler
+ dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
+ outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
+ printk("\nEnable the interrupt for the controler");
+ }
+ printk("\nRead Eeprom");
+ i_EepromReadMainHeader(io_addr[0], this_board->pc_EepromChip,
+ dev);
+ } else {
+ printk("\nPCI Eeprom unused");
+ }
+
+ if (it->options[2] > 0) {
+ devpriv->us_UseDma = ADDI_DISABLE;
+ } else {
+ devpriv->us_UseDma = ADDI_ENABLE;
+ }
+
+ if (this_board->i_Dma) {
+ printk("\nDMA used");
+ if (devpriv->us_UseDma == ADDI_ENABLE) {
+ // alloc DMA buffers
+ devpriv->b_DmaDoubleBuffer = 0;
+ for (i = 0; i < 2; i++) {
+ for (pages = 4; pages >= 0; pages--) {
+ if ((devpriv->ul_DmaBufferVirtual[i] =
+ (void *)
+ __get_free_pages
+ (GFP_KERNEL, pages))) {
+ break;
+ }
+ }
+ if (devpriv->ul_DmaBufferVirtual[i]) {
+ devpriv->ui_DmaBufferPages[i] = pages;
+ devpriv->ui_DmaBufferSize[i] =
+ PAGE_SIZE * pages;
+ devpriv->ui_DmaBufferSamples[i] =
+ devpriv->
+ ui_DmaBufferSize[i] >> 1;
+ devpriv->ul_DmaBufferHw[i] =
+ virt_to_bus((void *)devpriv->
+ ul_DmaBufferVirtual[i]);
+ }
+ }
+ if (!devpriv->ul_DmaBufferVirtual[0]) {
+ rt_printk
+ (", Can't allocate DMA buffer, DMA disabled!");
+ devpriv->us_UseDma = ADDI_DISABLE;
+ }
+
+ if (devpriv->ul_DmaBufferVirtual[1]) {
+ devpriv->b_DmaDoubleBuffer = 1;
+ }
+ }
+
+ if ((devpriv->us_UseDma == ADDI_ENABLE)) {
+ rt_printk("\nDMA ENABLED\n");
+ } else {
+ printk("\nDMA DISABLED\n");
+ }
+ }
+
+ if (!strcmp(this_board->pc_DriverName, "apci1710")) {
+#ifdef CONFIG_APCI_1710
+ i_ADDI_AttachPCI1710(dev);
+
+ // save base address
+ devpriv->s_BoardInfos.ui_Address = io_addr[2];
+#endif
+ } else {
+ //Update-0.7.57->0.7.68dev->n_subdevices = 7;
+ n_subdevices = 7;
+ if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+ return ret;
+
+ // Allocate and Initialise AI Subdevice Structures
+ s = dev->subdevices + 0;
+ if ((this_board->i_NbrAiChannel)
+ || (this_board->i_NbrAiChannelDiff)) {
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags =
+ SDF_READABLE | SDF_RT | SDF_COMMON | SDF_GROUND
+ | SDF_DIFF;
+ if (this_board->i_NbrAiChannel) {
+ s->n_chan = this_board->i_NbrAiChannel;
+ devpriv->b_SingelDiff = 0;
+ } else {
+ s->n_chan = this_board->i_NbrAiChannelDiff;
+ devpriv->b_SingelDiff = 1;
+ }
+ s->maxdata = this_board->i_AiMaxdata;
+ s->len_chanlist = this_board->i_AiChannelList;
+ s->range_table = this_board->pr_AiRangelist;
+
+ /* Set the initialisation flag */
+ devpriv->b_AiInitialisation = 1;
+
+ s->insn_config =
+ this_board->i_hwdrv_InsnConfigAnalogInput;
+ s->insn_read = this_board->i_hwdrv_InsnReadAnalogInput;
+ s->insn_write =
+ this_board->i_hwdrv_InsnWriteAnalogInput;
+ s->insn_bits = this_board->i_hwdrv_InsnBitsAnalogInput;
+ s->do_cmdtest =
+ this_board->i_hwdrv_CommandTestAnalogInput;
+ s->do_cmd = this_board->i_hwdrv_CommandAnalogInput;
+ s->cancel = this_board->i_hwdrv_CancelAnalogInput;
+
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ // Allocate and Initialise AO Subdevice Structures
+ s = dev->subdevices + 1;
+ if (this_board->i_NbrAoChannel) {
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_GROUND | SDF_COMMON |
+ SDF_RT;
+ s->n_chan = this_board->i_NbrAoChannel;
+ s->maxdata = this_board->i_AoMaxdata;
+ s->len_chanlist = this_board->i_NbrAoChannel;
+ s->range_table = this_board->pr_AoRangelist;
+ s->insn_config =
+ this_board->i_hwdrv_InsnConfigAnalogOutput;
+ s->insn_write =
+ this_board->i_hwdrv_InsnWriteAnalogOutput;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+ // Allocate and Initialise DI Subdevice Structures
+ s = dev->subdevices + 2;
+ if (this_board->i_NbrDiChannel) {
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags =
+ SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = this_board->i_NbrDiChannel;
+ s->maxdata = 1;
+ s->len_chanlist = this_board->i_NbrDiChannel;
+ s->range_table = &range_digital;
+ s->io_bits = 0; /* all bits input */
+ s->insn_config =
+ this_board->i_hwdrv_InsnConfigDigitalInput;
+ s->insn_read = this_board->i_hwdrv_InsnReadDigitalInput;
+ s->insn_write =
+ this_board->i_hwdrv_InsnWriteDigitalInput;
+ s->insn_bits = this_board->i_hwdrv_InsnBitsDigitalInput;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+ // Allocate and Initialise DO Subdevice Structures
+ s = dev->subdevices + 3;
+ if (this_board->i_NbrDoChannel) {
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags =
+ SDF_READABLE | SDF_WRITEABLE | SDF_RT |
+ SDF_GROUND | SDF_COMMON;
+ s->n_chan = this_board->i_NbrDoChannel;
+ s->maxdata = this_board->i_DoMaxdata;
+ s->len_chanlist = this_board->i_NbrDoChannel;
+ s->range_table = &range_digital;
+ s->io_bits = 0xf; /* all bits output */
+
+ s->insn_config = this_board->i_hwdrv_InsnConfigDigitalOutput; //for digital output memory..
+ s->insn_write =
+ this_board->i_hwdrv_InsnWriteDigitalOutput;
+ s->insn_bits =
+ this_board->i_hwdrv_InsnBitsDigitalOutput;
+ s->insn_read =
+ this_board->i_hwdrv_InsnReadDigitalOutput;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ // Allocate and Initialise Timer Subdevice Structures
+ s = dev->subdevices + 4;
+ if (this_board->i_Timer) {
+ s->type = COMEDI_SUBD_TIMER;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_RT | SDF_GROUND |
+ SDF_COMMON;
+ s->n_chan = 1;
+ s->maxdata = 0;
+ s->len_chanlist = 1;
+ s->range_table = &range_digital;
+
+ s->insn_write = this_board->i_hwdrv_InsnWriteTimer;
+ s->insn_read = this_board->i_hwdrv_InsnReadTimer;
+ s->insn_config = this_board->i_hwdrv_InsnConfigTimer;
+ s->insn_bits = this_board->i_hwdrv_InsnBitsTimer;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ // Allocate and Initialise TTL
+ s = dev->subdevices + 5;
+ if (this_board->i_NbrTTLChannel) {
+ s->type = COMEDI_SUBD_TTLIO;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT |
+ SDF_GROUND | SDF_COMMON;
+ s->n_chan = this_board->i_NbrTTLChannel;
+ s->maxdata = 1;
+ s->io_bits = 0; /* all bits input */
+ s->len_chanlist = this_board->i_NbrTTLChannel;
+ s->range_table = &range_digital;
+ s->insn_config = this_board->i_hwdr_ConfigInitTTLIO;
+ s->insn_bits = this_board->i_hwdr_ReadTTLIOBits;
+ s->insn_read = this_board->i_hwdr_ReadTTLIOAllPortValue;
+ s->insn_write = this_board->i_hwdr_WriteTTLIOChlOnOff;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /* EEPROM */
+ s = dev->subdevices + 6;
+ if (this_board->i_PCIEeprom) {
+ s->type = COMEDI_SUBD_MEMORY;
+ s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
+ s->n_chan = 256;
+ s->maxdata = 0xffff;
+ s->insn_read = i_ADDIDATA_InsnReadEeprom;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+ }
+
+ printk("\ni_ADDI_Attach end\n");
+ i_ADDI_Reset(dev);
+ devpriv->b_ValidDriver = 1;
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : static int i_ADDI_Detach(struct comedi_device *dev) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Task : Deallocates resources of the addi_common driver |
+| Free the DMA buffers, unregister irq. |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
+| |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDI_Detach(struct comedi_device * dev)
+{
+
+ if (dev->private) {
+ if (devpriv->b_ValidDriver) {
+ i_ADDI_Reset(dev);
+ }
+
+ if (dev->irq) {
+ comedi_free_irq(dev->irq, dev);
+ }
+
+ if ((devpriv->ps_BoardInfo->pc_EepromChip == NULL)
+ || (strcmp(devpriv->ps_BoardInfo->pc_EepromChip,
+ ADDIDATA_9054) != 0)) {
+ if (devpriv->allocated) {
+ i_pci_card_free(devpriv->amcc);
+ }
+
+ if (devpriv->ul_DmaBufferVirtual[0]) {
+ free_pages((unsigned long)devpriv->
+ ul_DmaBufferVirtual[0],
+ devpriv->ui_DmaBufferPages[0]);
+ }
+
+ if (devpriv->ul_DmaBufferVirtual[1]) {
+ free_pages((unsigned long)devpriv->
+ ul_DmaBufferVirtual[1],
+ devpriv->ui_DmaBufferPages[1]);
+ }
+ } else {
+ iounmap((void *)devpriv->dw_AiBase);
+
+ if (devpriv->allocated) {
+ i_pci_card_free(devpriv->amcc);
+ }
+ }
+
+ if (pci_list_builded) {
+ //v_pci_card_list_cleanup(PCI_VENDOR_ID_AMCC);
+ v_pci_card_list_cleanup(this_board->i_VendorId);
+ pci_list_builded = 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : static int i_ADDI_Reset(struct comedi_device *dev) |
+| |
++----------------------------------------------------------------------------+
+| Task : Disables all interrupts, Resets digital output to low, |
+| Set all analog output to low |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
+| |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDI_Reset(struct comedi_device * dev)
+{
+
+ this_board->i_hwdrv_Reset(dev);
+ return 0;
+}
+
+// Interrupt function
+/*
++----------------------------------------------------------------------------+
+| Function name : |
+|static void v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG) |
+| |
++----------------------------------------------------------------------------+
+| Task : Registerd interrupt routine |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG)
+{
+ struct comedi_device *dev = d;
+ this_board->v_hwdrv_Interrupt(irq, d);
+ return IRQ_RETVAL(1);
+}
+
+// EEPROM Read Function
+/*
++----------------------------------------------------------------------------+
+| Function name : |
+|INT i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data)
+| |
++----------------------------------------------------------------------------+
+| Task : Read 256 words from EEPROM |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters :(struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ WORD w_Data;
+ WORD w_Address;
+ w_Address = CR_CHAN(insn->chanspec); // address to be read as 0,1,2,3...255
+
+ w_Data = w_EepromReadWord(devpriv->i_IobaseAmcc,
+ this_board->pc_EepromChip, 0x100 + (2 * w_Address));
+ data[0] = w_Data;
+ //multiplied by 2 bcozinput will be like 0,1,2...255
+ return insn->n;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
new file mode 100644
index 000000000000..19df5c1444a4
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -0,0 +1,462 @@
+/*
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/kmod.h>
+#include <linux/uaccess.h>
+#include "../../comedidev.h"
+#include "addi_amcc_s5933.h"
+
+#define ERROR -1
+#define SUCCESS 1
+
+/* variable type definition */
+typedef unsigned char BYTE, *PBYTE;
+typedef short SHORT, *PSHORT;
+typedef unsigned short USHORT, *PUSHORT;
+typedef unsigned short WORD, *PWORD;
+typedef int INT, *PINT;;
+typedef unsigned int UINT, *PUINT;
+typedef int LONG, *PLONG; /* 32-bit */
+typedef unsigned int ULONG, *PULONG; /* 32-bit */
+typedef unsigned int DWORD, *PDWORD; /* 32-bit */
+typedef unsigned long ULONG_PTR;
+
+typedef const struct comedi_lrange *PCRANGE;
+
+#define LOBYTE(W) (BYTE)((W) & 0xFF)
+#define HIBYTE(W) (BYTE)(((W) >> 8) & 0xFF)
+#define MAKEWORD(H, L) (USHORT)((L) | ((H) << 8))
+#define LOWORD(W) (USHORT)((W) & 0xFFFF)
+#define HIWORD(W) (USHORT)(((W) >> 16) & 0xFFFF)
+#define MAKEDWORD(H, L) (UINT)((L) | ((H) << 16))
+
+#define ADDI_ENABLE 1
+#define ADDI_DISABLE 0
+#define APCI1710_SAVE_INTERRUPT 1
+
+#define ADDIDATA_EEPROM 1
+#define ADDIDATA_NO_EEPROM 0
+#define ADDIDATA_93C76 "93C76"
+#define ADDIDATA_S5920 "S5920"
+#define ADDIDATA_S5933 "S5933"
+#define ADDIDATA_9054 "9054"
+
+/* ADDIDATA Enable Disable */
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+
+/* Structures */
+
+/* structure for the boardtype */
+typedef struct {
+ const char *pc_DriverName; // driver name
+ INT i_VendorId; //PCI vendor a device ID of card
+ INT i_DeviceId;
+ INT i_IorangeBase0;
+ INT i_IorangeBase1;
+ INT i_IorangeBase2; // base 2 range
+ INT i_IorangeBase3; // base 3 range
+ INT i_PCIEeprom; // eeprom present or not
+ char *pc_EepromChip; // type of chip
+ INT i_NbrAiChannel; // num of A/D chans
+ INT i_NbrAiChannelDiff; // num of A/D chans in diff mode
+ INT i_AiChannelList; // len of chanlist
+ INT i_NbrAoChannel; // num of D/A chans
+ INT i_AiMaxdata; // resolution of A/D
+ INT i_AoMaxdata; // resolution of D/A
+ PCRANGE pr_AiRangelist; // rangelist for A/D
+ PCRANGE pr_AoRangelist; // rangelist for D/A
+
+ INT i_NbrDiChannel; // Number of DI channels
+ INT i_NbrDoChannel; // Number of DO channels
+ INT i_DoMaxdata; // data to set all chanels high
+
+ INT i_NbrTTLChannel; // Number of TTL channels
+ PCRANGE pr_TTLRangelist; // rangelist for TTL
+
+ INT i_Dma; // dma present or not
+ INT i_Timer; // timer subdevice present or not
+ BYTE b_AvailableConvertUnit;
+ UINT ui_MinAcquisitiontimeNs; // Minimum Acquisition in Nano secs
+ UINT ui_MinDelaytimeNs; // Minimum Delay in Nano secs
+
+ /* interrupt and reset */
+ void (*v_hwdrv_Interrupt)(int irq, void *d);
+ int (*i_hwdrv_Reset)(struct comedi_device *dev);
+
+ /* Subdevice functions */
+
+ /* ANALOG INPUT */
+ int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd);
+ int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev,
+ struct comedi_subdevice *s);
+ int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev,
+ struct comedi_subdevice *s);
+
+ /* Analog Output */
+ int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+ /* Digital Input */
+ int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+ /* Digital Output */
+ int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+ /* TIMER */
+ int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+ int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+ int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+ /* TTL IO */
+ int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+ int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+ int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+} boardtype;
+
+//MODULE INFO STRUCTURE
+
+typedef union {
+ /* Incremental counter infos */
+ struct {
+ union {
+ struct {
+ BYTE b_ModeRegister1;
+ BYTE b_ModeRegister2;
+ BYTE b_ModeRegister3;
+ BYTE b_ModeRegister4;
+ } s_ByteModeRegister;
+ DWORD dw_ModeRegister1_2_3_4;
+ } s_ModeRegister;
+
+ struct {
+ unsigned int b_IndexInit:1;
+ unsigned int b_CounterInit:1;
+ unsigned int b_ReferenceInit:1;
+ unsigned int b_IndexInterruptOccur:1;
+ unsigned int b_CompareLogicInit:1;
+ unsigned int b_FrequencyMeasurementInit:1;
+ unsigned int b_FrequencyMeasurementEnable:1;
+ } s_InitFlag;
+
+ } s_SiemensCounterInfo;
+
+ /* SSI infos */
+ struct {
+ BYTE b_SSIProfile;
+ BYTE b_PositionTurnLength;
+ BYTE b_TurnCptLength;
+ BYTE b_SSIInit;
+ } s_SSICounterInfo;
+
+ /* TTL I/O infos */
+ struct {
+ BYTE b_TTLInit;
+ BYTE b_PortConfiguration[4];
+ } s_TTLIOInfo;
+
+ /* Digital I/O infos */
+ struct {
+ BYTE b_DigitalInit;
+ BYTE b_ChannelAMode;
+ BYTE b_ChannelBMode;
+ BYTE b_OutputMemoryEnabled;
+ DWORD dw_OutputMemory;
+ } s_DigitalIOInfo;
+
+ /*********************/
+ /* 82X54 timer infos */
+ /*********************/
+
+ struct {
+ struct {
+ BYTE b_82X54Init;
+ BYTE b_InputClockSelection;
+ BYTE b_InputClockLevel;
+ BYTE b_OutputLevel;
+ BYTE b_HardwareGateLevel;
+ DWORD dw_ConfigurationWord;
+ } s_82X54TimerInfo[3];
+ BYTE b_InterruptMask;
+ } s_82X54ModuleInfo;
+
+ /*********************/
+ /* Chronometer infos */
+ /*********************/
+
+ struct {
+ BYTE b_ChronoInit;
+ BYTE b_InterruptMask;
+ BYTE b_PCIInputClock;
+ BYTE b_TimingUnit;
+ BYTE b_CycleMode;
+ double d_TimingInterval;
+ DWORD dw_ConfigReg;
+ } s_ChronoModuleInfo;
+
+ /***********************/
+ /* Pulse encoder infos */
+ /***********************/
+
+ struct {
+ struct {
+ BYTE b_PulseEncoderInit;
+ } s_PulseEncoderInfo[4];
+ DWORD dw_SetRegister;
+ DWORD dw_ControlRegister;
+ DWORD dw_StatusRegister;
+ } s_PulseEncoderModuleInfo;
+
+ /* Tor conter infos */
+ struct {
+ struct {
+ BYTE b_TorCounterInit;
+ BYTE b_TimingUnit;
+ BYTE b_InterruptEnable;
+ double d_TimingInterval;
+ ULONG ul_RealTimingInterval;
+ } s_TorCounterInfo[2];
+ BYTE b_PCIInputClock;
+ } s_TorCounterModuleInfo;
+
+ /* PWM infos */
+ struct {
+ struct {
+ BYTE b_PWMInit;
+ BYTE b_TimingUnit;
+ BYTE b_InterruptEnable;
+ double d_LowTiming;
+ double d_HighTiming;
+ ULONG ul_RealLowTiming;
+ ULONG ul_RealHighTiming;
+ } s_PWMInfo[2];
+ BYTE b_ClockSelection;
+ } s_PWMModuleInfo;
+
+ /* ETM infos */
+ struct {
+ struct {
+ BYTE b_ETMEnable;
+ BYTE b_ETMInterrupt;
+ } s_ETMInfo[2];
+ BYTE b_ETMInit;
+ BYTE b_TimingUnit;
+ BYTE b_ClockSelection;
+ double d_TimingInterval;
+ ULONG ul_Timing;
+ } s_ETMModuleInfo;
+
+ /* CDA infos */
+ struct {
+ BYTE b_CDAEnable;
+ BYTE b_CDAInterrupt;
+ BYTE b_CDAInit;
+ BYTE b_FctSelection;
+ BYTE b_CDAReadFIFOOverflow;
+ } s_CDAModuleInfo;
+
+} str_ModuleInfo;
+
+/* Private structure for the addi_apci3120 driver */
+typedef struct {
+
+ INT iobase;
+ INT i_IobaseAmcc; // base+size for AMCC chip
+ INT i_IobaseAddon; //addon base address
+ INT i_IobaseReserved;
+ ULONG_PTR dw_AiBase;
+ struct pcilst_struct *amcc; // ptr too AMCC data
+ BYTE allocated; // we have blocked card
+ BYTE b_ValidDriver; // driver is ok
+ BYTE b_AiContinuous; // we do unlimited AI
+ BYTE b_AiInitialisation;
+ UINT ui_AiActualScan; //how many scans we finished
+ UINT ui_AiBufferPtr; // data buffer ptr in samples
+ UINT ui_AiNbrofChannels; // how many channels is measured
+ UINT ui_AiScanLength; // Length of actual scanlist
+ UINT ui_AiActualScanPosition; // position in actual scan
+ PUINT pui_AiChannelList; // actual chanlist
+ UINT ui_AiChannelList[32]; // actual chanlist
+ BYTE b_AiChannelConfiguration[32]; // actual chanlist
+ UINT ui_AiReadData[32];
+ DWORD dw_AiInitialised;
+ UINT ui_AiTimer0; //Timer Constant for Timer0
+ UINT ui_AiTimer1; //Timer constant for Timer1
+ UINT ui_AiFlags;
+ UINT ui_AiDataLength;
+ short *AiData; // Pointer to sample data
+ UINT ui_AiNbrofScans; // number of scans to do
+ USHORT us_UseDma; // To use Dma or not
+ BYTE b_DmaDoubleBuffer; // we can use double buffering
+ UINT ui_DmaActualBuffer; // which buffer is used now
+ //*UPDATE-0.7.57->0.7.68
+ //ULONG ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer
+ short *ul_DmaBufferVirtual[2]; // pointers to begin of DMA buffer
+ ULONG ul_DmaBufferHw[2]; // hw address of DMA buff
+ UINT ui_DmaBufferSize[2]; // size of dma buffer in bytes
+ UINT ui_DmaBufferUsesize[2]; // which size we may now used for transfer
+ UINT ui_DmaBufferSamples[2]; // size in samples
+ UINT ui_DmaBufferPages[2]; // number of pages in buffer
+ BYTE b_DigitalOutputRegister; // Digital Output Register
+ BYTE b_OutputMemoryStatus;
+ BYTE b_AnalogInputChannelNbr; // Analog input channel Nbr
+ BYTE b_AnalogOutputChannelNbr; // Analog input Output Nbr
+ BYTE b_TimerSelectMode; // Contain data written at iobase + 0C
+ BYTE b_ModeSelectRegister; // Contain data written at iobase + 0E
+ USHORT us_OutputRegister; // Contain data written at iobase + 0
+ BYTE b_InterruptState;
+ BYTE b_TimerInit; // Specify if InitTimerWatchdog was load
+ BYTE b_TimerStarted; // Specify if timer 2 is running or not
+ BYTE b_Timer2Mode; // Specify the timer 2 mode
+ BYTE b_Timer2Interrupt; //Timer2 interrupt enable or disable
+ BYTE b_AiCyclicAcquisition; // indicate cyclic acquisition
+ BYTE b_InterruptMode; // eoc eos or dma
+ BYTE b_EocEosInterrupt; // Enable disable eoc eos interrupt
+ UINT ui_EocEosConversionTime;
+ BYTE b_EocEosConversionTimeBase;
+ BYTE b_SingelDiff;
+ BYTE b_ExttrigEnable; /* To enable or disable external trigger */
+
+ /* Pointer to the current process */
+ struct task_struct *tsk_Current;
+ boardtype *ps_BoardInfo;
+
+ /* Hardware board infos for 1710 */
+ struct {
+ UINT ui_Address; /* Board address */
+ UINT ui_FlashAddress;
+ BYTE b_InterruptNbr; /* Board interrupt number */
+ BYTE b_SlotNumber; /* PCI slot number */
+ BYTE b_BoardVersion;
+ DWORD dw_MolduleConfiguration[4]; /* Module config */
+ } s_BoardInfos;
+
+ /* Interrupt infos */
+ struct {
+ ULONG ul_InterruptOccur; /* 0 : No interrupt occur */
+ /* > 0 : Interrupt occur */
+ UINT ui_Read; /* Read FIFO */
+ UINT ui_Write; /* Write FIFO */
+ struct {
+ BYTE b_OldModuleMask;
+ ULONG ul_OldInterruptMask; /* Interrupt mask */
+ ULONG ul_OldCounterLatchValue; /* Interrupt counter value */
+ } s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
+ } s_InterruptParameters;
+
+ str_ModuleInfo s_ModuleInfo[4];
+ ULONG ul_TTLPortConfiguration[10];
+
+} addi_private;
+
+static unsigned short pci_list_builded; /* set to 1 when list of card is known */
+
+/* Function declarations */
+static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it);
+static int i_ADDI_Detach(struct comedi_device *dev);
+static int i_ADDI_Reset(struct comedi_device *dev);
+
+static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG);
+static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
new file mode 100644
index 000000000000..a8a1bb2e8fa5
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
@@ -0,0 +1,1158 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : ADDI DATA | Compiler : GCC |
+ | Modulname : addi_eeprom.c | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description : ADDI EEPROM Module |
+ +-----------------------------------------------------------------------+
+ | UPDATE'S |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+#define NVCMD_BEGIN_READ (0x7 << 5 ) // nvRam begin read command
+#define NVCMD_LOAD_LOW (0x4 << 5 ) // nvRam load low command
+#define NVCMD_LOAD_HIGH (0x5 << 5 ) // nvRam load high command
+#define EE76_CMD_LEN 13 // bits in instructions
+#define EE_READ 0x0180 // 01 1000 0000 read instruction
+
+#define WORD unsigned short
+#define PWORD unsigned short *
+#define PDWORD unsigned int *
+
+#ifndef DWORD
+#define DWORD unsigned int
+#endif
+
+#define EEPROM_DIGITALINPUT 0
+#define EEPROM_DIGITALOUTPUT 1
+#define EEPROM_ANALOGINPUT 2
+#define EEPROM_ANALOGOUTPUT 3
+#define EEPROM_TIMER 4
+#define EEPROM_WATCHDOG 5
+#define EEPROM_TIMER_WATCHDOG_COUNTER 10
+
+struct str_Functionality {
+ BYTE b_Type;
+ WORD w_Address;
+};
+
+typedef struct {
+ WORD w_HeaderSize;
+ BYTE b_Nfunctions;
+ struct str_Functionality s_Functions[7];
+} str_MainHeader;
+
+typedef struct {
+ WORD w_Nchannel;
+ BYTE b_Interruptible;
+ WORD w_NinterruptLogic;
+} str_DigitalInputHeader;
+
+typedef struct {
+ WORD w_Nchannel;
+} str_DigitalOutputHeader;
+
+// used for timer as well as watchdog
+
+typedef struct {
+ WORD w_HeaderSize;
+ BYTE b_Resolution;
+ BYTE b_Mode; // in case of Watchdog it is functionality
+ WORD w_MinTiming;
+ BYTE b_TimeBase;
+} str_TimerDetails;
+typedef struct {
+
+ WORD w_Ntimer;
+ str_TimerDetails s_TimerDetails[4]; // supports 4 timers
+} str_TimerMainHeader;
+
+typedef struct {
+ WORD w_Nchannel;
+ BYTE b_Resolution;
+} str_AnalogOutputHeader;
+
+typedef struct {
+ WORD w_Nchannel;
+ WORD w_MinConvertTiming;
+ WORD w_MinDelayTiming;
+ BYTE b_HasDma;
+ BYTE b_Resolution;
+} str_AnalogInputHeader;
+
+ /*****************************************/
+ /* Read Header Functions */
+ /*****************************************/
+
+INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, struct comedi_device *dev);
+
+INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_DigitalInputHeader * s_Header);
+
+INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_DigitalOutputHeader * s_Header);
+
+INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_TimerMainHeader * s_Header);
+
+INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_AnalogOutputHeader * s_Header);
+
+INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_AnalogInputHeader * s_Header);
+
+ /******************************************/
+ /* Eeprom Specific Functions */
+ /******************************************/
+WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ WORD w_EepromStartAddress);
+void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
+void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress);
+void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ BYTE b_DataLengthInBits);
+void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value);
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : WORD w_EepromReadWord |
+| (WORD w_PCIBoardEepromAddress, |
+| char * pc_PCIChipInformation, |
+| WORD w_EepromStartAddress) |
++----------------------------------------------------------------------------+
+| Task : Read from eepromn a word |
++----------------------------------------------------------------------------+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address |
+| |
+| char *pc_PCIChipInformation : PCI Chip Type. |
+| |
+| WORD w_EepromStartAddress : Selected eeprom address |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : Read word value from eeprom |
++----------------------------------------------------------------------------+
+*/
+
+WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
+ WORD w_EepromStartAddress)
+{
+
+ BYTE b_Counter = 0;
+
+ BYTE b_ReadByte = 0;
+
+ BYTE b_ReadLowByte = 0;
+
+ BYTE b_ReadHighByte = 0;
+
+ BYTE b_SelectedAddressLow = 0;
+
+ BYTE b_SelectedAddressHigh = 0;
+
+ WORD w_ReadWord = 0;
+
+ /**************************/
+
+ /* Test the PCI chip type */
+
+ /**************************/
+
+ if ((!strcmp(pc_PCIChipInformation, "S5920")) ||
+ (!strcmp(pc_PCIChipInformation, "S5933")))
+ {
+
+ for (b_Counter = 0; b_Counter < 2; b_Counter++)
+ {
+
+ b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256; //Read the low 8 bit part
+
+ b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256; //Read the high 8 bit part
+
+ /************************************/
+
+ /* Select the load low address mode */
+
+ /************************************/
+
+ outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F);
+
+ /****************/
+
+ /* Wait on busy */
+
+ /****************/
+
+ v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+ /************************/
+
+ /* Load the low address */
+
+ /************************/
+
+ outb(b_SelectedAddressLow,
+ w_PCIBoardEepromAddress + 0x3E);
+
+ /****************/
+
+ /* Wait on busy */
+
+ /****************/
+
+ v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+ /*************************************/
+
+ /* Select the load high address mode */
+
+ /*************************************/
+
+ outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F);
+
+ /****************/
+
+ /* Wait on busy */
+
+ /****************/
+
+ v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+ /*************************/
+
+ /* Load the high address */
+
+ /*************************/
+
+ outb(b_SelectedAddressHigh,
+ w_PCIBoardEepromAddress + 0x3E);
+
+ /****************/
+
+ /* Wait on busy */
+
+ /****************/
+
+ v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+ /************************/
+
+ /* Select the READ mode */
+
+ /************************/
+
+ outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F);
+
+ /****************/
+
+ /* Wait on busy */
+
+ /****************/
+
+ v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+ /*****************************/
+
+ /* Read data into the EEPROM */
+
+ /*****************************/
+
+ b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E);
+
+ /****************/
+
+ /* Wait on busy */
+
+ /****************/
+
+ v_EepromWaitBusy(w_PCIBoardEepromAddress);
+
+ /*********************************/
+
+ /* Select the upper address part */
+
+ /*********************************/
+
+ if (b_Counter == 0)
+ {
+
+ b_ReadLowByte = b_ReadByte;
+
+ } // if(b_Counter==0)
+
+ else
+ {
+
+ b_ReadHighByte = b_ReadByte;
+
+ } // if(b_Counter==0)
+
+ } // for (b_Counter=0; b_Counter<2; b_Counter++)
+
+ w_ReadWord = (b_ReadLowByte | (((WORD) b_ReadHighByte) * 256));
+
+ } // end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933")))
+
+ if (!strcmp(pc_PCIChipInformation, "93C76"))
+ {
+
+ /*************************************/
+
+ /* Read 16 bit from the EEPROM 93C76 */
+
+ /*************************************/
+
+ v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress,
+ &w_ReadWord);
+
+ }
+
+ return (w_ReadWord);
+
+}
+
+/*
+
++----------------------------------------------------------------------------+
+
+| Function Name : void v_EepromWaitBusy |
+
+| (WORD w_PCIBoardEepromAddress) |
+
++----------------------------------------------------------------------------+
+
+| Task : Wait the busy flag from PCI controller |
+
++----------------------------------------------------------------------------+
+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom base address |
+
++----------------------------------------------------------------------------+
+
+| Output Parameters : - |
+
++----------------------------------------------------------------------------+
+
+| Return Value : - |
+
++----------------------------------------------------------------------------+
+
+*/
+
+void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress)
+{
+
+ BYTE b_EepromBusy = 0;
+
+ do
+ {
+
+ /*************/
+
+ /* IMPORTANT */
+
+ /*************/
+
+ /************************************************************************/
+
+ /* An error has been written in the AMCC 5933 book at the page B-13 */
+
+ /* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and */
+
+ /* the operator register is AMCC_OP_REG_MCSR+3 */
+
+ /* WORD read EEPROM=0x8000 andAMCC_OP_REG_MCSR+2 */
+
+ /* DWORD read EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
+
+ /************************************************************************/
+
+ b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F);
+ b_EepromBusy = b_EepromBusy & 0x80;
+
+ }
+ while (b_EepromBusy == 0x80);
+
+}
+
+/*
+
++---------------------------------------------------------------------------------+
+
+| Function Name : void v_EepromClock76(DWORD dw_Address, |
+
+| DWORD dw_RegisterValue) |
+
++---------------------------------------------------------------------------------+
+
+| Task : This function sends the clocking sequence to the EEPROM. |
+
++---------------------------------------------------------------------------------+
+
+| Input Parameters : DWORD dw_Address : PCI eeprom base address |
+
+| DWORD dw_RegisterValue : PCI eeprom register value to write.|
+
++---------------------------------------------------------------------------------+
+
+| Output Parameters : - |
+
++---------------------------------------------------------------------------------+
+
+| Return Value : - |
+
++---------------------------------------------------------------------------------+
+
+*/
+
+void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue)
+{
+
+ /************************/
+
+ /* Set EEPROM clock Low */
+
+ /************************/
+
+ outl(dw_RegisterValue & 0x6, dw_Address);
+
+ /***************/
+
+ /* Wait 0.1 ms */
+
+ /***************/
+
+ udelay(100);
+
+ /*************************/
+
+ /* Set EEPROM clock High */
+
+ /*************************/
+
+ outl(dw_RegisterValue | 0x1, dw_Address);
+
+ /***************/
+
+ /* Wait 0.1 ms */
+
+ /***************/
+
+ udelay(100);
+
+}
+
+/*
+
++---------------------------------------------------------------------------------+
+
+| Function Name : void v_EepromSendCommand76(DWORD dw_Address, |
+
+| DWORD dw_EepromCommand, |
+
+| BYTE b_DataLengthInBits) |
+
++---------------------------------------------------------------------------------+
+
+| Task : This function sends a Command to the EEPROM 93C76. |
+
++---------------------------------------------------------------------------------+
+
+| Input Parameters : DWORD dw_Address : PCI eeprom base address |
+
+| DWORD dw_EepromCommand : PCI eeprom command to write. |
+
+| BYTE b_DataLengthInBits : PCI eeprom command data length. |
+
++---------------------------------------------------------------------------------+
+
+| Output Parameters : - |
+
++---------------------------------------------------------------------------------+
+
+| Return Value : - |
+
++---------------------------------------------------------------------------------+
+
+*/
+
+void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
+ BYTE b_DataLengthInBits)
+{
+
+ char c_BitPos = 0;
+
+ DWORD dw_RegisterValue = 0;
+
+ /*****************************/
+
+ /* Enable EEPROM Chip Select */
+
+ /*****************************/
+
+ dw_RegisterValue = 0x2;
+
+ /********************************************************************/
+
+ /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
+
+ /********************************************************************/
+
+ outl(dw_RegisterValue, dw_Address);
+
+ /***************/
+
+ /* Wait 0.1 ms */
+
+ /***************/
+
+ udelay(100);
+
+ /*******************************************/
+
+ /* Send EEPROM command - one bit at a time */
+
+ /*******************************************/
+
+ for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--)
+ {
+
+ /**********************************/
+
+ /* Check if current bit is 0 or 1 */
+
+ /**********************************/
+
+ if (dw_EepromCommand & (1 << c_BitPos))
+ {
+
+ /***********/
+
+ /* Write 1 */
+
+ /***********/
+
+ dw_RegisterValue = dw_RegisterValue | 0x4;
+
+ }
+
+ else
+ {
+
+ /***********/
+
+ /* Write 0 */
+
+ /***********/
+
+ dw_RegisterValue = dw_RegisterValue & 0x3;
+
+ }
+
+ /*********************/
+
+ /* Write the command */
+
+ /*********************/
+
+ outl(dw_RegisterValue, dw_Address);
+
+ /***************/
+
+ /* Wait 0.1 ms */
+
+ /***************/
+
+ udelay(100);
+
+ /****************************/
+
+ /* Trigger the EEPROM clock */
+
+ /****************************/
+
+ v_EepromClock76(dw_Address, dw_RegisterValue);
+
+ }
+
+}
+
+/*
+
++---------------------------------------------------------------------------------+
+
+| Function Name : void v_EepromCs76Read(DWORD dw_Address, |
+
+| WORD w_offset, |
+
+| PWORD pw_Value) |
+
++---------------------------------------------------------------------------------+
+
+| Task : This function read a value from the EEPROM 93C76. |
+
++---------------------------------------------------------------------------------+
+
+| Input Parameters : DWORD dw_Address : PCI eeprom base address |
+
+| WORD w_offset : Offset of the adress to read |
+
+| PWORD pw_Value : PCI eeprom 16 bit read value. |
+
++---------------------------------------------------------------------------------+
+
+| Output Parameters : - |
+
++---------------------------------------------------------------------------------+
+
+| Return Value : - |
+
++---------------------------------------------------------------------------------+
+
+*/
+
+void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value)
+{
+
+ char c_BitPos = 0;
+
+ DWORD dw_RegisterValue = 0;
+
+ DWORD dw_RegisterValueRead = 0;
+
+ /*************************************************/
+
+ /* Send EEPROM read command and offset to EEPROM */
+
+ /*************************************************/
+
+ v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2),
+ EE76_CMD_LEN);
+
+ /*******************************/
+
+ /* Get the last register value */
+
+ /*******************************/
+
+ dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2;
+
+ /*****************************/
+
+ /* Set the 16-bit value of 0 */
+
+ /*****************************/
+
+ *pw_Value = 0;
+
+ /************************/
+
+ /* Get the 16-bit value */
+
+ /************************/
+
+ for (c_BitPos = 0; c_BitPos < 16; c_BitPos++)
+ {
+
+ /****************************/
+
+ /* Trigger the EEPROM clock */
+
+ /****************************/
+
+ v_EepromClock76(dw_Address, dw_RegisterValue);
+
+ /**********************/
+
+ /* Get the result bit */
+
+ /**********************/
+
+ dw_RegisterValueRead = inl(dw_Address);
+
+ /***************/
+
+ /* Wait 0.1 ms */
+
+ /***************/
+
+ udelay(100);
+
+ /***************************************/
+
+ /* Get bit value and shift into result */
+
+ /***************************************/
+
+ if (dw_RegisterValueRead & 0x8)
+ {
+
+ /**********/
+
+ /* Read 1 */
+
+ /**********/
+
+ *pw_Value = (*pw_Value << 1) | 0x1;
+
+ }
+
+ else
+ {
+
+ /**********/
+
+ /* Read 0 */
+
+ /**********/
+
+ *pw_Value = (*pw_Value << 1);
+
+ }
+
+ }
+
+ /*************************/
+
+ /* Clear all EEPROM bits */
+
+ /*************************/
+
+ dw_RegisterValue = 0x0;
+
+ /********************************************************************/
+
+ /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
+
+ /********************************************************************/
+
+ outl(dw_RegisterValue, dw_Address);
+
+ /***************/
+
+ /* Wait 0.1 ms */
+
+ /***************/
+
+ udelay(100);
+
+}
+
+ /******************************************/
+ /* EEPROM HEADER READ FUNCTIONS */
+ /******************************************/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress, |
+| char * pc_PCIChipInformation,struct comedi_device *dev) |
++----------------------------------------------------------------------------+
+| Task : Read from eeprom Main Header |
++----------------------------------------------------------------------------+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address |
+| |
+| char *pc_PCIChipInformation : PCI Chip Type. |
+| |
+| struct comedi_device *dev : comedi device structure |
+| pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
++----------------------------------------------------------------------------+
+*/
+
+INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, struct comedi_device *dev)
+{
+ WORD w_Temp, i, w_Count = 0;
+ UINT ui_Temp;
+ str_MainHeader s_MainHeader;
+ str_DigitalInputHeader s_DigitalInputHeader;
+ str_DigitalOutputHeader s_DigitalOutputHeader;
+ //str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader;
+ str_AnalogOutputHeader s_AnalogOutputHeader;
+ str_AnalogInputHeader s_AnalogInputHeader;
+
+ // Read size
+ s_MainHeader.w_HeaderSize =
+ w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 0x100 + 8);
+
+ // Read nbr of functionality
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + 10);
+ s_MainHeader.b_Nfunctions = (BYTE) w_Temp & 0x00FF;
+
+ // Read functionality details
+ for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+ // Read Type
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + 12 + w_Count);
+ s_MainHeader.s_Functions[i].b_Type = (BYTE) w_Temp & 0x3F;
+ w_Count = w_Count + 2;
+ //Read Address
+ s_MainHeader.s_Functions[i].w_Address =
+ w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + 12 + w_Count);
+ w_Count = w_Count + 2;
+ }
+
+ // Display main header info
+ for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+
+ switch (s_MainHeader.s_Functions[i].b_Type) {
+ case EEPROM_DIGITALINPUT:
+ i_EepromReadDigitalInputHeader(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation,
+ s_MainHeader.s_Functions[i].w_Address,
+ &s_DigitalInputHeader);
+ this_board->i_NbrDiChannel =
+ s_DigitalInputHeader.w_Nchannel;
+ break;
+
+ case EEPROM_DIGITALOUTPUT:
+ i_EepromReadDigitalOutputHeader(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation,
+ s_MainHeader.s_Functions[i].w_Address,
+ &s_DigitalOutputHeader);
+ this_board->i_NbrDoChannel =
+ s_DigitalOutputHeader.w_Nchannel;
+ ui_Temp = 0xffffffff;
+ this_board->i_DoMaxdata =
+ ui_Temp >> (32 - this_board->i_NbrDoChannel);
+ break;
+
+ case EEPROM_ANALOGINPUT:
+ i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation,
+ s_MainHeader.s_Functions[i].w_Address,
+ &s_AnalogInputHeader);
+ if (!(strcmp(this_board->pc_DriverName, "apci3200")))
+ this_board->i_NbrAiChannel =
+ s_AnalogInputHeader.w_Nchannel * 4;
+ else
+ this_board->i_NbrAiChannel =
+ s_AnalogInputHeader.w_Nchannel;
+ this_board->i_Dma = s_AnalogInputHeader.b_HasDma;
+ this_board->ui_MinAcquisitiontimeNs =
+ (UINT) s_AnalogInputHeader.w_MinConvertTiming *
+ 1000;
+ this_board->ui_MinDelaytimeNs =
+ (UINT) s_AnalogInputHeader.w_MinDelayTiming *
+ 1000;
+ ui_Temp = 0xffff;
+ this_board->i_AiMaxdata =
+ ui_Temp >> (16 -
+ s_AnalogInputHeader.b_Resolution);
+ break;
+
+ case EEPROM_ANALOGOUTPUT:
+ i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation,
+ s_MainHeader.s_Functions[i].w_Address,
+ &s_AnalogOutputHeader);
+ this_board->i_NbrAoChannel =
+ s_AnalogOutputHeader.w_Nchannel;
+ ui_Temp = 0xffff;
+ this_board->i_AoMaxdata =
+ ui_Temp >> (16 -
+ s_AnalogOutputHeader.b_Resolution);
+ break;
+
+ case EEPROM_TIMER:
+ this_board->i_Timer = 1; //Timer subdevice present
+ break;
+
+ case EEPROM_WATCHDOG:
+ this_board->i_Timer = 1; //Timer subdevice present
+ break;
+
+ case EEPROM_TIMER_WATCHDOG_COUNTER:
+ this_board->i_Timer = 1; //Timer subdevice present
+ }
+ }
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_EepromReadDigitalInputHeader(WORD |
+| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, |
+| WORD w_Address,str_DigitalInputHeader *s_Header) |
+| |
++----------------------------------------------------------------------------+
+| Task : Read Digital Input Header |
++----------------------------------------------------------------------------+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address |
+| |
+| char *pc_PCIChipInformation : PCI Chip Type. |
+| |
+| str_DigitalInputHeader *s_Header: Digita Input Header |
+| Pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
++----------------------------------------------------------------------------+
+*/
+INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_DigitalInputHeader * s_Header)
+{
+ WORD w_Temp;
+
+ // read nbr of channels
+ s_Header->w_Nchannel =
+ w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 0x100 + w_Address + 6);
+
+ // interruptible or not
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + w_Address + 8);
+ s_Header->b_Interruptible = (BYTE) (w_Temp >> 7) & 0x01;
+
+// How many interruptible logic
+ s_Header->w_NinterruptLogic =
+ w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 0x100 + w_Address + 10);
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_EepromReadDigitalOutputHeader(WORD |
+| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, |
+| WORD w_Address,str_DigitalOutputHeader *s_Header) |
+| |
++----------------------------------------------------------------------------+
+| Task : Read Digital Output Header |
++----------------------------------------------------------------------------+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address |
+| |
+| char *pc_PCIChipInformation : PCI Chip Type. |
+| |
+| str_DigitalOutputHeader *s_Header: Digital Output Header|
+| Pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
++----------------------------------------------------------------------------+
+*/
+INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_DigitalOutputHeader * s_Header)
+{
+// Read Nbr channels
+ s_Header->w_Nchannel =
+ w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 0x100 + w_Address + 6);
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, |
+| char *pc_PCIChipInformation,WORD w_Address, |
+| str_TimerMainHeader *s_Header) |
++----------------------------------------------------------------------------+
+| Task : Read Timer or Watchdog Header |
++----------------------------------------------------------------------------+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address |
+| |
+| char *pc_PCIChipInformation : PCI Chip Type. |
+| |
+| str_TimerMainHeader *s_Header: Timer Header |
+| Pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
++----------------------------------------------------------------------------+
+*/
+INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_TimerMainHeader * s_Header)
+{
+
+ WORD i, w_Size = 0, w_Temp;
+
+//Read No of Timer
+ s_Header->w_Ntimer =
+ w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 0x100 + w_Address + 6);
+//Read header size
+
+ for (i = 0; i < s_Header->w_Ntimer; i++) {
+ s_Header->s_TimerDetails[i].w_HeaderSize =
+ w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation,
+ 0x100 + w_Address + 8 + w_Size + 0);
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation,
+ 0x100 + w_Address + 8 + w_Size + 2);
+
+ //Read Resolution
+ s_Header->s_TimerDetails[i].b_Resolution =
+ (BYTE) (w_Temp >> 10) & 0x3F;
+
+ //Read Mode
+ s_Header->s_TimerDetails[i].b_Mode =
+ (BYTE) (w_Temp >> 4) & 0x3F;
+
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation,
+ 0x100 + w_Address + 8 + w_Size + 4);
+
+ //Read MinTiming
+ s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF;
+
+ //Read Timebase
+ s_Header->s_TimerDetails[i].b_TimeBase = (BYTE) (w_Temp) & 0x3F;
+ w_Size += s_Header->s_TimerDetails[i].w_HeaderSize;
+ }
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_EepromReadAnlogOutputHeader(WORD |
+| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, |
+| WORD w_Address,str_AnalogOutputHeader *s_Header) |
++----------------------------------------------------------------------------+
+| Task : Read Nalog Output Header |
++----------------------------------------------------------------------------+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address |
+| |
+| char *pc_PCIChipInformation : PCI Chip Type. |
+| |
+| str_AnalogOutputHeader *s_Header:Anlog Output Header |
+| Pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
++----------------------------------------------------------------------------+
+*/
+
+INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_AnalogOutputHeader * s_Header)
+{
+ WORD w_Temp;
+ // No of channels for 1st hard component
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + w_Address + 10);
+ s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
+ // Resolution for 1st hard component
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + w_Address + 16);
+ s_Header->b_Resolution = (BYTE) (w_Temp >> 8) & 0xFF;
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_EepromReadAnlogInputHeader(WORD |
+| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, |
+| WORD w_Address,str_AnalogInputHeader *s_Header) |
++----------------------------------------------------------------------------+
+| Task : Read Nalog Output Header |
++----------------------------------------------------------------------------+
+| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address |
+| |
+| char *pc_PCIChipInformation : PCI Chip Type. |
+| |
+| str_AnalogInputHeader *s_Header:Anlog Input Header |
+| Pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
++----------------------------------------------------------------------------+
+*/
+
+// Reads only for ONE hardware component
+INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,
+ char *pc_PCIChipInformation, WORD w_Address,
+ str_AnalogInputHeader * s_Header)
+{
+ WORD w_Temp, w_Offset;
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + w_Address + 10);
+ s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
+ s_Header->w_MinConvertTiming =
+ w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 0x100 + w_Address + 16);
+ s_Header->w_MinDelayTiming =
+ w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
+ 0x100 + w_Address + 30);
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + w_Address + 20);
+ s_Header->b_HasDma = (w_Temp >> 13) & 0x01; // whether dma present or not
+
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72); // reading Y
+ w_Temp = w_Temp & 0x00FF;
+ if (w_Temp) //Y>0
+ {
+ w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16))); // offset of first analog input single header
+ w_Offset = w_Offset + 2; // resolution
+ } else //Y=0
+ {
+ w_Offset = 74;
+ w_Offset = w_Offset + 2; // resolution
+ }
+
+// read Resolution
+ w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
+ pc_PCIChipInformation, 0x100 + w_Address + w_Offset);
+ s_Header->b_Resolution = w_Temp & 0x001F; // last 5 bits
+
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
new file mode 100644
index 000000000000..617dc087dcbf
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
@@ -0,0 +1,457 @@
+/*
+ Modified by umesh on 16th may 2001
+ Modified by sarath on 22nd may 2001
+*/
+
+/*
+ comedi/drivers/amcc_s5933_v_58.h
+
+ Stuff for AMCC S5933 PCI Controller
+
+ Author: Michal Dobes <majkl@tesnet.cz>
+
+ Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver
+ made by Andrea Cisternino <acister@pcape1.pi.infn.it>
+ and as result of espionage from MITE code made by David A. Schleef.
+ Thanks to AMCC for their on-line documentation and bus master DMA
+ example.
+*/
+
+#ifndef _AMCC_S5933_H_
+#define _AMCC_S5933_H_
+
+#include <linux/pci.h>
+#include "../../comedidev.h"
+
+#ifdef PCI_SUPPORT_VER1
+#error Sorry, no support for 2.1.55 and older! :-((((
+#endif
+
+/***********Added by sarath for compatibility with APCI3120
+
+*************************/
+
+#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 // written on base0
+
+#define AMWEN_ENABLE 0x02 // added for step 6 dma written on base2
+#define A2P_FIFO_WRITE_ENABLE 0x01
+
+#define AGCSTS_TC_ENABLE 0x10000000 // Added for transfer count enable bit
+
+// ADDON RELATED ADDITIONS
+// Constant
+#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00
+#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200
+#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L
+#define APCI3120_AMWEN_ENABLE 0x02
+#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01
+#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L
+#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L
+#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L
+#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0
+#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0
+#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0
+
+ // ADD_ON ::: this needed since apci supports 16 bit interface to add on
+#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C
+#define APCI3120_ADD_ON_AGCSTS_HIGH APCI3120_ADD_ON_AGCSTS_LOW + 2
+#define APCI3120_ADD_ON_MWAR_LOW 0x24
+#define APCI3120_ADD_ON_MWAR_HIGH APCI3120_ADD_ON_MWAR_LOW + 2
+#define APCI3120_ADD_ON_MWTC_LOW 0x058
+#define APCI3120_ADD_ON_MWTC_HIGH APCI3120_ADD_ON_MWTC_LOW + 2
+
+// AMCC
+#define APCI3120_AMCC_OP_MCSR 0x3C
+#define APCI3120_AMCC_OP_REG_INTCSR 0x38
+
+/*******from here all upward definitions are added by sarath */
+
+/****************************************************************************/
+/* AMCC Operation Register Offsets - PCI */
+/****************************************************************************/
+
+#define AMCC_OP_REG_OMB1 0x00
+#define AMCC_OP_REG_OMB2 0x04
+#define AMCC_OP_REG_OMB3 0x08
+#define AMCC_OP_REG_OMB4 0x0c
+#define AMCC_OP_REG_IMB1 0x10
+#define AMCC_OP_REG_IMB2 0x14
+#define AMCC_OP_REG_IMB3 0x18
+#define AMCC_OP_REG_IMB4 0x1c
+#define AMCC_OP_REG_FIFO 0x20
+#define AMCC_OP_REG_MWAR 0x24
+#define AMCC_OP_REG_MWTC 0x28
+#define AMCC_OP_REG_MRAR 0x2c
+#define AMCC_OP_REG_MRTC 0x30
+#define AMCC_OP_REG_MBEF 0x34
+#define AMCC_OP_REG_INTCSR 0x38
+#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* INT source */
+#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */
+#define AMCC_OP_REG_MCSR 0x3c
+#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */
+#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */
+
+#define AMCC_FIFO_DEPTH_DWORD 8
+#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32))
+
+/****************************************************************************/
+/* AMCC Operation Registers Size - PCI */
+/****************************************************************************/
+
+#define AMCC_OP_REG_SIZE 64 /* in bytes */
+
+/****************************************************************************/
+/* AMCC Operation Register Offsets - Add-on */
+/****************************************************************************/
+
+#define AMCC_OP_REG_AIMB1 0x00
+#define AMCC_OP_REG_AIMB2 0x04
+#define AMCC_OP_REG_AIMB3 0x08
+#define AMCC_OP_REG_AIMB4 0x0c
+#define AMCC_OP_REG_AOMB1 0x10
+#define AMCC_OP_REG_AOMB2 0x14
+#define AMCC_OP_REG_AOMB3 0x18
+#define AMCC_OP_REG_AOMB4 0x1c
+#define AMCC_OP_REG_AFIFO 0x20
+#define AMCC_OP_REG_AMWAR 0x24
+#define AMCC_OP_REG_APTA 0x28
+#define AMCC_OP_REG_APTD 0x2c
+#define AMCC_OP_REG_AMRAR 0x30
+#define AMCC_OP_REG_AMBEF 0x34
+#define AMCC_OP_REG_AINT 0x38
+#define AMCC_OP_REG_AGCSTS 0x3c
+#define AMCC_OP_REG_AMWTC 0x58
+#define AMCC_OP_REG_AMRTC 0x5c
+
+/****************************************************************************/
+/* AMCC - Add-on General Control/Status Register */
+/****************************************************************************/
+
+#define AGCSTS_CONTROL_MASK 0xfffff000
+#define AGCSTS_NV_ACC_MASK 0xe0000000
+#define AGCSTS_RESET_MASK 0x0e000000
+#define AGCSTS_NV_DA_MASK 0x00ff0000
+#define AGCSTS_BIST_MASK 0x0000f000
+#define AGCSTS_STATUS_MASK 0x000000ff
+#define AGCSTS_TCZERO_MASK 0x000000c0
+#define AGCSTS_FIFO_ST_MASK 0x0000003f
+
+#define AGCSTS_RESET_MBFLAGS 0x08000000
+#define AGCSTS_RESET_P2A_FIFO 0x04000000
+#define AGCSTS_RESET_A2P_FIFO 0x02000000
+#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
+
+#define AGCSTS_A2P_TCOUNT 0x00000080
+#define AGCSTS_P2A_TCOUNT 0x00000040
+
+#define AGCSTS_FS_P2A_EMPTY 0x00000020
+#define AGCSTS_FS_P2A_HALF 0x00000010
+#define AGCSTS_FS_P2A_FULL 0x00000008
+
+#define AGCSTS_FS_A2P_EMPTY 0x00000004
+#define AGCSTS_FS_A2P_HALF 0x00000002
+#define AGCSTS_FS_A2P_FULL 0x00000001
+
+/****************************************************************************/
+/* AMCC - Add-on Interrupt Control/Status Register */
+/****************************************************************************/
+
+#define AINT_INT_MASK 0x00ff0000
+#define AINT_SEL_MASK 0x0000ffff
+#define AINT_IS_ENSEL_MASK 0x00001f1f
+
+#define AINT_INT_ASSERTED 0x00800000
+#define AINT_BM_ERROR 0x00200000
+#define AINT_BIST_INT 0x00100000
+
+#define AINT_RT_COMPLETE 0x00080000
+#define AINT_WT_COMPLETE 0x00040000
+
+#define AINT_OUT_MB_INT 0x00020000
+#define AINT_IN_MB_INT 0x00010000
+
+#define AINT_READ_COMPL 0x00008000
+#define AINT_WRITE_COMPL 0x00004000
+
+#define AINT_OMB_ENABLE 0x00001000
+#define AINT_OMB_SELECT 0x00000c00
+#define AINT_OMB_BYTE 0x00000300
+
+#define AINT_IMB_ENABLE 0x00000010
+#define AINT_IMB_SELECT 0x0000000c
+#define AINT_IMB_BYTE 0x00000003
+
+/* Enable Bus Mastering */
+#define EN_A2P_TRANSFERS 0x00000400
+/* FIFO Flag Reset */
+#define RESET_A2P_FLAGS 0x04000000L
+/* FIFO Relative Priority */
+#define A2P_HI_PRIORITY 0x00000100L
+/* Identify Interrupt Sources */
+#define ANY_S593X_INT 0x00800000L
+#define READ_TC_INT 0x00080000L
+#define WRITE_TC_INT 0x00040000L
+#define IN_MB_INT 0x00020000L
+#define MASTER_ABORT_INT 0x00100000L
+#define TARGET_ABORT_INT 0x00200000L
+#define BUS_MASTER_INT 0x00200000L
+
+/****************************************************************************/
+
+struct pcilst_struct {
+ struct pcilst_struct *next;
+ int used;
+ struct pci_dev *pcidev;
+ unsigned short vendor;
+ unsigned short device;
+ unsigned int master;
+ unsigned char pci_bus;
+ unsigned char pci_slot;
+ unsigned char pci_func;
+ unsigned int io_addr[5];
+ unsigned int irq;
+};
+
+struct pcilst_struct *amcc_devices; // ptr to root list of all amcc devices
+
+/****************************************************************************/
+
+void v_pci_card_list_init(unsigned short pci_vendor, char display);
+void v_pci_card_list_cleanup(unsigned short pci_vendor);
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+ unsigned short
+ device_id);
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot,
+ struct pcilst_struct **card);
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot);
+
+int i_pci_card_alloc(struct pcilst_struct *amcc);
+int i_pci_card_free(struct pcilst_struct *amcc);
+void v_pci_card_list_display(void);
+int i_pci_card_data(struct pcilst_struct *amcc,
+ unsigned char *pci_bus, unsigned char *pci_slot,
+ unsigned char *pci_func, unsigned short *io_addr,
+ unsigned short *irq, unsigned short *master);
+
+/****************************************************************************/
+
+/* build list of amcc cards in this system */
+void v_pci_card_list_init(unsigned short pci_vendor, char display)
+{
+ struct pci_dev *pcidev;
+ struct pcilst_struct *amcc, *last;
+ int i;
+
+ amcc_devices = NULL;
+ last = NULL;
+
+ pci_for_each_dev(pcidev) {
+ if (pcidev->vendor == pci_vendor) {
+ amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
+ memset(amcc, 0, sizeof(*amcc));
+
+ amcc->pcidev = pcidev;
+ if (last) {
+ last->next = amcc;
+ } else {
+ amcc_devices = amcc;
+ }
+ last = amcc;
+
+ amcc->vendor = pcidev->vendor;
+ amcc->device = pcidev->device;
+#if 0
+ amcc->master = pcidev->master; // how get this information under 2.4 kernels?
+#endif
+ amcc->pci_bus = pcidev->bus->number;
+ amcc->pci_slot = PCI_SLOT(pcidev->devfn);
+ amcc->pci_func = PCI_FUNC(pcidev->devfn);
+ for (i = 0; i < 5; i++)
+ amcc->io_addr[i] =
+ pcidev->resource[i].start & ~3UL;
+ amcc->irq = pcidev->irq;
+ }
+ }
+
+ if (display)
+ v_pci_card_list_display();
+}
+
+/****************************************************************************/
+/* free up list of amcc cards in this system */
+void v_pci_card_list_cleanup(unsigned short pci_vendor)
+{
+ struct pcilst_struct *amcc, *next;
+
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ kfree(amcc);
+ }
+
+ amcc_devices = NULL;
+}
+
+/****************************************************************************/
+/* find first unused card with this device_id */
+struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
+ unsigned short device_id)
+{
+ struct pcilst_struct *amcc, *next;
+
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ if ((!amcc->used) && (amcc->device == device_id)
+ && (amcc->vendor == vendor_id))
+ return amcc;
+
+ }
+
+ return NULL;
+}
+
+/****************************************************************************/
+/* find card on requested position */
+int i_find_free_pci_card_by_position(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot,
+ struct pcilst_struct **card)
+{
+ struct pcilst_struct *amcc, *next;
+
+ *card = NULL;
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
+ && (amcc->pci_bus == pci_bus)
+ && (amcc->pci_slot == pci_slot)) {
+ if (!(amcc->used)) {
+ *card = amcc;
+ return 0; // ok, card is found
+ } else {
+ rt_printk
+ (" - \nCard on requested position is used b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return 2; // card exist but is used
+ }
+ }
+ }
+
+ return 1; // no card found
+}
+
+/****************************************************************************/
+/* mark card as used */
+int i_pci_card_alloc(struct pcilst_struct *amcc)
+{
+ if (!amcc)
+ return -1;
+
+ if (amcc->used)
+ return 1;
+ amcc->used = 1;
+ return 0;
+}
+
+/****************************************************************************/
+/* mark card as free */
+int i_pci_card_free(struct pcilst_struct *amcc)
+{
+ if (!amcc)
+ return -1;
+
+ if (!amcc->used)
+ return 1;
+ amcc->used = 0;
+ return 0;
+}
+
+/****************************************************************************/
+/* display list of found cards */
+void v_pci_card_list_display(void)
+{
+ struct pcilst_struct *amcc, *next;
+
+ printk("List of pci cards\n");
+ printk("bus:slot:func vendor device master io_amcc io_daq irq used\n");
+
+ for (amcc = amcc_devices; amcc; amcc = next) {
+ next = amcc->next;
+ printk
+ ("%2d %2d %2d 0x%4x 0x%4x %3s 0x%4x 0x%4x %2d %2d\n",
+ amcc->pci_bus, amcc->pci_slot, amcc->pci_func,
+ amcc->vendor, amcc->device, amcc->master ? "yes" : "no",
+ amcc->io_addr[0], amcc->io_addr[2], amcc->irq, amcc->used);
+
+ }
+}
+
+/****************************************************************************/
+/* return all card information for driver */
+int i_pci_card_data(struct pcilst_struct *amcc,
+ unsigned char *pci_bus, unsigned char *pci_slot,
+ unsigned char *pci_func, unsigned short *io_addr,
+ unsigned short *irq, unsigned short *master)
+{
+ int i;
+
+ if (!amcc)
+ return -1;
+ *pci_bus = amcc->pci_bus;
+ *pci_slot = amcc->pci_slot;
+ *pci_func = amcc->pci_func;
+ for (i = 0; i < 5; i++)
+ io_addr[i] = amcc->io_addr[i];
+ *irq = amcc->irq;
+ *master = amcc->master;
+ return 0;
+}
+
+/****************************************************************************/
+/* select and alloc card */
+struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned short pci_bus,
+ unsigned short pci_slot)
+{
+ struct pcilst_struct *card;
+
+ if ((pci_bus < 1) & (pci_slot < 1)) { // use autodetection
+ if ((card = ptr_find_free_pci_card_by_device(vendor_id,
+ device_id)) ==
+ NULL) {
+ rt_printk(" - Unused card not found in system!\n");
+ return NULL;
+ }
+ } else {
+ switch (i_find_free_pci_card_by_position(vendor_id, device_id,
+ pci_bus, pci_slot,
+ &card)) {
+ case 1:
+ rt_printk
+ (" - Card not found on requested position b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return NULL;
+ case 2:
+ rt_printk
+ (" - Card on requested position is used b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return NULL;
+ }
+ }
+
+ if (i_pci_card_alloc(card) != 0) {
+ rt_printk(" - Can't allocate card!\n");
+ return NULL;
+ }
+
+ return card;
+}
+
+#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
new file mode 100644
index 000000000000..3f8929c09070
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
@@ -0,0 +1,1265 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-1710 | Compiler : GCC |
+ | Module name : hwdrv_apci1710.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-1710 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+#include "hwdrv_APCI1710.h"
+#include "APCI1710_Inp_cpt.c"
+
+#include "APCI1710_Ssi.c"
+#include "APCI1710_Tor.c"
+#include "APCI1710_Ttl.c"
+#include "APCI1710_Dig_io.c"
+#include "APCI1710_82x54.c"
+#include "APCI1710_Chrono.c"
+#include "APCI1710_Pwm.c"
+#include "APCI1710_INCCPT.c"
+
+void i_ADDI_AttachPCI1710(struct comedi_device * dev)
+{
+ struct comedi_subdevice *s;
+ int ret = 0;
+ int n_subdevices = 9;
+
+ //Update-0.7.57->0.7.68dev->n_subdevices = 9;
+ if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+ return;
+
+ // Allocate and Initialise Timer Subdevice Structures
+ s = dev->subdevices + 0;
+
+ s->type = COMEDI_SUBD_TIMER;
+ s->subdev_flags = SDF_WRITEABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 3;
+ s->maxdata = 0;
+ s->len_chanlist = 3;
+ s->range_table = &range_digital;
+ s->insn_write = i_APCI1710_InsnWriteEnableDisableTimer;
+ s->insn_read = i_APCI1710_InsnReadAllTimerValue;
+ s->insn_config = i_APCI1710_InsnConfigInitTimer;
+ s->insn_bits = i_APCI1710_InsnBitsTimer;
+
+ // Allocate and Initialise DIO Subdevice Structures
+ s = dev->subdevices + 1;
+
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 7;
+ s->maxdata = 1;
+ s->len_chanlist = 7;
+ s->range_table = &range_digital;
+ s->insn_config = i_APCI1710_InsnConfigDigitalIO;
+ s->insn_read = i_APCI1710_InsnReadDigitalIOChlValue;
+ s->insn_bits = i_APCI1710_InsnBitsDigitalIOPortOnOff;
+ s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff;
+
+ // Allocate and Initialise Chrono Subdevice Structures
+ s = dev->subdevices + 2;
+
+ s->type = COMEDI_SUBD_CHRONO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 4;
+ s->maxdata = 0;
+ s->len_chanlist = 4;
+ s->range_table = &range_digital;
+ s->insn_write = i_APCI1710_InsnWriteEnableDisableChrono;
+ s->insn_read = i_APCI1710_InsnReadChrono;
+ s->insn_config = i_APCI1710_InsnConfigInitChrono;
+ s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO;
+
+ // Allocate and Initialise PWM Subdevice Structures
+ s = dev->subdevices + 3;
+ s->type = COMEDI_SUBD_PWM;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 3;
+ s->maxdata = 1;
+ s->len_chanlist = 3;
+ s->range_table = &range_digital;
+ s->io_bits = 0; //all bits input
+ s->insn_config = i_APCI1710_InsnConfigPWM;
+ s->insn_read = i_APCI1710_InsnReadGetPWMStatus;
+ s->insn_write = i_APCI1710_InsnWritePWM;
+ s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt;
+
+ // Allocate and Initialise TTLIO Subdevice Structures
+ s = dev->subdevices + 4;
+ s->type = COMEDI_SUBD_TTLIO;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->len_chanlist = 8;
+ s->range_table = &range_apci1710_ttl; // to pass arguments in range
+ s->insn_config = i_APCI1710_InsnConfigInitTTLIO;
+ s->insn_bits = i_APCI1710_InsnBitsReadTTLIO;
+ s->insn_write = i_APCI1710_InsnWriteSetTTLIOChlOnOff;
+ s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue;
+
+ // Allocate and Initialise TOR Subdevice Structures
+ s = dev->subdevices + 5;
+ s->type = COMEDI_SUBD_TOR;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->len_chanlist = 8;
+ s->range_table = &range_digital;
+ s->io_bits = 0; //all bits input
+ s->insn_config = i_APCI1710_InsnConfigInitTorCounter;
+ s->insn_read = i_APCI1710_InsnReadGetTorCounterInitialisation;
+ s->insn_write = i_APCI1710_InsnWriteEnableDisableTorCounter;
+ s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue;
+
+ // Allocate and Initialise SSI Subdevice Structures
+ s = dev->subdevices + 6;
+ s->type = COMEDI_SUBD_SSI;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->len_chanlist = 4;
+ s->range_table = &range_apci1710_ssi;
+ s->insn_config = i_APCI1710_InsnConfigInitSSI;
+ s->insn_read = i_APCI1710_InsnReadSSIValue;
+ s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO;
+
+ // Allocate and Initialise PULSEENCODER Subdevice Structures
+ s = dev->subdevices + 7;
+ s->type = COMEDI_SUBD_PULSEENCODER;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->len_chanlist = 4;
+ s->range_table = &range_digital;
+ s->insn_config = i_APCI1710_InsnConfigInitPulseEncoder;
+ s->insn_write = i_APCI1710_InsnWriteEnableDisablePulseEncoder;
+ s->insn_bits = i_APCI1710_InsnBitsReadWritePulseEncoder;
+ s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder;
+
+ // Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures
+ s = dev->subdevices + 8;
+ s->type = COMEDI_SUBD_INCREMENTALCOUNTER;
+ s->subdev_flags =
+ SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 500;
+ s->maxdata = 1;
+ s->len_chanlist = 500;
+ s->range_table = &range_apci1710_inccpt;
+ s->insn_config = i_APCI1710_InsnConfigINCCPT;
+ s->insn_write = i_APCI1710_InsnWriteINCCPT;
+ s->insn_read = i_APCI1710_InsnReadINCCPT;
+ s->insn_bits = i_APCI1710_InsnBitsINCCPT;
+}
+
+int i_APCI1710_Reset(struct comedi_device * dev);
+void v_APCI1710_Interrupt(int irq, void *d);
+//for 1710
+
+int i_APCI1710_Reset(struct comedi_device * dev)
+{
+ int ret;
+ DWORD dw_Dummy;
+
+ /*********************************/
+ /* Read all module configuration */
+ /*********************************/
+ ret = inl(devpriv->s_BoardInfos.ui_Address + 60);
+ devpriv->s_BoardInfos.dw_MolduleConfiguration[0] = ret;
+
+ ret = inl(devpriv->s_BoardInfos.ui_Address + 124);
+ devpriv->s_BoardInfos.dw_MolduleConfiguration[1] = ret;
+
+ ret = inl(devpriv->s_BoardInfos.ui_Address + 188);
+ devpriv->s_BoardInfos.dw_MolduleConfiguration[2] = ret;
+
+ ret = inl(devpriv->s_BoardInfos.ui_Address + 252);
+ devpriv->s_BoardInfos.dw_MolduleConfiguration[3] = ret;
+
+ // outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60);
+ outl(0x83838383, devpriv->s_BoardInfos.ui_Address + 0x60);
+
+ devpriv->s_BoardInfos.b_BoardVersion = 1;
+
+ // Enable the interrupt for the controler
+ dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address + 0x38);
+ outl(dw_Dummy | 0x2000, devpriv->s_BoardInfos.ui_Address + 0x38);
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function's Name : __void__ v_APCI1710_InterruptFunction |
+| (BYTE b_Interrupt, __CPPARGS) |
++----------------------------------------------------------------------------+
+| Task : APCI-1710 interrupt function |
++----------------------------------------------------------------------------+
+| Input Parameters : BYTE b_Interrupt : Interrupt number |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 : OK |
+| -1 : Error |
++----------------------------------------------------------------------------+
+*/
+
+void v_APCI1710_Interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ BYTE b_ModuleCpt = 0;
+ BYTE b_InterruptFlag = 0;
+ BYTE b_PWMCpt = 0;
+ BYTE b_TorCounterCpt = 0;
+ BYTE b_PulseIncoderCpt = 0;
+ UINT ui_16BitValue;
+ ULONG ul_InterruptLatchReg = 0;
+ ULONG ul_LatchRegisterValue = 0;
+ ULONG ul_82X54InterruptStatus;
+ ULONG ul_StatusRegister;
+
+ str_ModuleInfo *ps_ModuleInfo;
+
+ printk("APCI1710 Interrupt\n");
+ for (b_ModuleCpt = 0; b_ModuleCpt < 4; b_ModuleCpt++, ps_ModuleInfo++) {
+
+ /**************************/
+ /* 1199/0225 to 0100/0226 */
+ /**************************/
+ ps_ModuleInfo = &devpriv->s_ModuleInfo[b_ModuleCpt];
+
+ /***********************/
+ /* Test if 82X54 timer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModuleCpt] &
+ 0xFFFF0000UL) == APCI1710_82X54_TIMER) {
+
+ //printk("TIMER Interrupt Occurred\n");
+ ul_82X54InterruptStatus = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (64 * b_ModuleCpt));
+
+ /***************************/
+ /* Test if interrupt occur */
+ /***************************/
+
+ if ((ul_82X54InterruptStatus & ps_ModuleInfo->
+ s_82X54ModuleInfo.
+ b_InterruptMask) != 0) {
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldInterruptMask =
+ (ul_82X54InterruptStatus &
+ ps_ModuleInfo->s_82X54ModuleInfo.
+ b_InterruptMask) << 4;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ b_OldModuleMask = 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.
+ ui_Write].ul_OldCounterLatchValue = 0;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write + 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ } // if ((ul_82X54InterruptStatus & 0x7) != 0)
+ } // 82X54 timer
+
+ /***************************/
+ /* Test if increm. counter */
+ /***************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModuleCpt] &
+ 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) {
+
+ ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
+ ui_Address + (64 * b_ModuleCpt));
+
+ /*********************/
+ /* Test if interrupt */
+ /*********************/
+
+ if ((ul_InterruptLatchReg & 0x22) && (ps_ModuleInfo->
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 & 0x80)) {
+ /************************************/
+ /* Test if strobe latch I interrupt */
+ /************************************/
+
+ if (ul_InterruptLatchReg & 2) {
+ ul_LatchRegisterValue =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 4 +
+ (64 * b_ModuleCpt));
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].ul_OldInterruptMask =
+ 1UL;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue =
+ ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* 0899/0224 to 1199/0225 */
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current,
+ 0);
+
+ }
+
+ /*************************************/
+ /* Test if strobe latch II interrupt */
+ /*************************************/
+
+ if (ul_InterruptLatchReg & 0x20) {
+
+ ul_LatchRegisterValue =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 8 +
+ (64 * b_ModuleCpt));
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].ul_OldInterruptMask =
+ 2UL;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue =
+ ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* 0899/0224 to 1199/0225 */
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current,
+ 0);
+
+ }
+ }
+
+ ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 24 + (64 * b_ModuleCpt));
+
+ /***************************/
+ /* Test if index interrupt */
+ /***************************/
+
+ if (ul_InterruptLatchReg & 0x8) {
+ ps_ModuleInfo->
+ s_SiemensCounterInfo.
+ s_InitFlag.b_IndexInterruptOccur = 1;
+
+ if (ps_ModuleInfo->
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister2 &
+ APCI1710_INDEX_AUTO_MODE) {
+
+ outl(ps_ModuleInfo->
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ dw_ModeRegister1_2_3_4,
+ devpriv->s_BoardInfos.
+ ui_Address + 20 +
+ (64 * b_ModuleCpt));
+ }
+
+ /*****************************/
+ /* Test if interrupt enabled */
+ /*****************************/
+
+ if ((ps_ModuleInfo->
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 &
+ APCI1710_ENABLE_INDEX_INT) ==
+ APCI1710_ENABLE_INDEX_INT) {
+ devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].ul_OldInterruptMask =
+ 4UL;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue =
+ ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* 0899/0224 to 1199/0225 */
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current,
+ 0);
+
+ }
+ }
+
+ /*****************************/
+ /* Test if compare interrupt */
+ /*****************************/
+
+ if (ul_InterruptLatchReg & 0x10) {
+ /*****************************/
+ /* Test if interrupt enabled */
+ /*****************************/
+
+ if ((ps_ModuleInfo->
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister3 &
+ APCI1710_ENABLE_COMPARE_INT) ==
+ APCI1710_ENABLE_COMPARE_INT) {
+ devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].ul_OldInterruptMask =
+ 8UL;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue =
+ ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* 0899/0224 to 1199/0225 */
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current,
+ 0);
+
+ }
+ }
+
+ /*******************************************/
+ /* Test if frequency measurement interrupt */
+ /*******************************************/
+
+ if (ul_InterruptLatchReg & 0x20) {
+ /*******************/
+ /* Read the status */
+ /*******************/
+
+ ul_StatusRegister = inl(devpriv->s_BoardInfos.
+ ui_Address + 32 + (64 * b_ModuleCpt));
+
+ /******************/
+ /* Read the value */
+ /******************/
+
+ ul_LatchRegisterValue =
+ inl(devpriv->s_BoardInfos.ui_Address +
+ 28 + (64 * b_ModuleCpt));
+
+ switch ((ul_StatusRegister >> 1) & 3) {
+ case 0:
+ /*************************/
+ /* Test the counter mode */
+ /*************************/
+
+ if ((devpriv->s_ModuleInfo[b_ModuleCpt].
+ s_SiemensCounterInfo.
+ s_ModeRegister.
+ s_ByteModeRegister.
+ b_ModeRegister1 &
+ APCI1710_16BIT_COUNTER)
+ == APCI1710_16BIT_COUNTER) {
+ /****************************************/
+ /* Test if 16-bit counter 1 pulse occur */
+ /****************************************/
+
+ if ((ul_LatchRegisterValue &
+ 0xFFFFU) != 0) {
+ ui_16BitValue =
+ (UINT)
+ ul_LatchRegisterValue
+ & 0xFFFFU;
+ ul_LatchRegisterValue =
+ (ul_LatchRegisterValue
+ & 0xFFFF0000UL)
+ | (0xFFFFU -
+ ui_16BitValue);
+ }
+
+ /****************************************/
+ /* Test if 16-bit counter 2 pulse occur */
+ /****************************************/
+
+ if ((ul_LatchRegisterValue &
+ 0xFFFF0000UL) !=
+ 0) {
+ ui_16BitValue =
+ (UINT) (
+ (ul_LatchRegisterValue
+ >> 16) &
+ 0xFFFFU);
+ ul_LatchRegisterValue =
+ (ul_LatchRegisterValue
+ & 0xFFFFUL) |
+ ((0xFFFFU -
+ ui_16BitValue)
+ << 16);
+ }
+ } else {
+ if (ul_LatchRegisterValue != 0) {
+ ul_LatchRegisterValue =
+ 0xFFFFFFFFUL -
+ ul_LatchRegisterValue;
+ }
+ }
+ break;
+
+ case 1:
+ /****************************************/
+ /* Test if 16-bit counter 2 pulse occur */
+ /****************************************/
+
+ if ((ul_LatchRegisterValue &
+ 0xFFFF0000UL) != 0) {
+ ui_16BitValue =
+ (UINT) (
+ (ul_LatchRegisterValue
+ >> 16) &
+ 0xFFFFU);
+ ul_LatchRegisterValue =
+ (ul_LatchRegisterValue &
+ 0xFFFFUL) | ((0xFFFFU -
+ ui_16BitValue)
+ << 16);
+ }
+ break;
+
+ case 2:
+ /****************************************/
+ /* Test if 16-bit counter 1 pulse occur */
+ /****************************************/
+
+ if ((ul_LatchRegisterValue & 0xFFFFU) !=
+ 0) {
+ ui_16BitValue =
+ (UINT)
+ ul_LatchRegisterValue &
+ 0xFFFFU;
+ ul_LatchRegisterValue =
+ (ul_LatchRegisterValue &
+ 0xFFFF0000UL) | (0xFFFFU
+ - ui_16BitValue);
+ }
+ break;
+ }
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldInterruptMask = 0x10000UL;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ b_OldModuleMask = 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters[devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue =
+ ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* 0899/0224 to 1199/0225 */
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write + 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ }
+ } // Incremental counter
+
+ /***************/
+ /* Test if CDA */
+ /***************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModuleCpt] &
+ 0xFFFF0000UL) == APCI1710_CDA) {
+ /******************************************/
+ /* Test if CDA enable and functionality 0 */
+ /******************************************/
+
+ if ((devpriv->s_ModuleInfo[b_ModuleCpt].
+ s_CDAModuleInfo.
+ b_CDAEnable == APCI1710_ENABLE)
+ && (devpriv->s_ModuleInfo[b_ModuleCpt].
+ s_CDAModuleInfo.b_FctSelection == 0)) {
+ /****************************/
+ /* Get the interrupt status */
+ /****************************/
+
+ ul_StatusRegister = inl(devpriv->s_BoardInfos.
+ ui_Address + 16 + (64 * b_ModuleCpt));
+ /***************************/
+ /* Test if interrupt occur */
+ /***************************/
+
+ if (ul_StatusRegister & 1) {
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].ul_OldInterruptMask =
+ 0x80000UL;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue = 0;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current,
+ 0);
+
+ } // if (ul_StatusRegister & 1)
+
+ }
+ } // CDA
+
+ /***********************/
+ /* Test if PWM counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModuleCpt] &
+ 0xFFFF0000UL) == APCI1710_PWM) {
+ for (b_PWMCpt = 0; b_PWMCpt < 2; b_PWMCpt++) {
+ /*************************************/
+ /* Test if PWM interrupt initialised */
+ /*************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModuleCpt].
+ s_PWMModuleInfo.
+ s_PWMInfo[b_PWMCpt].
+ b_InterruptEnable == APCI1710_ENABLE) {
+ /*****************************/
+ /* Read the interrupt status */
+ /*****************************/
+
+ ul_StatusRegister =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 16 +
+ (20 * b_PWMCpt) +
+ (64 * b_ModuleCpt));
+
+ /***************************/
+ /* Test if interrupt occur */
+ /***************************/
+
+ if (ul_StatusRegister & 0x1) {
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldInterruptMask =
+ 0x4000UL << b_PWMCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) %
+ APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO,
+ devpriv->tsk_Current,
+ 0);
+
+ } // if (ul_StatusRegister & 0x1)
+ } // if (APCI1710_ENABLE)
+ } // for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++)
+ } // PWM counter
+
+ /***********************/
+ /* Test if tor counter */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModuleCpt] &
+ 0xFFFF0000UL) == APCI1710_TOR_COUNTER) {
+ for (b_TorCounterCpt = 0; b_TorCounterCpt < 2;
+ b_TorCounterCpt++) {
+ /*************************************/
+ /* Test if tor interrupt initialised */
+ /*************************************/
+
+ if (devpriv->
+ s_ModuleInfo[b_ModuleCpt].
+ s_TorCounterModuleInfo.
+ s_TorCounterInfo[b_TorCounterCpt].
+ b_InterruptEnable == APCI1710_ENABLE) {
+ /*****************************/
+ /* Read the interrupt status */
+ /*****************************/
+
+ ul_StatusRegister =
+ inl(devpriv->s_BoardInfos.
+ ui_Address + 12 +
+ (16 * b_TorCounterCpt) +
+ (64 * b_ModuleCpt));
+
+ /***************************/
+ /* Test if interrupt occur */
+ /***************************/
+
+ if (ul_StatusRegister & 0x1) {
+ /******************************/
+ /* Read the tor counter value */
+ /******************************/
+
+ ul_LatchRegisterValue =
+ inl(devpriv->
+ s_BoardInfos.
+ ui_Address + 0 +
+ (16 * b_TorCounterCpt) +
+ (64 * b_ModuleCpt));
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldInterruptMask =
+ 0x1000UL <<
+ b_TorCounterCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue
+ = ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) %
+ APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO,
+ devpriv->tsk_Current,
+ 0);
+ } // if (ul_StatusRegister & 0x1)
+ } // if (APCI1710_ENABLE)
+ } // for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++)
+ } // Tor counter
+
+ /***********************/
+ /* Test if chronometer */
+ /***********************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModuleCpt] &
+ 0xFFFF0000UL) == APCI1710_CHRONOMETER) {
+
+ //printk("APCI1710 Chrono Interrupt\n");
+ /*****************************/
+ /* Read the interrupt status */
+ /*****************************/
+
+ ul_InterruptLatchReg = inl(devpriv->s_BoardInfos.
+ ui_Address + 12 + (64 * b_ModuleCpt));
+
+ /***************************/
+ /* Test if interrupt occur */
+ /***************************/
+
+ if ((ul_InterruptLatchReg & 0x8) == 0x8) {
+ /****************************/
+ /* Clear the interrupt flag */
+ /****************************/
+
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 32 + (64 * b_ModuleCpt));
+
+ /***************************/
+ /* Test if continuous mode */
+ /***************************/
+
+ if (ps_ModuleInfo->
+ s_ChronoModuleInfo.
+ b_CycleMode == APCI1710_ENABLE) {
+ /********************/
+ /* Clear the status */
+ /********************/
+
+ outl(0, devpriv->s_BoardInfos.
+ ui_Address + 36 +
+ (64 * b_ModuleCpt));
+ }
+
+ /*************************/
+ /* Read the timing value */
+ /*************************/
+
+ ul_LatchRegisterValue =
+ inl(devpriv->s_BoardInfos.ui_Address +
+ 4 + (64 * b_ModuleCpt));
+
+ /*****************************/
+ /* Test if interrupt enabled */
+ /*****************************/
+
+ if (ps_ModuleInfo->
+ s_ChronoModuleInfo.b_InterruptMask) {
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].ul_OldInterruptMask =
+ 0x80;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue =
+ ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) % APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current,
+ 0);
+
+ }
+ }
+ } // Chronometer
+
+ /*************************/
+ /* Test if pulse encoder */
+ /*************************/
+
+ if ((devpriv->s_BoardInfos.
+ dw_MolduleConfiguration[b_ModuleCpt] &
+ 0xFFFF0000UL) == APCI1710_PULSE_ENCODER) {
+ /****************************/
+ /* Read the status register */
+ /****************************/
+
+ ul_StatusRegister = inl(devpriv->s_BoardInfos.
+ ui_Address + 20 + (64 * b_ModuleCpt));
+
+ if (ul_StatusRegister & 0xF) {
+ for (b_PulseIncoderCpt = 0;
+ b_PulseIncoderCpt < 4;
+ b_PulseIncoderCpt++) {
+ /*************************************/
+ /* Test if pulse encoder initialised */
+ /*************************************/
+
+ if ((ps_ModuleInfo->
+ s_PulseEncoderModuleInfo.
+ s_PulseEncoderInfo
+ [b_PulseIncoderCpt].
+ b_PulseEncoderInit == 1)
+ && (((ps_ModuleInfo->s_PulseEncoderModuleInfo.dw_SetRegister >> b_PulseIncoderCpt) & 1) == 1) && (((ul_StatusRegister >> (b_PulseIncoderCpt)) & 1) == 1)) {
+ devpriv->s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldInterruptMask =
+ 0x100UL <<
+ b_PulseIncoderCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ b_OldModuleMask =
+ 1 << b_ModuleCpt;
+
+ devpriv->
+ s_InterruptParameters.
+ s_FIFOInterruptParameters
+ [devpriv->
+ s_InterruptParameters.
+ ui_Write].
+ ul_OldCounterLatchValue
+ = ul_LatchRegisterValue;
+
+ devpriv->
+ s_InterruptParameters.
+ ul_InterruptOccur++;
+
+ /****************************/
+ /* 0899/0224 to 1199/0225 */
+ /****************************/
+ /* Increment the write FIFO */
+ /****************************/
+
+ devpriv->
+ s_InterruptParameters.
+ ui_Write = (devpriv->
+ s_InterruptParameters.
+ ui_Write +
+ 1) %
+ APCI1710_SAVE_INTERRUPT;
+
+ b_InterruptFlag = 1;
+
+ /**********************/
+ /* Call user function */
+ /**********************/
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO,
+ devpriv->tsk_Current,
+ 0);
+
+ }
+ }
+ }
+ } //pulse encoder
+
+ }
+ return;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
new file mode 100644
index 000000000000..998cbba8afeb
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
+#define COMEDI_SUBD_PWM 12 /* Pulse width Measurement */
+#define COMEDI_SUBD_SSI 13 /* Synchronous serial interface */
+#define COMEDI_SUBD_TOR 14 /* Tor counter */
+#define COMEDI_SUBD_CHRONO 15 /* Chrono meter */
+#define COMEDI_SUBD_PULSEENCODER 16 /* Pulse Encoder INP CPT */
+#define COMEDI_SUBD_INCREMENTALCOUNTER 17 /* Incremental Counter */
+
+#define APCI1710_BOARD_NAME "apci1710"
+#define APCI1710_BOARD_VENDOR_ID 0x10E8
+#define APCI1710_BOARD_DEVICE_ID 0x818F
+#define APCI1710_ADDRESS_RANGE 256
+#define APCI1710_CONFIG_ADDRESS_RANGE 8
+#define APCI1710_INCREMENTAL_COUNTER 0x53430000UL
+#define APCI1710_SSI_COUNTER 0x53490000UL
+#define APCI1710_TTL_IO 0x544C0000UL
+#define APCI1710_DIGITAL_IO 0x44490000UL
+#define APCI1710_82X54_TIMER 0x49430000UL
+#define APCI1710_CHRONOMETER 0x43480000UL
+#define APCI1710_PULSE_ENCODER 0x495A0000UL
+#define APCI1710_TOR_COUNTER 0x544F0000UL
+#define APCI1710_PWM 0x50570000UL
+#define APCI1710_ETM 0x45540000UL
+#define APCI1710_CDA 0x43440000UL
+#define APCI1710_DISABLE 0
+#define APCI1710_ENABLE 1
+#define APCI1710_SYNCHRONOUS_MODE 1
+#define APCI1710_ASYNCHRONOUS_MODE 0
+
+//MODULE INFO STRUCTURE
+
+static const struct comedi_lrange range_apci1710_ttl = { 4, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1)
+ }
+};
+
+static const struct comedi_lrange range_apci1710_ssi = { 4, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1)
+ }
+};
+
+static const struct comedi_lrange range_apci1710_inccpt = { 4, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1)
+ }
+};
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
new file mode 100644
index 000000000000..e4527926c2df
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
@@ -0,0 +1,600 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-035 | Compiler : GCC |
+ | Module name : hwdrv_apci035.c | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-035 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci035.h"
+INT i_WatchdogNbr = 0;
+INT i_Temp = 0;
+INT i_Flag = 1;
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI035_ConfigTimerWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Configures The Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 0 Configure As Timer |
+| 1 Configure As Watchdog |
+ data[1] : Watchdog number
+| data[2] : Time base Unit |
+| data[3] : Reload Value |
+ data[4] : External Trigger |
+ 1:Enable
+ 0:Disable
+ data[5] :External Trigger Level
+ 00 Trigger Disabled
+ 01 Trigger Enabled (Low level)
+ 10 Trigger Enabled (High Level)
+ 11 Trigger Enabled (High/Low level)
+ data[6] : External Gate |
+ 1:Enable
+ 0:Disable
+ data[7] : External Gate level
+ 00 Gate Disabled
+ 01 Gate Enabled (Low level)
+ 10 Gate Enabled (High Level)
+ data[8] :Warning Relay
+ 1: ENABLE
+ 0: DISABLE
+ data[9] :Warning Delay available
+ data[10] :Warning Relay Time unit
+ data[11] :Warning Relay Time Reload value
+ data[12] :Reset Relay
+ 1 : ENABLE
+ 0 : DISABLE
+ data[13] :Interrupt
+ 1 : ENABLE
+ 0 : DISABLE
+
+|
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Status = 0;
+ UINT ui_Command = 0;
+ UINT ui_Mode = 0;
+ i_Temp = 0;
+ devpriv->tsk_Current = current;
+ devpriv->b_TimerSelectMode = data[0];
+ i_WatchdogNbr = data[1];
+ if (data[0] == 0) {
+ ui_Mode = 2;
+ } else {
+ ui_Mode = 0;
+ }
+//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
+ ui_Command = 0;
+//ui_Command = ui_Command & 0xFFFFF9FEUL;
+ outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ ui_Command = 0;
+ ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/************************/
+/* Set the reload value */
+/************************/
+ outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4);
+/*********************/
+/* Set the time unit */
+/*********************/
+ outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8);
+ if (data[0] == ADDIDATA_TIMER) {
+
+ /******************************/
+ /* Set the mode : */
+ /* - Disable the hardware */
+ /* - Disable the counter mode */
+ /* - Disable the warning */
+ /* - Disable the reset */
+ /* - Enable the timer mode */
+ /* - Set the timer mode */
+ /******************************/
+
+ ui_Command =
+ (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL;
+
+ } //if (data[0] == ADDIDATA_TIMER)
+ else {
+ if (data[0] == ADDIDATA_WATCHDOG) {
+
+ /******************************/
+ /* Set the mode : */
+ /* - Disable the hardware */
+ /* - Disable the counter mode */
+ /* - Disable the warning */
+ /* - Disable the reset */
+ /* - Disable the timer mode */
+ /******************************/
+
+ ui_Command = ui_Command & 0xFFF819E2UL;
+
+ } else {
+ printk("\n The parameter for Timer/watchdog selection is in error\n");
+ return -EINVAL;
+ }
+ }
+ outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ ui_Command = 0;
+ ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/********************************/
+/* Disable the hardware trigger */
+/********************************/
+ ui_Command = ui_Command & 0xFFFFF89FUL;
+ if (data[4] == ADDIDATA_ENABLE) {
+ /**********************************/
+ /* Set the hardware trigger level */
+ /**********************************/
+ ui_Command = ui_Command | (data[5] << 5);
+ }
+ outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ ui_Command = 0;
+ ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/*****************************/
+/* Disable the hardware gate */
+/*****************************/
+ ui_Command = ui_Command & 0xFFFFF87FUL;
+ if (data[6] == ADDIDATA_ENABLE) {
+/*******************************/
+/* Set the hardware gate level */
+/*******************************/
+ ui_Command = ui_Command | (data[7] << 7);
+ }
+ outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ ui_Command = 0;
+ ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/*******************************/
+/* Disable the hardware output */
+/*******************************/
+ ui_Command = ui_Command & 0xFFFFF9FBUL;
+/*********************************/
+/* Set the hardware output level */
+/*********************************/
+ ui_Command = ui_Command | (data[8] << 2);
+ outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ if (data[9] == ADDIDATA_ENABLE) {
+ /************************/
+ /* Set the reload value */
+ /************************/
+ outl(data[11],
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24);
+ /**********************/
+ /* Set the time unite */
+ /**********************/
+ outl(data[10],
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28);
+ }
+
+ ui_Command = 0;
+ ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ /*******************************/
+ /* Disable the hardware output */
+ /*******************************/
+ ui_Command = ui_Command & 0xFFFFF9F7UL;
+ /*********************************/
+ /* Set the hardware output level */
+ /*********************************/
+ ui_Command = ui_Command | (data[12] << 3);
+ outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ /*************************************/
+ /** Enable the watchdog interrupt **/
+ /*************************************/
+ ui_Command = 0;
+ ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+/*******************************/
+/* Set the interrupt selection */
+/*******************************/
+ ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
+
+ ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1);
+ outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI035_StartStopWriteTimerWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Start / Stop The Selected Timer , or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 0 - Stop Selected Timer/Watchdog |
+| 1 - Start Selected Timer/Watchdog |
+| 2 - Trigger Selected Timer/Watchdog |
+| 3 - Stop All Timer/Watchdog |
+| 4 - Start All Timer/Watchdog |
+| 5 - Trigger All Timer/Watchdog |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Command = 0;
+ INT i_Count = 0;
+ if (data[0] == 1) {
+ ui_Command =
+ inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ /**********************/
+ /* Start the hardware */
+ /**********************/
+ ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL;
+ outl(ui_Command,
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ } // if (data[0]==1)
+ if (data[0] == 2) {
+ ui_Command =
+ inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ /***************************/
+ /* Set the trigger command */
+ /***************************/
+ ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL;
+ outl(ui_Command,
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ }
+
+ if (data[0] == 0) //Stop The Watchdog
+ {
+ //Stop The Watchdog
+ ui_Command = 0;
+ //ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12);
+ //ui_Command = ui_Command & 0xFFFFF9FEUL;
+ outl(ui_Command,
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
+ } // if (data[1]==0)
+ if (data[0] == 3) //stop all Watchdogs
+ {
+ ui_Command = 0;
+ for (i_Count = 1; i_Count <= 4; i_Count++) {
+ if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ ui_Command = 0x2UL;
+ } else {
+ ui_Command = 0x10UL;
+ }
+ i_WatchdogNbr = i_Count;
+ outl(ui_Command,
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
+ 0);
+ }
+
+ }
+ if (data[0] == 4) //start all Watchdogs
+ {
+ ui_Command = 0;
+ for (i_Count = 1; i_Count <= 4; i_Count++) {
+ if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ ui_Command = 0x1UL;
+ } else {
+ ui_Command = 0x8UL;
+ }
+ i_WatchdogNbr = i_Count;
+ outl(ui_Command,
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
+ 0);
+ }
+ }
+ if (data[0] == 5) //trigger all Watchdogs
+ {
+ ui_Command = 0;
+ for (i_Count = 1; i_Count <= 4; i_Count++) {
+ if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ ui_Command = 0x4UL;
+ } else {
+ ui_Command = 0x20UL;
+ }
+
+ i_WatchdogNbr = i_Count;
+ outl(ui_Command,
+ devpriv->iobase + ((i_WatchdogNbr - 1) * 32) +
+ 0);
+ }
+ i_Temp = 1;
+ }
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI035_ReadTimerWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read The Selected Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : software trigger status
+ data[1] : hardware trigger status
+| data[2] : Software clear status
+ data[3] : Overflow status
+ data[4] : Timer actual value
+
+
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Status = 0; // Status register
+ i_WatchdogNbr = insn->unused[0];
+ /******************/
+ /* Get the status */
+ /******************/
+ ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16);
+ /***********************************/
+ /* Get the software trigger status */
+ /***********************************/
+ data[0] = ((ui_Status >> 1) & 1);
+ /***********************************/
+ /* Get the hardware trigger status */
+ /***********************************/
+ data[1] = ((ui_Status >> 2) & 1);
+ /*********************************/
+ /* Get the software clear status */
+ /*********************************/
+ data[2] = ((ui_Status >> 3) & 1);
+ /***************************/
+ /* Get the overflow status */
+ /***************************/
+ data[3] = ((ui_Status >> 0) & 1);
+ if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);
+
+ } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI035_ConfigAnalogInput |
+| (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] : Warning delay value
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ devpriv->tsk_Current = current;
+ outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
+ outl(0, devpriv->iobase + 128 + 0);
+/********************************/
+/* Initialise the warning value */
+/********************************/
+ outl(0x300 | 0, devpriv->iobase + 128 + 0x4);
+ outl((data[0] << 8), devpriv->iobase + 128 + 0);
+ outl(0x200000UL, devpriv->iobase + 128 + 12);
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI035_ReadAnalogInput |
+| (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 |
+| |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_CommandRegister = 0;
+/******************/
+/* Set the start */
+/******************/
+ ui_CommandRegister = 0x80000;
+ /******************************/
+ /* Write the command register */
+ /******************************/
+ outl(ui_CommandRegister, devpriv->iobase + 128 + 8);
+
+/***************************************/
+/* Read the digital value of the input */
+/***************************************/
+ data[0] = inl(devpriv->iobase + 128 + 28);
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI035_Reset(struct comedi_device *dev) |
+| |
++----------------------------------------------------------------------------+
+| Task :Resets the registers of the card |
++----------------------------------------------------------------------------+
+| Input Parameters : |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI035_Reset(struct comedi_device * dev)
+{
+ INT i_Count = 0;
+ for (i_Count = 1; i_Count <= 4; i_Count++) {
+ i_WatchdogNbr = i_Count;
+ outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); //stop all timers
+ }
+ outl(0x0, devpriv->iobase + 128 + 12); //Disable the warning delay
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : static void v_APCI035_Interrupt |
+| (int irq , void *d) |
++----------------------------------------------------------------------------+
+| Task : Interrupt processing Routine |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq : irq number |
+| void *d : void pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+static void v_APCI035_Interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ UINT ui_StatusRegister1 = 0;
+ UINT ui_StatusRegister2 = 0;
+ UINT ui_ReadCommand = 0;
+ UINT ui_ChannelNumber = 0;
+ UINT ui_DigitalTemperature = 0;
+ if (i_Temp == 1) {
+ i_WatchdogNbr = i_Flag;
+ i_Flag = i_Flag + 1;
+ }
+ /**************************************/
+ /* Read the interrupt status register of temperature Warning */
+ /**************************************/
+ ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16);
+ /**************************************/
+ /* Read the interrupt status register for Watchdog/timer */
+ /**************************************/
+
+ ui_StatusRegister2 =
+ inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20);
+
+ if ((((ui_StatusRegister1) & 0x8) == 0x8)) //Test if warning relay interrupt
+ {
+ /**********************************/
+ /* Disable the temperature warning */
+ /**********************************/
+ ui_ReadCommand = inl(devpriv->iobase + 128 + 12);
+ ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL;
+ outl(ui_ReadCommand, devpriv->iobase + 128 + 12);
+ /***************************/
+ /* Read the channel number */
+ /***************************/
+ ui_ChannelNumber = inl(devpriv->iobase + 128 + 60);
+ /**************************************/
+ /* Read the digital temperature value */
+ /**************************************/
+ ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60);
+ send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
+ } //if (((ui_StatusRegister1 & 0x8) == 0x8))
+
+ else {
+ if ((ui_StatusRegister2 & 0x1) == 0x1) {
+ send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
+ }
+ } //else if (((ui_StatusRegister1 & 0x8) == 0x8))
+
+ return;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
new file mode 100644
index 000000000000..80d7c0d39aab
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+/* Card Specific information */
+#define APCI035_BOARD_VENDOR_ID 0x15B8
+#define APCI035_ADDRESS_RANGE 255
+
+INT i_TW_Number;
+struct {
+ INT i_Gain;
+ INT i_Polarity;
+ INT i_OffsetRange;
+ INT i_Coupling;
+ INT i_SingleDiff;
+ INT i_AutoCalibration;
+ UINT ui_ReloadValue;
+ UINT ui_TimeUnitReloadVal;
+ INT i_Interrupt;
+ INT i_ModuleSelection;
+} Config_Parameters_Main;
+
+/* ANALOG INPUT RANGE */
+struct comedi_lrange range_apci035_ai = { 8, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2),
+ UNI_RANGE(1)
+ }
+};
+
+/* Timer / Watchdog Related Defines */
+#define APCI035_TCW_SYNC_ENABLEDISABLE 0
+#define APCI035_TCW_RELOAD_VALUE 4
+#define APCI035_TCW_TIMEBASE 8
+#define APCI035_TCW_PROG 12
+#define APCI035_TCW_TRIG_STATUS 16
+#define APCI035_TCW_IRQ 20
+#define APCI035_TCW_WARN_TIMEVAL 24
+#define APCI035_TCW_WARN_TIMEBASE 28
+
+#define ADDIDATA_TIMER 0
+/* #define ADDIDATA_WATCHDOG 1 */
+
+#define APCI035_TW1 0
+#define APCI035_TW2 32
+#define APCI035_TW3 64
+#define APCI035_TW4 96
+
+#define APCI035_AI_OFFSET 0
+#define APCI035_TEMP 128
+#define APCI035_ALR_SEQ 4
+#define APCI035_START_STOP_INDEX 8
+#define APCI035_ALR_START_STOP 12
+#define APCI035_ALR_IRQ 16
+#define APCI035_EOS 20
+#define APCI035_CHAN_NO 24
+#define APCI035_CHAN_VAL 28
+#define APCI035_CONV_TIME_TIME_BASE 36
+#define APCI035_RELOAD_CONV_TIME_VAL 32
+#define APCI035_DELAY_TIME_TIME_BASE 44
+#define APCI035_RELOAD_DELAY_TIME_VAL 40
+#define ENABLE_EXT_TRIG 1
+#define ENABLE_EXT_GATE 2
+#define ENABLE_EXT_TRIG_GATE 3
+
+#define ANALOG_INPUT 0
+#define TEMPERATURE 1
+#define RESISTANCE 2
+
+#define ADDIDATA_GREATER_THAN_TEST 0
+#define ADDIDATA_LESS_THAN_TEST 1
+
+#define APCI035_MAXVOLT 2.5
+
+#define ADDIDATA_UNIPOLAR 1
+#define ADDIDATA_BIPOLAR 2
+
+/* ADDIDATA Enable Disable */
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+
+/* Hardware Layer functions for Apci035 */
+
+/* TIMER */
+/* timer value is passed as u seconds */
+INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/* Temperature Related Defines (Analog Input Subdevice) */
+
+INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/* Interrupt */
+static void v_APCI035_Interrupt(int irq, void *d);
+
+/* Reset functions */
+INT i_APCI035_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
new file mode 100644
index 000000000000..32796ceb946e
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
@@ -0,0 +1,285 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-1032 | Compiler : GCC |
+ | Module name : hwdrv_apci1032.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-1032 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci1032.h"
+#include <linux/delay.h>
+//Global variables
+UINT ui_InterruptStatus = 0;
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1032_ConfigDigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Configures the digital input Subdevice |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| unsigned int *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 1 Enable Digital Input Interrupt |
+| 0 Disable Digital Input Interrupt |
+| data[1] : 0 ADDIDATA Interrupt OR LOGIC |
+| : 1 ADDIDATA Interrupt AND LOGIC |
+| data[2] : Interrupt mask for the mode 1 |
+| data[3] : Interrupt mask for the mode 2 |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_TmpValue;
+
+ ULONG ul_Command1 = 0;
+ ULONG ul_Command2 = 0;
+ devpriv->tsk_Current = current;
+
+ /*******************************/
+ /* Set the digital input logic */
+ /*******************************/
+ if (data[0] == ADDIDATA_ENABLE) {
+ ul_Command1 = ul_Command1 | data[2];
+ ul_Command2 = ul_Command2 | data[3];
+ outl(ul_Command1,
+ devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
+ outl(ul_Command2,
+ devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+ if (data[1] == ADDIDATA_OR) {
+ outl(0x4, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ ui_TmpValue =
+ inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ } //if (data[1] == ADDIDATA_OR)
+ else {
+ outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ } //else if(data[1] == ADDIDATA_OR)
+ } // if( data[0] == ADDIDATA_ENABLE)
+ else {
+ ul_Command1 = ul_Command1 & 0xFFFF0000;
+ ul_Command2 = ul_Command2 & 0xFFFF0000;
+ outl(ul_Command1,
+ devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
+ outl(ul_Command2,
+ devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+ outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ } //else if ( data[0] == ADDIDATA_ENABLE)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1032_Read1DigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the digital input |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_Channel : Channel number to read |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_TmpValue = 0;
+ UINT ui_Channel;
+ ui_Channel = CR_CHAN(insn->chanspec);
+ if (ui_Channel >= 0 && ui_Channel <= 31) {
+ ui_TmpValue = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+ // since only 1 channel reqd to bring it to last bit it is rotated
+ // 8 +(chan - 1) times then ANDed with 1 for last bit.
+ *data = (ui_TmpValue >> ui_Channel) & 0x1;
+ } //if(ui_Channel >= 0 && ui_Channel <=31)
+ else {
+ //comedi_error(dev," \n chan spec wrong\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //else if(ui_Channel >= 0 && ui_Channel <=31)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1032_ReadMoreDigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the Requested digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_NoOfChannels : No Of Channels To be Read |
+| UINT *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_PortValue = data[0];
+ UINT ui_Mask = 0;
+ UINT ui_NoOfChannels;
+
+ ui_NoOfChannels = CR_CHAN(insn->chanspec);
+ if (data[1] == 0) {
+ *data = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
+ switch (ui_NoOfChannels) {
+ case 2:
+ ui_Mask = 3;
+ *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+ break;
+ case 4:
+ ui_Mask = 15;
+ *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+ break;
+ case 8:
+ ui_Mask = 255;
+ *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
+ break;
+ case 16:
+ ui_Mask = 65535;
+ *data = (*data >> (16 * ui_PortValue)) & ui_Mask;
+ break;
+ case 31:
+ break;
+ default:
+ //comedi_error(dev," \nchan spec wrong\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ break;
+ } //switch(ui_NoOfChannels)
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ *data = ui_InterruptStatus;
+ } //if(data[1]==1)
+ } //else if(data[1]==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : static void v_APCI1032_Interrupt |
+| (int irq , void *d) |
++----------------------------------------------------------------------------+
+| Task : Interrupt handler for the interruptible digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq : irq number |
+| void *d : void pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+static void v_APCI1032_Interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+
+ UINT ui_Temp;
+ //disable the interrupt
+ ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE,
+ devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
+ ui_InterruptStatus =
+ inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);
+ ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF;
+ send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
+ outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //enable the interrupt
+ return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1032_Reset(struct comedi_device *dev) | |
++----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1032_Reset(struct comedi_device * dev)
+{
+ outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //disable the interrupts
+ inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); //Reset the interrupt status register
+ outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt
+ outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
new file mode 100644
index 000000000000..659ef85088cd
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/********* Definitions for APCI-1032 card *****/
+
+#define APCI1032_BOARD_VENDOR_ID 0x15B8
+#define APCI1032_ADDRESS_RANGE 20
+//DIGITAL INPUT DEFINE
+
+#define APCI1032_DIGITAL_IP 0
+#define APCI1032_DIGITAL_IP_INTERRUPT_MODE1 4
+#define APCI1032_DIGITAL_IP_INTERRUPT_MODE2 8
+#define APCI1032_DIGITAL_IP_IRQ 16
+
+//Digital Input IRQ Function Selection
+#define ADDIDATA_OR 0
+#define ADDIDATA_AND 1
+
+//Digital Input Interrupt Status
+#define APCI1032_DIGITAL_IP_INTERRUPT_STATUS 12
+
+//Digital Input Interrupt Enable Disable.
+#define APCI1032_DIGITAL_IP_INTERRUPT_ENABLE 0x4
+#define APCI1032_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+
+// Hardware Layer functions for Apci1032
+
+//DI
+// for di read
+
+INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// Interrupt functions.....
+
+static void v_APCI1032_Interrupt(int irq, void *d);
+//Reset
+INT i_APCI1032_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
new file mode 100644
index 000000000000..2d6adcff41e3
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
@@ -0,0 +1,3045 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-1500 | Compiler : GCC |
+ | Module name : hwdrv_apci1500.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-1500 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+#include "hwdrv_apci1500.h"
+
+int i_TimerCounter1Init = 0;
+int i_TimerCounter2Init = 0;
+int i_WatchdogCounter3Init = 0;
+int i_Event1Status = 0, i_Event2Status = 0;
+int i_TimerCounterWatchdogInterrupt = 0;
+int i_Logic = 0, i_CounterLogic = 0;
+int i_InterruptMask = 0;
+int i_InputChannel = 0;
+int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
+ 0, i_WatchdogCounter3Enabled = 0;
+
+/*
+ +----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_ConfigDigitalInputEvent |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : An event can be generated for each port. |
+| The first event is related to the first 8 channels |
+| (port 1) and the second to the following 6 channels |
+| (port 2). An interrupt is generated when one or both |
+| events have occurred |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| unsigned int *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] :Number of the input port on |
+| which the event will take place |
+| (1 or 2)
+ data[1] : The event logic for port 1 has |
+| three possibilities |
+| :0 APCI1500_AND :This logic |
+| links |
+| the inputs |
+| with an AND |
+| logic. |
+| 1 APCI1500_OR :This logic |
+| links |
+| the inputs |
+| with a |
+| OR logic. |
+| 2 APCI1500_OR_PRIORITY |
+| :This logic |
+| links |
+| the inputs |
+| with a |
+| priority |
+| OR logic. |
+| Input 1 |
+| has the |
+| highest |
+| priority |
+| level and |
+| input 8 |
+| the smallest|
+| For the second port the user has|
+| 1 possibility: |
+| APCI1500_OR :This logic |
+| links |
+| the inputs |
+| with a |
+| polarity |
+| OR logic |
+| data[2] : These 8-character word for port1|
+| and 6-character word for port 2 |
+| give the mask of the event. |
+| Each place gives the state |
+| of the input channels and can |
+| have one of these six characters|
+| |
+| 0 : This input must be on 0 |
+| 1 : This input must be on 1 |
+| 2 : This input reacts to |
+| a falling edge |
+| 3 : This input reacts to a |
+| rising edge |
+| 4 : This input reacts to both edges |
+|
+| 5 : This input is not |
+| used for event |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
+ int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
+ int i_PatternTransitionCount = 0, i_RegValue;
+ int i;
+
+ /*************************************************/
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Disables the main interrupt on the board */
+ /**********************************************/
+ outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ if (data[0] == 1) {
+ i_MaxChannel = 8;
+ } // if (data[0] == 1)
+ else {
+ if (data[0] == 2) {
+ i_MaxChannel = 6;
+ } // if(data[0]==2)
+ else {
+ printk("\nThe specified port event does not exist\n");
+ return -EINVAL;
+ } //else if(data[0]==2)
+ } //else if (data[0] == 1)
+ switch (data[1]) {
+ case 0:
+ data[1] = APCI1500_AND;
+ break;
+ case 1:
+ data[1] = APCI1500_OR;
+ break;
+ case 2:
+ data[1] = APCI1500_OR_PRIORITY;
+ break;
+ default:
+ printk("\nThe specified interrupt logic does not exist\n");
+ return -EINVAL;
+ } //switch(data[1]);
+
+ i_Logic = data[1];
+ for (i_Count = i_MaxChannel, i = 0; i_Count > 0; i_Count--, i++) {
+ i_EventMask = data[2 + i];
+ switch (i_EventMask) {
+ case 0:
+ i_PatternMask =
+ i_PatternMask | (1 << (i_MaxChannel - i_Count));
+ break;
+ case 1:
+ i_PatternMask =
+ i_PatternMask | (1 << (i_MaxChannel - i_Count));
+ i_PatternPolarity =
+ i_PatternPolarity | (1 << (i_MaxChannel -
+ i_Count));
+ break;
+ case 2:
+ i_PatternMask =
+ i_PatternMask | (1 << (i_MaxChannel - i_Count));
+ i_PatternTransition =
+ i_PatternTransition | (1 << (i_MaxChannel -
+ i_Count));
+ break;
+ case 3:
+ i_PatternMask =
+ i_PatternMask | (1 << (i_MaxChannel - i_Count));
+ i_PatternPolarity =
+ i_PatternPolarity | (1 << (i_MaxChannel -
+ i_Count));
+ i_PatternTransition =
+ i_PatternTransition | (1 << (i_MaxChannel -
+ i_Count));
+ break;
+ case 4:
+ i_PatternTransition =
+ i_PatternTransition | (1 << (i_MaxChannel -
+ i_Count));
+ break;
+ case 5:
+ break;
+ default:
+ printk("\nThe option indicated in the event mask does not exist\n");
+ return -EINVAL;
+ } // switch(i_EventMask)
+ } //for (i_Count = i_MaxChannel; i_Count >0;i_Count --)
+
+ if (data[0] == 1) {
+ /****************************/
+ /* Test the interrupt logic */
+ /****************************/
+
+ if (data[1] == APCI1500_AND ||
+ data[1] == APCI1500_OR ||
+ data[1] == APCI1500_OR_PRIORITY) {
+ /**************************************/
+ /* Tests if a transition was declared */
+ /* for a OR PRIORITY logic */
+ /**************************************/
+
+ if (data[1] == APCI1500_OR_PRIORITY
+ && i_PatternTransition != 0) {
+ /********************************************/
+ /* Transition error on an OR PRIORITY logic */
+ /********************************************/
+ printk("\nTransition error on an OR PRIORITY logic\n");
+ return -EINVAL;
+ } // if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0)
+
+ /*************************************/
+ /* Tests if more than one transition */
+ /* was declared for an AND logic */
+ /*************************************/
+
+ if (data[1] == APCI1500_AND) {
+ for (i_Count = 0; i_Count < 8; i_Count++) {
+ i_PatternTransitionCount =
+ i_PatternTransitionCount +
+ ((i_PatternTransition >>
+ i_Count) & 0x1);
+
+ } //for (i_Count = 0; i_Count < 8; i_Count++)
+
+ if (i_PatternTransitionCount > 1) {
+ /****************************************/
+ /* Transition error on an AND logic */
+ /****************************************/
+ printk("\n Transition error on an AND logic\n");
+ return -EINVAL;
+ } // if (i_PatternTransitionCount > 1)
+ } // if (data[1]== APCI1500_AND)
+
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /******************/
+ /* Disable Port A */
+ /******************/
+ outb(0xF0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Selects the polarity register of port 1 */
+ /**********************************************/
+ outb(APCI1500_RW_PORT_A_PATTERN_POLARITY,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_PatternPolarity,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*********************************************/
+ /* Selects the pattern mask register of */
+ /* port 1 */
+ /*********************************************/
+ outb(APCI1500_RW_PORT_A_PATTERN_MASK,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_PatternMask,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /********************************************/
+ /* Selects the pattern transition register */
+ /* of port 1 */
+ /********************************************/
+ outb(APCI1500_RW_PORT_A_PATTERN_TRANSITION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_PatternTransition,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /******************************************/
+ /* Selects the mode specification mask */
+ /* register of port 1 */
+ /******************************************/
+ outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /******************************************/
+ /* Selects the mode specification mask */
+ /* register of port 1 */
+ /******************************************/
+ outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**********************/
+ /* Port A new mode */
+ /**********************/
+
+ i_RegValue = (i_RegValue & 0xF9) | data[1] | 0x9;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ i_Event1Status = 1;
+
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************/
+ /* Enable Port A */
+ /*****************/
+ outb(0xF4,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ } // if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY)
+ else {
+ printk("\nThe choice for interrupt logic does not exist\n");
+ return -EINVAL;
+ } // else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY)
+ } // if (data[0]== 1)
+
+ /************************************/
+ /* Test if event setting for port 2 */
+ /************************************/
+
+ if (data[0] == 2) {
+ /************************/
+ /* Test the event logic */
+ /************************/
+
+ if (data[1] == APCI1500_OR) {
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /******************/
+ /* Disable Port B */
+ /******************/
+ outb(0x74,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /****************************************/
+ /* Selects the mode specification mask */
+ /* register of port B */
+ /****************************************/
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /******************************************/
+ /* Selects the mode specification mask */
+ /* register of port B */
+ /******************************************/
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = i_RegValue & 0xF9;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**********************************/
+ /* Selects error channels 1 and 2 */
+ /**********************************/
+
+ i_PatternMask = (i_PatternMask | 0xC0);
+ i_PatternPolarity = (i_PatternPolarity | 0xC0);
+ i_PatternTransition = (i_PatternTransition | 0xC0);
+
+ /**********************************************/
+ /* Selects the polarity register of port 2 */
+ /**********************************************/
+ outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_PatternPolarity,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Selects the pattern transition register */
+ /* of port 2 */
+ /**********************************************/
+ outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_PatternTransition,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Selects the pattern Mask register */
+ /* of port 2 */
+ /**********************************************/
+
+ outb(APCI1500_RW_PORT_B_PATTERN_MASK,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_PatternMask,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /******************************************/
+ /* Selects the mode specification mask */
+ /* register of port 2 */
+ /******************************************/
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /******************************************/
+ /* Selects the mode specification mask */
+ /* register of port 2 */
+ /******************************************/
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = (i_RegValue & 0xF9) | 4;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ i_Event2Status = 1;
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************/
+ /* Enable Port B */
+ /*****************/
+
+ outb(0xF4,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } // if (data[1] == APCI1500_OR)
+ else {
+ printk("\nThe choice for interrupt logic does not exist\n");
+ return -EINVAL;
+ } //elseif (data[1] == APCI1500_OR)
+ } //if(data[0]==2)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_StartStopInputEvent |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Allows or disallows a port event |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_Channel : Channel number to read |
+| unsigned int *data : Data Pointer to read status |
+ data[0] :0 Start input event
+ 1 Stop input event
+ data[1] :No of port (1 or 2)
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
+ 0, i_RegValue;
+ switch (data[0]) {
+ case START:
+ /*************************/
+ /* Tests the port number */
+ /*************************/
+
+ if (data[1] == 1 || data[1] == 2) {
+ /***************************/
+ /* Test if port 1 selected */
+ /***************************/
+
+ if (data[1] == 1) {
+ /*****************************/
+ /* Test if event initialised */
+ /*****************************/
+ if (i_Event1Status == 1) {
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************/
+ /* Disable Port A */
+ /******************/
+ outb(0xF0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***************************************************/
+ /* Selects the command and status register of */
+ /* port 1 */
+ /***************************************************/
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************/
+ /* Allows the pattern interrupt */
+ /*************************************/
+ outb(0xC0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************/
+ /* Enable Port A */
+ /*****************/
+ outb(0xF4,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_Event1InterruptStatus = 1;
+ outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Authorizes the main interrupt on the board */
+ /**********************************************/
+ outb(0xD0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ } // if(i_Event1Status==1)
+ else {
+ printk("\nEvent 1 not initialised\n");
+ return -EINVAL;
+ } //else if(i_Event1Status==1)
+ } //if (data[1]==1)
+ if (data[1] == 2) {
+
+ if (i_Event2Status == 1) {
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************/
+ /* Disable Port B */
+ /******************/
+ outb(0x74,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***************************************************/
+ /* Selects the command and status register of */
+ /* port 2 */
+ /***************************************************/
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************/
+ /* Allows the pattern interrupt */
+ /*************************************/
+ outb(0xC0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************/
+ /* Enable Port B */
+ /*****************/
+ outb(0xF4,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Authorizes the main interrupt on the board */
+ /**********************************************/
+ outb(0xD0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_Event2InterruptStatus = 1;
+ } // if(i_Event2Status==1)
+ else {
+ printk("\nEvent 2 not initialised\n");
+ return -EINVAL;
+ } //else if(i_Event2Status==1)
+ } // if(data[1]==2)
+ } // if (data[1] == 1 || data[0] == 2)
+ else {
+ printk("\nThe port parameter is in error\n");
+ return -EINVAL;
+ } //else if (data[1] == 1 || data[0] == 2)
+
+ break;
+
+ case STOP:
+ /*************************/
+ /* Tests the port number */
+ /*************************/
+
+ if (data[1] == 1 || data[1] == 2) {
+ /***************************/
+ /* Test if port 1 selected */
+ /***************************/
+
+ if (data[1] == 1) {
+ /*****************************/
+ /* Test if event initialised */
+ /*****************************/
+ if (i_Event1Status == 1) {
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************/
+ /* Disable Port A */
+ /******************/
+ outb(0xF0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***************************************************/
+ /* Selects the command and status register of */
+ /* port 1 */
+ /***************************************************/
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************/
+ /* Inhibits the pattern interrupt */
+ /*************************************/
+ outb(0xE0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************/
+ /* Enable Port A */
+ /*****************/
+ outb(0xF4,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_Event1InterruptStatus = 0;
+ } // if(i_Event1Status==1)
+ else {
+ printk("\nEvent 1 not initialised\n");
+ return -EINVAL;
+ } //else if(i_Event1Status==1)
+ } //if (data[1]==1)
+ if (data[1] == 2) {
+ /*****************************/
+ /* Test if event initialised */
+ /*****************************/
+ if (i_Event2Status == 1) {
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************/
+ /* Disable Port B */
+ /******************/
+ outb(0x74,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***************************************************/
+ /* Selects the command and status register of */
+ /* port 2 */
+ /***************************************************/
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************/
+ /* Inhibits the pattern interrupt */
+ /*************************************/
+ outb(0xE0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************************/
+ /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */
+ /*****************************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************/
+ /* Enable Port B */
+ /*****************/
+ outb(0xF4,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_Event2InterruptStatus = 0;
+ } // if(i_Event2Status==1)
+ else {
+ printk("\nEvent 2 not initialised\n");
+ return -EINVAL;
+ } //else if(i_Event2Status==1)
+ } //if(data[1]==2)
+
+ } // if (data[1] == 1 || data[1] == 2)
+ else {
+ printk("\nThe port parameter is in error\n");
+ return -EINVAL;
+ } //else if (data[1] == 1 || data[1] == 2)
+ break;
+ default:
+ printk("\nThe option of START/STOP logic does not exist\n");
+ return -EINVAL;
+ } //switch(data[0])
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_Initialisation |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the digital input |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_Channel : Channel number to read |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ int i_DummyRead = 0;
+ /******************/
+ /* Software reset */
+ /******************/
+ i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the master configuration control register */
+ /*****************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the mode specification register of port A */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /* Selects the data path polarity register of port A */
+ outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* High level of port A means 1 */
+ outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /* Selects the data direction register of port A */
+ outb(APCI1500_RW_PORT_A_DATA_DIRECTION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* All bits used as inputs */
+ outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port A */
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port A */
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates the interrupt management of port A: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the handshake specification register of port A */
+ outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes the register */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the mode specification register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the data path polarity register of port B */
+ outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* A high level of port B means 1 */
+ outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the data direction register of port B */
+ outb(APCI1500_RW_PORT_B_DATA_DIRECTION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* All bits used as inputs */
+ outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port B */
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port B */
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates the interrupt management of port B: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the handshake specification register of port B */
+ outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes the register */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the data path polarity register of port C */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* High level of port C means 1 */
+ outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the data direction register of port C */
+ outb(APCI1500_RW_PORT_C_DATA_DIRECTION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* All bits used as inputs except channel 1 */
+ outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the special IO register of port C */
+ outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes it */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************************************************/
+ /* Selects the command and status register of timer 1 */
+ /******************************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of timer 1 */
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates the interrupt management of timer 1 */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************************************************/
+ /* Selects the command and status register of timer 2 */
+ /******************************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of timer 2 */
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates Timer 2 interrupt management: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************************************************/
+ /* Selects the command and status register of timer 3 */
+ /******************************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of Timer 3 */
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates interrupt management of timer 3: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************************/
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes all interrupts */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_ReadMoreDigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the Requested digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_NoOfChannels : No Of Channels To be Read |
+| UINT *data : Data Pointer
+ data[0] : 0 Read a single channel
+ 1 read a port value
+ data[1] : port value
++----------------------------------------------------------------------------+
+| Output Parameters : -- data[0] :The read status value
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_PortValue = data[1];
+ UINT ui_Mask = 0;
+ UINT ui_Channel;
+ UINT ui_TmpValue = 0;
+ ui_Channel = CR_CHAN(insn->chanspec);
+
+ switch (data[0]) {
+ case 0:
+ if (ui_Channel >= 0 && ui_Channel <= 15) {
+ ui_TmpValue =
+ (UINT) inw(devpriv->i_IobaseAddon +
+ APCI1500_DIGITAL_IP);
+ *data = (ui_TmpValue >> ui_Channel) & 0x1;
+ } //if(ui_Channel >= 0 && ui_Channel <=15)
+ else {
+ printk("\nThe channel specification are in error\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //else if(ui_Channel >= 0 && ui_Channel <=15)
+ break;
+ case 1:
+
+ *data = (UINT) inw(devpriv->i_IobaseAddon +
+ APCI1500_DIGITAL_IP);
+ switch (ui_Channel) {
+ case 2:
+ ui_Mask = 3;
+ *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+ break;
+ case 4:
+ ui_Mask = 15;
+ *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+ break;
+ case 8:
+ ui_Mask = 255;
+ *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
+ break;
+ case 15:
+ break;
+
+ default:
+ printk("\nSpecified channel cannot be read \n");
+ return -EINVAL; // "sorry channel spec wrong "
+ break;
+ } //switch(ui_Channel)
+ break;
+ default:
+ printk("\nThe specified functionality does not exist\n");
+ return -EINVAL;
+ } //switch(data[0])
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_ConfigDigitalOutputErrorInterrupt
+ (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn
+ *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : Configures the digital output memory and the digital
+ output error interrupt |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| unsigned int *data : Data Pointer contains |
+| configuration parameters as below |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| data[0] :1:Memory on |
+| 0:Memory off |
+ data[1] :1 Enable the voltage error interrupt
+| :0 Disable the voltage error interrupt |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ devpriv->b_OutputMemoryStatus = data[0];
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_WriteDigitalOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Writes port value To the selected port |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_NoOfChannels : No Of Channels To Write |
+| UINT *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ static UINT ui_Temp = 0;
+ UINT ui_Temp1;
+
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+
+ if (!devpriv->b_OutputMemoryStatus) {
+ ui_Temp = 0;
+
+ } //if(!devpriv->b_OutputMemoryStatus )
+ if (data[3] == 0) {
+ if (data[1] == 0) {
+ data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ outw(data[0],
+ devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] =
+ (data[0] << (2 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 4:
+ data[0] =
+ (data[0] << (4 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 8:
+ data[0] =
+ (data[0] << (8 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 15:
+ data[0] = data[0] | ui_Temp;
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outw(data[0],
+ devpriv->i_IobaseAddon +
+ APCI1500_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==0)
+ else {
+ if (data[3] == 1) {
+ if (data[1] == 0) {
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ (data[0] << ui_NoOfChannel) ^
+ 0xffffffff;
+ data[0] = data[0] & ui_Temp;
+ outw(data[0],
+ devpriv->i_IobaseAddon +
+ APCI1500_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] = ~data[0] & 0x3;
+ ui_Temp1 = 3;
+ ui_Temp1 =
+ ui_Temp1 << 2 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (2 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+
+ case 4:
+ data[0] = ~data[0] & 0xf;
+ ui_Temp1 = 15;
+ ui_Temp1 =
+ ui_Temp1 << 4 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (4 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+
+ case 8:
+ data[0] = ~data[0] & 0xff;
+ ui_Temp1 = 255;
+ ui_Temp1 =
+ ui_Temp1 << 8 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (8 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+
+ case 15:
+ break;
+
+ default:
+ comedi_error(dev,
+ " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outw(data[0],
+ devpriv->i_IobaseAddon +
+ APCI1500_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==1);
+ else {
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } //if else data[3]==1)
+ } //if else data[3]==0)
+ ui_Temp = data[0];
+ return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device
+ *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+| |
++----------------------------------------------------------------------------+
+| Task : Configures The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status data[0] : 2 APCI1500_1_8_KHZ
+| 1 APCI1500_3_6_KHZ |
+| 0 APCI1500_115_KHZ
+ data[1] : 0 Counter1/Timer1
+ 1 Counter2/Timer2
+ 2 Counter3/Watchdog
+ data[2] : 0 Counter
+ 1 Timer/Watchdog
+ data[3] : This parameter has |
+| two meanings. |
+| - If the counter/timer |
+| is used as a counter |
+| the limit value of |
+| the counter is given |
+| |
+| - If the counter/timer |
+| is used as a timer, |
+| the divider factor |
+| for the output is |
+| given.
+ data[4] : 0 APCI1500_CONTINUOUS
+ 1 APCI1500_SINGLE
+ data[5] : 0 Software Trigger
+ 1 Hardware Trigger
+
+ data[6] :0 Software gate
+ 1 Hardware gate
+ data[7] :0 Interrupt Disable
+ 1 Interrupt Enable
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ int i_TimerCounterMode, i_MasterConfiguration;
+
+ devpriv->tsk_Current = current;
+
+//Selection of the input clock
+ if (data[0] == 0 || data[0] == 1 || data[0] == 2) {
+ outw(data[0], devpriv->i_IobaseAddon + APCI1500_CLK_SELECT);
+ } // if(data[0]==0||data[0]==1||data[0]==2)
+ else {
+ if (data[0] != 3) {
+ printk("\nThe option for input clock selection does not exist\n");
+ return -EINVAL;
+ } // if(data[0]!=3)
+ } //elseif(data[0]==0||data[0]==1||data[0]==2)
+ //Select the counter/timer
+ switch (data[1]) {
+ case COUNTER1:
+ //selecting counter or timer
+ switch (data[2]) {
+ case 0:
+ data[2] = APCI1500_COUNTER;
+ break;
+ case 1:
+ data[2] = APCI1500_TIMER;
+ break;
+ default:
+ printk("\nThis choice is not a timer nor a counter\n");
+ return -EINVAL;
+ } // switch(data[2])
+
+ //Selecting single or continuous mode
+ switch (data[4]) {
+ case 0:
+ data[4] = APCI1500_CONTINUOUS;
+ break;
+ case 1:
+ data[4] = APCI1500_SINGLE;
+ break;
+ default:
+ printk("\nThis option for single/continuous mode does not exist\n");
+ return -EINVAL;
+ } // switch(data[4])
+
+ i_TimerCounterMode = data[2] | data[4] | 7;
+ /*************************/
+ /* Test the reload value */
+ /*************************/
+
+ if ((data[3] >= 0) && (data[3] <= 65535)) {
+ if (data[7] == APCI1500_ENABLE
+ || data[7] == APCI1500_DISABLE) {
+
+ /************************************************/
+ /* Selects the mode register of timer/counter 1 */
+ /************************************************/
+ outb(APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************/
+ /* Writes the new mode */
+ /***********************/
+ outb(i_TimerCounterMode,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /****************************************************/
+ /* Selects the constant register of timer/counter 1 */
+ /****************************************************/
+
+ outb(APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*************************/
+ /* Writes the low value */
+ /*************************/
+
+ outb(data[3],
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /****************************************************/
+ /* Selects the constant register of timer/counter 1 */
+ /****************************************************/
+
+ outb(APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**************************/
+ /* Writes the high value */
+ /**************************/
+
+ data[3] = data[3] >> 8;
+ outb(data[3],
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*********************************************/
+ /* Selects the master configuration register */
+ /*********************************************/
+
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**********************/
+ /* Reads the register */
+ /**********************/
+
+ i_MasterConfiguration =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /********************************************************/
+ /* Enables timer/counter 1 and triggers timer/counter 1 */
+ /********************************************************/
+
+ i_MasterConfiguration =
+ i_MasterConfiguration | 0x40;
+
+ /*********************************************/
+ /* Selects the master configuration register */
+ /*********************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /********************************/
+ /* Writes the new configuration */
+ /********************************/
+ outb(i_MasterConfiguration,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /****************************************/
+ /* Selects the commands register of */
+ /* timer/counter 1 */
+ /****************************************/
+
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************/
+ /* Disable timer/counter 1 */
+ /***************************/
+
+ outb(0x0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /****************************************/
+ /* Selects the commands register of */
+ /* timer/counter 1 */
+ /****************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************/
+ /* Trigger timer/counter 1 */
+ /***************************/
+ outb(0x2,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+ else {
+ printk("\nError in selection of interrupt enable or disable\n");
+ return -EINVAL;
+ } //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+ } // if ((data[3]>= 0) && (data[3] <= 65535))
+ else {
+ printk("\nError in selection of reload value\n");
+ return -EINVAL;
+ } //else if ((data[3]>= 0) && (data[3] <= 65535))
+ i_TimerCounterWatchdogInterrupt = data[7];
+ i_TimerCounter1Init = 1;
+ break;
+
+ case COUNTER2: //selecting counter or timer
+ switch (data[2]) {
+ case 0:
+ data[2] = APCI1500_COUNTER;
+ break;
+ case 1:
+ data[2] = APCI1500_TIMER;
+ break;
+ default:
+ printk("\nThis choice is not a timer nor a counter\n");
+ return -EINVAL;
+ } // switch(data[2])
+
+ //Selecting single or continuous mode
+ switch (data[4]) {
+ case 0:
+ data[4] = APCI1500_CONTINUOUS;
+ break;
+ case 1:
+ data[4] = APCI1500_SINGLE;
+ break;
+ default:
+ printk("\nThis option for single/continuous mode does not exist\n");
+ return -EINVAL;
+ } // switch(data[4])
+
+ //Selecting software or hardware trigger
+ switch (data[5]) {
+ case 0:
+ data[5] = APCI1500_SOFTWARE_TRIGGER;
+ break;
+ case 1:
+ data[5] = APCI1500_HARDWARE_TRIGGER;
+ break;
+ default:
+ printk("\nThis choice for software or hardware trigger does not exist\n");
+ return -EINVAL;
+ } // switch(data[5])
+
+ //Selecting software or hardware gate
+ switch (data[6]) {
+ case 0:
+ data[6] = APCI1500_SOFTWARE_GATE;
+ break;
+ case 1:
+ data[6] = APCI1500_HARDWARE_GATE;
+ break;
+ default:
+ printk("\nThis choice for software or hardware gate does not exist\n");
+ return -EINVAL;
+ } // switch(data[6])
+
+ i_TimerCounterMode = data[2] | data[4] | data[5] | data[6] | 7;
+
+ /*************************/
+ /* Test the reload value */
+ /*************************/
+
+ if ((data[3] >= 0) && (data[3] <= 65535)) {
+ if (data[7] == APCI1500_ENABLE
+ || data[7] == APCI1500_DISABLE) {
+
+ /************************************************/
+ /* Selects the mode register of timer/counter 2 */
+ /************************************************/
+ outb(APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************/
+ /* Writes the new mode */
+ /***********************/
+ outb(i_TimerCounterMode,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /****************************************************/
+ /* Selects the constant register of timer/counter 2 */
+ /****************************************************/
+
+ outb(APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*************************/
+ /* Writes the low value */
+ /*************************/
+
+ outb(data[3],
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /****************************************************/
+ /* Selects the constant register of timer/counter 2 */
+ /****************************************************/
+
+ outb(APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**************************/
+ /* Writes the high value */
+ /**************************/
+
+ data[3] = data[3] >> 8;
+ outb(data[3],
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*********************************************/
+ /* Selects the master configuration register */
+ /*********************************************/
+
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**********************/
+ /* Reads the register */
+ /**********************/
+
+ i_MasterConfiguration =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /********************************************************/
+ /* Enables timer/counter 2 and triggers timer/counter 2 */
+ /********************************************************/
+
+ i_MasterConfiguration =
+ i_MasterConfiguration | 0x20;
+
+ /*********************************************/
+ /* Selects the master configuration register */
+ /*********************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /********************************/
+ /* Writes the new configuration */
+ /********************************/
+ outb(i_MasterConfiguration,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /****************************************/
+ /* Selects the commands register of */
+ /* timer/counter 2 */
+ /****************************************/
+
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************/
+ /* Disable timer/counter 2 */
+ /***************************/
+
+ outb(0x0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /****************************************/
+ /* Selects the commands register of */
+ /* timer/counter 2 */
+ /****************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************/
+ /* Trigger timer/counter 1 */
+ /***************************/
+ outb(0x2,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+ else {
+ printk("\nError in selection of interrupt enable or disable\n");
+ return -EINVAL;
+ } //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+ } // if ((data[3]>= 0) && (data[3] <= 65535))
+ else {
+ printk("\nError in selection of reload value\n");
+ return -EINVAL;
+ } //else if ((data[3]>= 0) && (data[3] <= 65535))
+ i_TimerCounterWatchdogInterrupt = data[7];
+ i_TimerCounter2Init = 1;
+ break;
+
+ case COUNTER3: //selecting counter or watchdog
+ switch (data[2]) {
+ case 0:
+ data[2] = APCI1500_COUNTER;
+ break;
+ case 1:
+ data[2] = APCI1500_WATCHDOG;
+ break;
+ default:
+ printk("\nThis choice is not a watchdog nor a counter\n");
+ return -EINVAL;
+ } // switch(data[2])
+
+ //Selecting single or continuous mode
+ switch (data[4]) {
+ case 0:
+ data[4] = APCI1500_CONTINUOUS;
+ break;
+ case 1:
+ data[4] = APCI1500_SINGLE;
+ break;
+ default:
+ printk("\nThis option for single/continuous mode does not exist\n");
+ return -EINVAL;
+ } // switch(data[4])
+
+ //Selecting software or hardware gate
+ switch (data[6]) {
+ case 0:
+ data[6] = APCI1500_SOFTWARE_GATE;
+ break;
+ case 1:
+ data[6] = APCI1500_HARDWARE_GATE;
+ break;
+ default:
+ printk("\nThis choice for software or hardware gate does not exist\n");
+ return -EINVAL;
+ } // switch(data[6])
+
+ /*****************************/
+ /* Test if used for watchdog */
+ /*****************************/
+
+ if (data[2] == APCI1500_WATCHDOG) {
+ /*****************************/
+ /* - Enables the output line */
+ /* - Enables retrigger */
+ /* - Pulses output */
+ /*****************************/
+ i_TimerCounterMode = data[2] | data[4] | 0x54;
+ } //if (data[2] == APCI1500_WATCHDOG)
+ else {
+ i_TimerCounterMode = data[2] | data[4] | data[6] | 7;
+ } //elseif (data[2] == APCI1500_WATCHDOG)
+ /*************************/
+ /* Test the reload value */
+ /*************************/
+
+ if ((data[3] >= 0) && (data[3] <= 65535)) {
+ if (data[7] == APCI1500_ENABLE
+ || data[7] == APCI1500_DISABLE) {
+
+ /************************************************/
+ /* Selects the mode register of watchdog/counter 3 */
+ /************************************************/
+ outb(APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************/
+ /* Writes the new mode */
+ /***********************/
+ outb(i_TimerCounterMode,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /****************************************************/
+ /* Selects the constant register of watchdog/counter 3 */
+ /****************************************************/
+
+ outb(APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*************************/
+ /* Writes the low value */
+ /*************************/
+
+ outb(data[3],
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /****************************************************/
+ /* Selects the constant register of watchdog/counter 3 */
+ /****************************************************/
+
+ outb(APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**************************/
+ /* Writes the high value */
+ /**************************/
+
+ data[3] = data[3] >> 8;
+ outb(data[3],
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*********************************************/
+ /* Selects the master configuration register */
+ /*********************************************/
+
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /**********************/
+ /* Reads the register */
+ /**********************/
+
+ i_MasterConfiguration =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /********************************************************/
+ /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */
+ /********************************************************/
+
+ i_MasterConfiguration =
+ i_MasterConfiguration | 0x10;
+
+ /*********************************************/
+ /* Selects the master configuration register */
+ /*********************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /********************************/
+ /* Writes the new configuration */
+ /********************************/
+ outb(i_MasterConfiguration,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /********************/
+ /* Test if COUNTER */
+ /********************/
+ if (data[2] == APCI1500_COUNTER) {
+
+ /*************************************/
+ /* Selects the command register of */
+ /* watchdog/counter 3 */
+ /*************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************************/
+ /* Disable the watchdog/counter 3 and starts it */
+ /*************************************************/
+ outb(0x0,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*************************************/
+ /* Selects the command register of */
+ /* watchdog/counter 3 */
+ /*************************************/
+
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************************/
+ /* Trigger the watchdog/counter 3 and starts it */
+ /*************************************************/
+ outb(0x2,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ } //elseif(data[2]==APCI1500_COUNTER)
+
+ } //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+ else {
+ printk("\nError in selection of interrupt enable or disable\n");
+ return -EINVAL;
+ } //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE)
+ } // if ((data[3]>= 0) && (data[3] <= 65535))
+ else {
+ printk("\nError in selection of reload value\n");
+ return -EINVAL;
+ } //else if ((data[3]>= 0) && (data[3] <= 65535))
+ i_TimerCounterWatchdogInterrupt = data[7];
+ i_WatchdogCounter3Init = 1;
+ break;
+
+ default:
+ printk("\nThe specified counter\timer option does not exist\n");
+ } //switch(data[1])
+ i_CounterLogic = data[2];
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_StartStopTriggerTimerCounterWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data); |
++----------------------------------------------------------------------------+
+| Task : Start / Stop or trigger the timer counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
+ data[0] : 0 Counter1/Timer1
+ 1 Counter2/Timer2
+ 2 Counter3/Watchdog
+ data[1] : 0 start
+ 1 stop
+ 2 Trigger
+ data[2] : 0 Counter
+ 1 Timer/Watchdog
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ int i_CommandAndStatusValue;
+
+ switch (data[0]) {
+ case COUNTER1:
+ switch (data[1]) {
+ case START:
+ if (i_TimerCounter1Init == 1) {
+ if (i_TimerCounterWatchdogInterrupt == 1) {
+ i_CommandAndStatusValue = 0xC4; //Enable the interrupt
+ } // if(i_TimerCounterWatchdogInterrupt==1)
+ else {
+ i_CommandAndStatusValue = 0xE4; //disable the interrupt
+ } //elseif(i_TimerCounterWatchdogInterrupt==1)
+ /**************************/
+ /* Starts timer/counter 1 */
+ /**************************/
+ i_TimerCounter1Enabled = 1;
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_TimerCounter1Init==1)
+ else {
+ printk("\nCounter/Timer1 not configured\n");
+ return -EINVAL;
+ }
+ break;
+
+ case STOP:
+
+ /**************************/
+ /* Stop timer/counter 1 */
+ /**************************/
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x00,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_TimerCounter1Enabled = 0;
+ break;
+
+ case TRIGGER:
+ if (i_TimerCounter1Init == 1) {
+ if (i_TimerCounter1Enabled == 1) {
+ /************************/
+ /* Set Trigger and gate */
+ /************************/
+
+ i_CommandAndStatusValue = 0x6;
+ } //if( i_TimerCounter1Enabled==1)
+ else {
+ /***************/
+ /* Set Trigger */
+ /***************/
+
+ i_CommandAndStatusValue = 0x2;
+ } //elseif(i_TimerCounter1Enabled==1)
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_TimerCounter1Init==1)
+ else {
+ printk("\nCounter/Timer1 not configured\n");
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ printk("\nThe specified option for start/stop/trigger does not exist\n");
+ return -EINVAL;
+ } //switch(data[1])
+ break;
+
+ case COUNTER2:
+ switch (data[1]) {
+ case START:
+ if (i_TimerCounter2Init == 1) {
+ if (i_TimerCounterWatchdogInterrupt == 1) {
+ i_CommandAndStatusValue = 0xC4; //Enable the interrupt
+ } // if(i_TimerCounterWatchdogInterrupt==1)
+ else {
+ i_CommandAndStatusValue = 0xE4; //disable the interrupt
+ } //elseif(i_TimerCounterWatchdogInterrupt==1)
+ /**************************/
+ /* Starts timer/counter 2 */
+ /**************************/
+ i_TimerCounter2Enabled = 1;
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_TimerCounter2Init==1)
+ else {
+ printk("\nCounter/Timer2 not configured\n");
+ return -EINVAL;
+ }
+ break;
+
+ case STOP:
+
+ /**************************/
+ /* Stop timer/counter 2 */
+ /**************************/
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x00,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_TimerCounter2Enabled = 0;
+ break;
+ case TRIGGER:
+ if (i_TimerCounter2Init == 1) {
+ if (i_TimerCounter2Enabled == 1) {
+ /************************/
+ /* Set Trigger and gate */
+ /************************/
+
+ i_CommandAndStatusValue = 0x6;
+ } //if( i_TimerCounter2Enabled==1)
+ else {
+ /***************/
+ /* Set Trigger */
+ /***************/
+
+ i_CommandAndStatusValue = 0x2;
+ } //elseif(i_TimerCounter2Enabled==1)
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_TimerCounter2Init==1)
+ else {
+ printk("\nCounter/Timer2 not configured\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ printk("\nThe specified option for start/stop/trigger does not exist\n");
+ return -EINVAL;
+ } //switch(data[1])
+ break;
+ case COUNTER3:
+ switch (data[1]) {
+ case START:
+ if (i_WatchdogCounter3Init == 1) {
+
+ if (i_TimerCounterWatchdogInterrupt == 1) {
+ i_CommandAndStatusValue = 0xC4; //Enable the interrupt
+ } // if(i_TimerCounterWatchdogInterrupt==1)
+ else {
+ i_CommandAndStatusValue = 0xE4; //disable the interrupt
+ } //elseif(i_TimerCounterWatchdogInterrupt==1)
+ /**************************/
+ /* Starts Watchdog/counter 3 */
+ /**************************/
+ i_WatchdogCounter3Enabled = 1;
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ } // if( i_WatchdogCounter3init==1)
+ else {
+ printk("\nWatchdog/Counter3 not configured\n");
+ return -EINVAL;
+ }
+ break;
+
+ case STOP:
+
+ /**************************/
+ /* Stop Watchdog/counter 3 */
+ /**************************/
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x00,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_WatchdogCounter3Enabled = 0;
+ break;
+
+ case TRIGGER:
+ switch (data[2]) {
+ case 0: //triggering counter 3
+ if (i_WatchdogCounter3Init == 1) {
+ if (i_WatchdogCounter3Enabled == 1) {
+ /************************/
+ /* Set Trigger and gate */
+ /************************/
+
+ i_CommandAndStatusValue = 0x6;
+ } //if( i_WatchdogCounter3Enabled==1)
+ else {
+ /***************/
+ /* Set Trigger */
+ /***************/
+
+ i_CommandAndStatusValue = 0x2;
+ } //elseif(i_WatchdogCounter3Enabled==1)
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_WatchdogCounter3Init==1)
+ else {
+ printk("\nCounter3 not configured\n");
+ return -EINVAL;
+ }
+ break;
+ case 1:
+ //triggering Watchdog 3
+ if (i_WatchdogCounter3Init == 1) {
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x6,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_WatchdogCounter3Init==1)
+ else {
+ printk("\nWatchdog 3 not configured\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ printk("\nWrong choice of watchdog/counter3\n");
+ return -EINVAL;
+ } //switch(data[2])
+ break;
+ default:
+ printk("\nThe specified option for start/stop/trigger does not exist\n");
+ return -EINVAL;
+ } //switch(data[1])
+ break;
+ default:
+ printk("\nThe specified choice for counter/watchdog/timer does not exist\n");
+ return -EINVAL;
+ } //switch(data[0])
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_ReadCounterTimerWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data); |
++----------------------------------------------------------------------------+
+| Task : Read The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
+ data[0] : 0 Counter1/Timer1
+ 1 Counter2/Timer2
+ 2 Counter3/Watchdog
+
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ int i_CommandAndStatusValue;
+ switch (data[0]) {
+ case COUNTER1:
+ //Read counter/timer1
+ if (i_TimerCounter1Init == 1) {
+ if (i_TimerCounter1Enabled == 1) {
+ /************************/
+ /* Set RCC and gate */
+ /************************/
+
+ i_CommandAndStatusValue = 0xC;
+ } //if( i_TimerCounter1Init==1)
+ else {
+ /***************/
+ /* Set RCC */
+ /***************/
+
+ i_CommandAndStatusValue = 0x8;
+ } //elseif(i_TimerCounter1Init==1)
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************************/
+ /* Selects the counter register (high) */
+ /***************************************/
+ outb(APCI1500_R_CPT_TMR1_VALUE_HIGH,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] = data[0] << 8;
+ data[0] = data[0] & 0xff00;
+ outb(APCI1500_R_CPT_TMR1_VALUE_LOW,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] =
+ data[0] | inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_TimerCounter1Init==1)
+ else {
+ printk("\nTimer/Counter1 not configured\n");
+ return -EINVAL;
+ } //elseif( i_TimerCounter1Init==1)
+ break;
+ case COUNTER2:
+ //Read counter/timer2
+ if (i_TimerCounter2Init == 1) {
+ if (i_TimerCounter2Enabled == 1) {
+ /************************/
+ /* Set RCC and gate */
+ /************************/
+
+ i_CommandAndStatusValue = 0xC;
+ } //if( i_TimerCounter2Init==1)
+ else {
+ /***************/
+ /* Set RCC */
+ /***************/
+
+ i_CommandAndStatusValue = 0x8;
+ } //elseif(i_TimerCounter2Init==1)
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************************/
+ /* Selects the counter register (high) */
+ /***************************************/
+ outb(APCI1500_R_CPT_TMR2_VALUE_HIGH,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] = data[0] << 8;
+ data[0] = data[0] & 0xff00;
+ outb(APCI1500_R_CPT_TMR2_VALUE_LOW,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] =
+ data[0] | inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_TimerCounter2Init==1)
+ else {
+ printk("\nTimer/Counter2 not configured\n");
+ return -EINVAL;
+ } //elseif( i_TimerCounter2Init==1)
+ break;
+ case COUNTER3:
+ //Read counter/watchdog2
+ if (i_WatchdogCounter3Init == 1) {
+ if (i_WatchdogCounter3Enabled == 1) {
+ /************************/
+ /* Set RCC and gate */
+ /************************/
+
+ i_CommandAndStatusValue = 0xC;
+ } //if( i_TimerCounter2Init==1)
+ else {
+ /***************/
+ /* Set RCC */
+ /***************/
+
+ i_CommandAndStatusValue = 0x8;
+ } //elseif(i_WatchdogCounter3Init==1)
+
+ /********************************************/
+ /* Selects the commands and status register */
+ /********************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_CommandAndStatusValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************************/
+ /* Selects the counter register (high) */
+ /***************************************/
+ outb(APCI1500_R_CPT_TMR3_VALUE_HIGH,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] = data[0] << 8;
+ data[0] = data[0] & 0xff00;
+ outb(APCI1500_R_CPT_TMR3_VALUE_LOW,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ data[0] =
+ data[0] | inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ } //if( i_WatchdogCounter3Init==1)
+ else {
+ printk("\nWatchdogCounter3 not configured\n");
+ return -EINVAL;
+ } //elseif( i_WatchdogCounter3Init==1)
+ break;
+ default:
+ printk("\nThe choice of timer/counter/watchdog does not exist\n");
+ return -EINVAL;
+ } //switch(data[0])
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_ReadInterruptMask |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data); |
++----------------------------------------------------------------------------+
+| Task : Read the interrupt mask |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
+
+
++----------------------------------------------------------------------------+
+| Output Parameters : -- data[0]:The interrupt mask value data[1]:Channel no
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ data[0] = i_InterruptMask;
+ data[1] = i_InputChannel;
+ i_InterruptMask = 0;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_ConfigureInterrupt |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data); |
++----------------------------------------------------------------------------+
+| Task : Configures the interrupt registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer |
+
+
++----------------------------------------------------------------------------+
+| Output Parameters : --
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Status;
+ int i_RegValue;
+ int i_Constant;
+ devpriv->tsk_Current = current;
+ outl(0x0, devpriv->i_IobaseAmcc + 0x38);
+ if (data[0] == 1) {
+ i_Constant = 0xC0;
+ } //if(data[0]==1)
+ else {
+ if (data[0] == 0) {
+ i_Constant = 0x00;
+ } //if{data[0]==0)
+ else {
+ printk("\nThe parameter passed to driver is in error for enabling the voltage interrupt\n");
+ return -EINVAL;
+ } //else if(data[0]==0)
+ } //elseif(data[0]==1)
+
+ /*****************************************************/
+ /* Selects the mode specification register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*********************************************/
+ /* Writes the new configuration (APCI1500_OR) */
+ /*********************************************/
+ i_RegValue = (i_RegValue & 0xF9) | APCI1500_OR;
+
+ outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************/
+ /* Selects the command and status register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************/
+ /* Authorises the interrupt on the board */
+ /*****************************************/
+ outb(0xC0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /***************************************************/
+ /* Selects the pattern polarity register of port B */
+ /***************************************************/
+ outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************/
+ /* Selects the pattern transition register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************************/
+ /* Selects the pattern mask register of port B */
+ /***********************************************/
+ outb(APCI1500_RW_PORT_B_PATTERN_MASK,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the command and status register of port A */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of port A */
+ /***********************************/
+
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************/
+ /* Selects the command and status register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of port B */
+ /***********************************/
+
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the command and status register of timer 1 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of timer 1 */
+ /***********************************/
+
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the command and status register of timer 2 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of timer 2 */
+ /***********************************/
+
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the command and status register of timer 3 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of timer 3 */
+ /***********************************/
+
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*************************************************/
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Authorizes the main interrupt on the board */
+ /**********************************************/
+ outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************/
+ /* Enables the PCI interrupt */
+ /*****************************/
+ outl(0x3000, devpriv->i_IobaseAmcc + 0x38);
+ ui_Status = inl(devpriv->i_IobaseAmcc + 0x10);
+ ui_Status = inl(devpriv->i_IobaseAmcc + 0x38);
+ outl(0x23000, devpriv->i_IobaseAmcc + 0x38);
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : static void v_APCI1500_Interrupt |
+| (int irq , void *d) |
++----------------------------------------------------------------------------+
+| Task : Interrupt handler |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq : irq number |
+| void *d : void pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+static void v_APCI1500_Interrupt(int irq, void *d)
+{
+
+ struct comedi_device *dev = d;
+ UINT ui_InterruptStatus = 0;
+ int i_RegValue = 0;
+ i_InterruptMask = 0;
+
+ /***********************************/
+ /* Read the board interrupt status */
+ /***********************************/
+ ui_InterruptStatus = inl(devpriv->i_IobaseAmcc + 0x38);
+
+ /***************************************/
+ /* Test if board generated a interrupt */
+ /***************************************/
+ if ((ui_InterruptStatus & 0x800000) == 0x800000) {
+ /************************/
+ /* Disable all Interrupt */
+ /************************/
+ /*************************************************/
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ //outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Disables the main interrupt on the board */
+ /**********************************************/
+ //outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the command and status register of port A */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ if ((i_RegValue & 0x60) == 0x60) {
+ /*****************************************************/
+ /* Selects the command and status register of port A */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of port A */
+ /***********************************/
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_InterruptMask = i_InterruptMask | 1;
+ if (i_Logic == APCI1500_OR_PRIORITY) {
+ outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ /***************************************************/
+ /* Selects the interrupt vector register of port A */
+ /***************************************************/
+ outb(APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+
+ i_InputChannel = 1 + (i_RegValue >> 1);
+
+ } // if(i_Logic==APCI1500_OR_PRIORITY)
+ else {
+ i_InputChannel = 0;
+ } //elseif(i_Logic==APCI1500_OR_PRIORITY)
+ } // if ((i_RegValue & 0x60) == 0x60)
+
+ /*****************************************************/
+ /* Selects the command and status register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ if ((i_RegValue & 0x60) == 0x60) {
+ /*****************************************************/
+ /* Selects the command and status register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of port B */
+ /***********************************/
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ printk("\n\n\n");
+ /****************/
+ /* Reads port B */
+ /****************/
+ i_RegValue =
+ inb((UINT) devpriv->iobase +
+ APCI1500_Z8536_PORT_B);
+
+ i_RegValue = i_RegValue & 0xC0;
+ /**************************************/
+ /* Tests if this is an external error */
+ /**************************************/
+
+ if (i_RegValue) {
+ //Disable the interrupt
+ /*****************************************************/
+ /* Selects the command and status register of port B */
+ /*****************************************************/
+ outl(0x0, devpriv->i_IobaseAmcc + 0x38);
+
+ if (i_RegValue & 0x80) {
+ i_InterruptMask =
+ i_InterruptMask | 0x40;
+ } //if (i_RegValue & 0x80)
+
+ if (i_RegValue & 0x40) {
+ i_InterruptMask =
+ i_InterruptMask | 0x80;
+ } //if (i_RegValue & 0x40)
+ } // if (i_RegValue)
+ else {
+ i_InterruptMask = i_InterruptMask | 2;
+ } // if (i_RegValue)
+ } //if ((i_RegValue & 0x60) == 0x60)
+
+ /*****************************************************/
+ /* Selects the command and status register of timer 1 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ if ((i_RegValue & 0x60) == 0x60) {
+ /*****************************************************/
+ /* Selects the command and status register of timer 1 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of timer 1 */
+ /***********************************/
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_InterruptMask = i_InterruptMask | 4;
+ } // if ((i_RegValue & 0x60) == 0x60)
+ /*****************************************************/
+ /* Selects the command and status register of timer 2 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ if ((i_RegValue & 0x60) == 0x60) {
+ /*****************************************************/
+ /* Selects the command and status register of timer 2 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of timer 2 */
+ /***********************************/
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ i_InterruptMask = i_InterruptMask | 8;
+ } // if ((i_RegValue & 0x60) == 0x60)
+
+ /*****************************************************/
+ /* Selects the command and status register of timer 3 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_RegValue =
+ inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ if ((i_RegValue & 0x60) == 0x60) {
+ /*****************************************************/
+ /* Selects the command and status register of timer 3 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ /***********************************/
+ /* Deletes the interrupt of timer 3 */
+ /***********************************/
+ i_RegValue = (i_RegValue & 0x0F) | 0x20;
+ outb(i_RegValue,
+ devpriv->iobase +
+ APCI1500_Z8536_CONTROL_REGISTER);
+ if (i_CounterLogic == APCI1500_COUNTER) {
+ i_InterruptMask = i_InterruptMask | 0x10;
+ } //if(i_CounterLogic==APCI1500_COUNTER)
+ else {
+ i_InterruptMask = i_InterruptMask | 0x20;
+ }
+ } // if ((i_RegValue & 0x60) == 0x60)
+
+ send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
+ /***********************/
+ /* Enable all Interrupts */
+ /***********************/
+
+ /*************************************************/
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /**********************************************/
+ /* Authorizes the main interrupt on the board */
+ /**********************************************/
+ outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ } // if ((ui_InterruptStatus & 0x800000) == 0x800000)
+ else {
+ printk("\nInterrupt from unknown source\n");
+
+ } //else if ((ui_InterruptStatus & 0x800000) == 0x800000)
+ return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1500_Reset(struct comedi_device *dev) | |
++----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1500_Reset(struct comedi_device * dev)
+{
+ int i_DummyRead = 0;
+ i_TimerCounter1Init = 0;
+ i_TimerCounter2Init = 0;
+ i_WatchdogCounter3Init = 0;
+ i_Event1Status = 0;
+ i_Event2Status = 0;
+ i_TimerCounterWatchdogInterrupt = 0;
+ i_Logic = 0;
+ i_CounterLogic = 0;
+ i_InterruptMask = 0;
+ i_InputChannel = 0;;
+ i_TimerCounter1Enabled = 0;
+ i_TimerCounter2Enabled = 0;
+ i_WatchdogCounter3Enabled = 0;
+
+ /******************/
+ /* Software reset */
+ /******************/
+ i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the master configuration control register */
+ /*****************************************************/
+ outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the mode specification register of port A */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_A_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /* Selects the data path polarity register of port A */
+ outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* High level of port A means 1 */
+ outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /* Selects the data direction register of port A */
+ outb(APCI1500_RW_PORT_A_DATA_DIRECTION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* All bits used as inputs */
+ outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port A */
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port A */
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates the interrupt management of port A: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the handshake specification register of port A */
+ outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes the register */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the mode specification register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the data path polarity register of port B */
+ outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* A high level of port B means 1 */
+ outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the data direction register of port B */
+ outb(APCI1500_RW_PORT_B_DATA_DIRECTION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* All bits used as inputs */
+ outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port B */
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of port B */
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates the interrupt management of port B: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the handshake specification register of port B */
+ outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes the register */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+
+ /*****************************************************/
+ /* Selects the data path polarity register of port C */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* High level of port C means 1 */
+ outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the data direction register of port C */
+ outb(APCI1500_RW_PORT_C_DATA_DIRECTION,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* All bits used as inputs except channel 1 */
+ outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the special IO register of port C */
+ outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes it */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************************************************/
+ /* Selects the command and status register of timer 1 */
+ /******************************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of timer 1 */
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates the interrupt management of timer 1 */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************************************************/
+ /* Selects the command and status register of timer 2 */
+ /******************************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of timer 2 */
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates Timer 2 interrupt management: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /******************************************************/
+ /* Selects the command and status register of timer 3 */
+ /******************************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes IP and IUS */
+ outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Selects the command and status register of Timer 3 */
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deactivates interrupt management of timer 3: */
+ outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*************************************************/
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /* Deletes all interrupts */
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ //reset all the digital outputs
+ outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP);
+/*******************************/
+/* Disable the board interrupt */
+/*******************************/
+ /*************************************************/
+ /* Selects the master interrupt control register */
+ /*************************************************/
+ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+ outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ /*****************************************************/
+ /* Selects the command and status register of port A */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+ outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+ /* Selects the command and status register of port B */
+ /*****************************************************/
+ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+ outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+ /* Selects the command and status register of timer 1 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+ outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+ /* Selects the command and status register of timer 2 */
+ /*****************************************************/
+ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+ outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/*****************************************************/
+/* Selects the command and status register of timer 3*/
+/*****************************************************/
+ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+/****************************/
+/* Deactivates all interrupts */
+/******************************/
+ outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER);
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
new file mode 100644
index 000000000000..5d960b40a6a8
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+/********* Definitions for APCI-1500 card *****/
+
+// Card Specific information
+#define APCI1500_BOARD_VENDOR_ID 0x10e8
+#define APCI1500_ADDRESS_RANGE 4
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI1500_DIGITAL_OP 2
+#define APCI1500_DIGITAL_IP 0
+#define APCI1500_AND 2
+#define APCI1500_OR 4
+#define APCI1500_OR_PRIORITY 6
+#define APCI1500_CLK_SELECT 0
+#define COUNTER1 0
+#define COUNTER2 1
+#define COUNTER3 2
+#define APCI1500_COUNTER 0x20
+#define APCI1500_TIMER 0
+#define APCI1500_WATCHDOG 0
+#define APCI1500_SINGLE 0
+#define APCI1500_CONTINUOUS 0x80
+#define APCI1500_DISABLE 0
+#define APCI1500_ENABLE 1
+#define APCI1500_SOFTWARE_TRIGGER 0x4
+#define APCI1500_HARDWARE_TRIGGER 0x10
+#define APCI1500_SOFTWARE_GATE 0
+#define APCI1500_HARDWARE_GATE 0x8
+#define START 0
+#define STOP 1
+#define TRIGGER 2
+
+/*
+ * Zillog I/O enumeration
+ */
+enum {
+ APCI1500_Z8536_PORT_C,
+ APCI1500_Z8536_PORT_B,
+ APCI1500_Z8536_PORT_A,
+ APCI1500_Z8536_CONTROL_REGISTER
+};
+
+/*
+ * Z8536 CIO Internal Address
+ */
+enum {
+ APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+ APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+ APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
+ APCI1500_RW_PORT_B_INTERRUPT_CONTROL,
+ APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR,
+ APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+ APCI1500_RW_PORT_C_DATA_DIRECTION,
+ APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
+
+ APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+ APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+ APCI1500_RW_CPT_TMR1_CMD_STATUS,
+ APCI1500_RW_CPT_TMR2_CMD_STATUS,
+ APCI1500_RW_CPT_TMR3_CMD_STATUS,
+ APCI1500_RW_PORT_A_DATA,
+ APCI1500_RW_PORT_B_DATA,
+ APCI1500_RW_PORT_C_DATA,
+
+ APCI1500_R_CPT_TMR1_VALUE_HIGH,
+ APCI1500_R_CPT_TMR1_VALUE_LOW,
+ APCI1500_R_CPT_TMR2_VALUE_HIGH,
+ APCI1500_R_CPT_TMR2_VALUE_LOW,
+ APCI1500_R_CPT_TMR3_VALUE_HIGH,
+ APCI1500_R_CPT_TMR3_VALUE_LOW,
+ APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
+ APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
+ APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
+ APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
+ APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
+ APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
+ APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
+ APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
+ APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
+ APCI1500_R_CURRENT_VECTOR,
+
+ APCI1500_RW_PORT_A_SPECIFICATION,
+ APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
+ APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
+ APCI1500_RW_PORT_A_DATA_DIRECTION,
+ APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL,
+ APCI1500_RW_PORT_A_PATTERN_POLARITY,
+ APCI1500_RW_PORT_A_PATTERN_TRANSITION,
+ APCI1500_RW_PORT_A_PATTERN_MASK,
+
+ APCI1500_RW_PORT_B_SPECIFICATION,
+ APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
+ APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
+ APCI1500_RW_PORT_B_DATA_DIRECTION,
+ APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL,
+ APCI1500_RW_PORT_B_PATTERN_POLARITY,
+ APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+ APCI1500_RW_PORT_B_PATTERN_MASK
+};
+
+ /*----------DIGITAL INPUT----------------*/
+static int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+
+static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*---------- DIGITAL OUTPUT------------*/
+static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*----------TIMER----------------*/
+static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*----------INTERRUPT HANDLER------*/
+static void v_APCI1500_Interrupt(int irq, void *d);
+static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+/*----------RESET---------------*/
+static int i_APCI1500_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
new file mode 100644
index 000000000000..5ae9a93844e7
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
@@ -0,0 +1,542 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-1516 | Compiler : GCC |
+ | Module name : hwdrv_apci1516.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-1516 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci1516.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_Read1DigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the digital input |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_TmpValue = 0;
+ UINT ui_Channel;
+ ui_Channel = CR_CHAN(insn->chanspec);
+ if (ui_Channel >= 0 && ui_Channel <= 7) {
+ ui_TmpValue = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+ // since only 1 channel reqd to bring it to last bit it is rotated
+ // 8 +(chan - 1) times then ANDed with 1 for last bit.
+ *data = (ui_TmpValue >> ui_Channel) & 0x1;
+ } //if(ui_Channel >= 0 && ui_Channel <=7)
+ else {
+ //comedi_error(dev," \n chan spec wrong\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //else if(ui_Channel >= 0 && ui_Channel <=7)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_ReadMoreDigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the Requested digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ UINT ui_PortValue = data[0];
+ UINT ui_Mask = 0;
+ UINT ui_NoOfChannels;
+
+ ui_NoOfChannels = CR_CHAN(insn->chanspec);
+
+ *data = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
+ switch (ui_NoOfChannels) {
+ case 2:
+ ui_Mask = 3;
+ *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+ break;
+ case 4:
+ ui_Mask = 15;
+ *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+ break;
+ case 7:
+ break;
+
+ default:
+ printk("\nWrong parameters\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ break;
+ } //switch(ui_NoOfChannels)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_ConfigDigitalOutput (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 |
+| unsigned int *data : Data Pointer contains |
+| configuration parameters as below |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| data[0] :1:Memory on |
+| 0:Memory off |
+| |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ devpriv->b_OutputMemoryStatus = data[0];
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_WriteDigitalOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Writes port value To the selected port |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Temp, ui_Temp1;
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+
+ printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP);
+
+ if (devpriv->b_OutputMemoryStatus) {
+ ui_Temp = inw(devpriv->iobase + APCI1516_DIGITAL_OP);
+
+ } //if(devpriv->b_OutputMemoryStatus )
+ else {
+ ui_Temp = 0;
+ } //if(devpriv->b_OutputMemoryStatus )
+ if (data[3] == 0) {
+ if (data[1] == 0) {
+ data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ outw(data[0], devpriv->iobase + APCI1516_DIGITAL_OP);
+
+ printk("EL311003 : d=%d @=%x\n", data[0],
+ devpriv->iobase + APCI1516_DIGITAL_OP);
+
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] =
+ (data[0] << (2 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 4:
+ data[0] =
+ (data[0] << (4 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 7:
+ data[0] = data[0] | ui_Temp;
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outw(data[0],
+ devpriv->iobase + APCI1516_DIGITAL_OP);
+
+ printk("EL311003 : d=%d @=%x\n", data[0],
+ devpriv->iobase + APCI1516_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==0)
+ else {
+ if (data[3] == 1) {
+ if (data[1] == 0) {
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] = (data[0] << ui_NoOfChannel) ^ 0xff;
+ data[0] = data[0] & ui_Temp;
+ outw(data[0],
+ devpriv->iobase + APCI1516_DIGITAL_OP);
+
+ printk("EL311003 : d=%d @=%x\n", data[0],
+ devpriv->iobase + APCI1516_DIGITAL_OP);
+
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] = ~data[0] & 0x3;
+ ui_Temp1 = 3;
+ ui_Temp1 =
+ ui_Temp1 << 2 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (2 *
+ data
+ [2])) ^
+ 0xff) & ui_Temp;
+ break;
+
+ case 4:
+ data[0] = ~data[0] & 0xf;
+ ui_Temp1 = 15;
+ ui_Temp1 =
+ ui_Temp1 << 4 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (4 *
+ data
+ [2])) ^
+ 0xff) & ui_Temp;
+ break;
+
+ case 7:
+ break;
+
+ default:
+ comedi_error(dev,
+ " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outw(data[0],
+ devpriv->iobase +
+ APCI1516_DIGITAL_OP);
+
+ printk("EL311003 : d=%d @=%x\n",
+ data[0],
+ devpriv->iobase +
+ APCI1516_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==1);
+ else {
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } //if else data[3]==1)
+ } //if else data[3]==0)
+ return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_ReadDigitalOutput |
+| (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 |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ UINT ui_Temp;
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+ ui_Temp = data[0];
+ *data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW);
+ if (ui_Temp == 0) {
+ *data = (*data >> ui_NoOfChannel) & 0x1;
+ } //if(ui_Temp==0)
+ else {
+ if (ui_Temp == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ *data = (*data >> (2 * data[1])) & 3;
+ break;
+
+ case 4:
+ *data = (*data >> (4 * data[1])) & 15;
+ break;
+
+ case 7:
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+ } //if(ui_Temp==1)
+ else {
+ printk("\nSpecified channel not supported \n");
+ } //elseif(ui_Temp==1)
+ } //elseif(ui_Temp==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : Configures The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ if (data[0] == 0) {
+ //Disable the watchdog
+ outw(0x0,
+ devpriv->i_IobaseAddon +
+ APCI1516_WATCHDOG_ENABLEDISABLE);
+ //Loading the Reload value
+ outw(data[1],
+ devpriv->i_IobaseAddon +
+ APCI1516_WATCHDOG_RELOAD_VALUE);
+ data[1] = data[1] >> 16;
+ outw(data[1],
+ devpriv->i_IobaseAddon +
+ APCI1516_WATCHDOG_RELOAD_VALUE + 2);
+ } //if(data[0]==0)
+ else {
+ printk("\nThe input parameters are wrong\n");
+ return -EINVAL;
+ } //elseif(data[0]==0)
+
+ return insn->n;
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : int i_APCI1516_StartStopWriteWatchdog |
+ | (struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data); |
+ +----------------------------------------------------------------------------+
+ | Task : Start / Stop The Watchdog |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : struct comedi_device *dev : Driver handle |
+ | struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+ | unsigned int *data : Data Pointer to read status |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -- |
+ +----------------------------------------------------------------------------+
+ | Return Value : TRUE : No error occur |
+ | : FALSE : Error occur. Return the error |
+ | |
+ +----------------------------------------------------------------------------+
+ */
+
+int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ switch (data[0]) {
+ case 0: //stop the watchdog
+ outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE); //disable the watchdog
+ break;
+ case 1: //start the watchdog
+ outw(0x0001,
+ devpriv->i_IobaseAddon +
+ APCI1516_WATCHDOG_ENABLEDISABLE);
+ break;
+ case 2: //Software trigger
+ outw(0x0201,
+ devpriv->i_IobaseAddon +
+ APCI1516_WATCHDOG_ENABLEDISABLE);
+ break;
+ default:
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } // switch(data[0])
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_ReadWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data); |
++----------------------------------------------------------------------------+
+| Task : Read The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1516_Reset(struct comedi_device *dev) | |
++----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1516_Reset(struct comedi_device * dev)
+{
+ outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP); //RESETS THE DIGITAL OUTPUTS
+ outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
+ outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE);
+ outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE + 2);
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
new file mode 100644
index 000000000000..398baa04a163
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+/********* Definitions for APCI-1516 card *****/
+
+// Card Specific information
+#define APCI1516_BOARD_VENDOR_ID 0x15B8
+#define APCI1516_ADDRESS_RANGE 8
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI1516_DIGITAL_OP 4
+#define APCI1516_DIGITAL_OP_RW 4
+#define APCI1516_DIGITAL_IP 0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_WATCHDOG 2
+#define APCI1516_DIGITAL_OP_WATCHDOG 0
+#define APCI1516_WATCHDOG_ENABLEDISABLE 12
+#define APCI1516_WATCHDOG_RELOAD_VALUE 4
+#define APCI1516_WATCHDOG_STATUS 16
+
+// Hardware Layer functions for Apci1516
+
+//Digital Input
+INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//Digital Output
+int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// TIMER
+// timer value is passed as u seconds
+int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//reset
+INT i_APCI1516_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
new file mode 100644
index 000000000000..a6b504c3d391
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -0,0 +1,1105 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-1564 | Compiler : GCC |
+ | Module name : hwdrv_apci1564.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-1564 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include <linux/delay.h>
+#include "hwdrv_apci1564.h"
+
+//Global variables
+UINT ui_InterruptStatus_1564 = 0;
+UINT ui_InterruptData, ui_Type;
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_ConfigDigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Configures the digital input Subdevice |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| unsigned int *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 1 Enable Digital Input Interrupt |
+| 0 Disable Digital Input Interrupt |
+| data[1] : 0 ADDIDATA Interrupt OR LOGIC |
+| : 1 ADDIDATA Interrupt AND LOGIC |
+| data[2] : Interrupt mask for the mode 1 |
+| data[3] : Interrupt mask for the mode 2 |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ devpriv->tsk_Current = current;
+ /*******************************/
+ /* Set the digital input logic */
+ /*******************************/
+ if (data[0] == ADDIDATA_ENABLE) {
+ data[2] = data[2] << 4;
+ data[3] = data[3] << 4;
+ outl(data[2],
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
+ outl(data[3],
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
+ if (data[1] == ADDIDATA_OR) {
+ outl(0x4,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_IRQ);
+ } // if (data[1] == ADDIDATA_OR)
+ else {
+ outl(0x6,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_IRQ);
+ } // else if (data[1] == ADDIDATA_OR)
+ } // if (data[0] == ADDIDATA_ENABLE)
+ else {
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_INTERRUPT_MODE1);
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_IRQ);
+ } // else if (data[0] == ADDIDATA_ENABLE)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_Read1DigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the digital input |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_Channel : Channel number to read |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_TmpValue = 0;
+ UINT ui_Channel;
+
+ ui_Channel = CR_CHAN(insn->chanspec);
+ if (ui_Channel >= 0 && ui_Channel <= 31) {
+ ui_TmpValue =
+ (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+ // since only 1 channel reqd to bring it to last bit it is rotated
+ // 8 +(chan - 1) times then ANDed with 1 for last bit.
+ *data = (ui_TmpValue >> ui_Channel) & 0x1;
+ } // if (ui_Channel >= 0 && ui_Channel <=31)
+ else {
+ comedi_error(dev, "Not a valid channel number !!! \n");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //else if (ui_Channel >= 0 && ui_Channel <=31)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_ReadMoreDigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the Requested digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_NoOfChannels : No Of Channels To be Read |
+| UINT *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_PortValue = data[0];
+ UINT ui_Mask = 0;
+ UINT ui_NoOfChannels;
+
+ ui_NoOfChannels = CR_CHAN(insn->chanspec);
+ if (data[1] == 0) {
+ *data = (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
+ switch (ui_NoOfChannels) {
+ case 2:
+ ui_Mask = 3;
+ *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+ break;
+ case 4:
+ ui_Mask = 15;
+ *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+ break;
+ case 8:
+ ui_Mask = 255;
+ *data = (*data >> (8 * ui_PortValue)) & ui_Mask;
+ break;
+ case 16:
+ ui_Mask = 65535;
+ *data = (*data >> (16 * ui_PortValue)) & ui_Mask;
+ break;
+ case 31:
+ break;
+ default:
+ comedi_error(dev, "Not a valid Channel number !!!\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ break;
+ } // switch (ui_NoOfChannels)
+ } // if (data[1]==0)
+ else {
+ if (data[1] == 1) {
+ *data = ui_InterruptStatus_1564;
+ } // if (data[1]==1)
+ } // else if (data[1]==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_ConfigDigitalOutput |
+| (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 |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[1] : 1 Enable VCC Interrupt |
+| 0 Disable VCC Interrupt |
+| data[2] : 1 Enable CC Interrupt |
+| 0 Disable CC Interrupt |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command = 0;
+
+ if ((data[0] != 0) && (data[0] != 1)) {
+ comedi_error(dev,
+ "Not a valid Data !!! ,Data should be 1 or 0\n");
+ return -EINVAL;
+ } // if ((data[0]!=0) && (data[0]!=1))
+ if (data[0]) {
+ devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+ } // if (data[0])
+ else {
+ devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+ } // else if (data[0])
+ if (data[1] == ADDIDATA_ENABLE) {
+ ul_Command = ul_Command | 0x1;
+ } // if (data[1] == ADDIDATA_ENABLE)
+ else {
+ ul_Command = ul_Command & 0xFFFFFFFE;
+ } // else if (data[1] == ADDIDATA_ENABLE)
+ if (data[2] == ADDIDATA_ENABLE) {
+ ul_Command = ul_Command | 0x2;
+ } // if (data[2] == ADDIDATA_ENABLE)
+ else {
+ ul_Command = ul_Command & 0xFFFFFFFD;
+ } // else if (data[2] == ADDIDATA_ENABLE)
+ outl(ul_Command,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_INTERRUPT);
+ ui_InterruptData =
+ inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_INTERRUPT);
+ devpriv->tsk_Current = current;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_WriteDigitalOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Writes port value To the selected port |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_NoOfChannels : No Of Channels To Write |
+| UINT *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Temp, ui_Temp1;
+ UINT ui_NoOfChannel;
+
+ ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ if (devpriv->b_OutputMemoryStatus) {
+ ui_Temp =
+ inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_RW);
+ } // if (devpriv->b_OutputMemoryStatus )
+ else {
+ ui_Temp = 0;
+ } // else if (devpriv->b_OutputMemoryStatus )
+ if (data[3] == 0) {
+ if (data[1] == 0) {
+ data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ outl(data[0],
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_RW);
+ } // if (data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+ case 2:
+ data[0] =
+ (data[0] << (2 *
+ data[2])) | ui_Temp;
+ break;
+ case 4:
+ data[0] =
+ (data[0] << (4 *
+ data[2])) | ui_Temp;
+ break;
+ case 8:
+ data[0] =
+ (data[0] << (8 *
+ data[2])) | ui_Temp;
+ break;
+ case 16:
+ data[0] =
+ (data[0] << (16 *
+ data[2])) | ui_Temp;
+ break;
+ case 31:
+ data[0] = data[0] | ui_Temp;
+ break;
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+ } // switch (ui_NoOfChannels)
+ outl(data[0],
+ devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_RW);
+ } // if (data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } // else if (data[1]==1)
+ } // else if (data[1]==0)
+ } //if(data[3]==0)
+ else {
+ if (data[3] == 1) {
+ if (data[1] == 0) {
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ (data[0] << ui_NoOfChannel) ^
+ 0xffffffff;
+ data[0] = data[0] & ui_Temp;
+ outl(data[0],
+ devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_RW);
+ } // if (data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+ case 2:
+ data[0] = ~data[0] & 0x3;
+ ui_Temp1 = 3;
+ ui_Temp1 =
+ ui_Temp1 << 2 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (2 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+ case 4:
+ data[0] = ~data[0] & 0xf;
+ ui_Temp1 = 15;
+ ui_Temp1 =
+ ui_Temp1 << 4 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (4 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+ case 8:
+ data[0] = ~data[0] & 0xff;
+ ui_Temp1 = 255;
+ ui_Temp1 =
+ ui_Temp1 << 8 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (8 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+ case 16:
+ data[0] = ~data[0] & 0xffff;
+ ui_Temp1 = 65535;
+ ui_Temp1 =
+ ui_Temp1 << 16 *
+ data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (16 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+ case 31:
+ break;
+ default:
+ comedi_error(dev,
+ " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //switch(ui_NoOfChannels)
+ outl(data[0],
+ devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_RW);
+ } // if (data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } // else if (data[1]==1)
+ } // else if (data[1]==0)
+ } // if (data[3]==1);
+ else {
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } // else if (data[3]==1)
+ } // else if (data[3]==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_ReadDigitalOutput |
+| (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 |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_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_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_RW);
+ if (ui_Temp == 0) {
+ *data = (*data >> ui_NoOfChannel) & 0x1;
+ } // if (ui_Temp==0)
+ else {
+ if (ui_Temp == 1) {
+ switch (ui_NoOfChannel) {
+ case 2:
+ *data = (*data >> (2 * data[1])) & 3;
+ break;
+
+ case 4:
+ *data = (*data >> (4 * data[1])) & 15;
+ break;
+
+ case 8:
+ *data = (*data >> (8 * data[1])) & 255;
+ break;
+
+ case 16:
+ *data = (*data >> (16 * data[1])) & 65535;
+ break;
+
+ case 31:
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+ break;
+ } // switch(ui_NoOfChannels)
+ } // if (ui_Temp==1)
+ else {
+ printk("\nSpecified channel not supported \n");
+ } // else if (ui_Temp==1)
+ } // else if (ui_Temp==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_ConfigTimerCounterWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Configures The Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 0 Configure As Timer |
+| 1 Configure As Counter |
+| 2 Configure As Watchdog |
+| data[1] : 1 Enable Interrupt |
+| 0 Disable Interrupt |
+| data[2] : Time Unit |
+| data[3] : Reload Value |
+| data[4] : Timer Mode |
+| data[5] : Timer Counter Watchdog Number|
+ data[6] : Counter Direction
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command1 = 0;
+ devpriv->tsk_Current = current;
+ if (data[0] == ADDIDATA_WATCHDOG) {
+ devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+
+ //Disable the watchdog
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+ APCI1564_TCW_PROG);
+ //Loading the Reload value
+ outl(data[3],
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+ APCI1564_TCW_RELOAD_VALUE);
+ } // if (data[0]==ADDIDATA_WATCHDOG)
+ else if (data[0] == ADDIDATA_TIMER) {
+ //First Stop The Timer
+ ul_Command1 =
+ inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+ outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //Stop The Timer
+
+ devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+ if (data[1] == 1) {
+ outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_IRQ);
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_IRQ);
+ outl(0x0,
+ devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP_WATCHDOG +
+ APCI1564_TCW_IRQ);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER1 +
+ APCI1564_TCW_IRQ);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER2 +
+ APCI1564_TCW_IRQ);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER3 +
+ APCI1564_TCW_IRQ);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER4 +
+ APCI1564_TCW_IRQ);
+ } // if (data[1]==1)
+ else {
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //disable Timer interrupt
+ } // else if (data[1]==1)
+
+ // Loading Timebase
+
+ outl(data[2],
+ devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_TIMEBASE);
+
+ //Loading the Reload value
+ outl(data[3],
+ devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_RELOAD_VALUE);
+
+ ul_Command1 =
+ inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ ul_Command1 =
+ (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
+ outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //mode 2
+ } // else if (data[0]==ADDIDATA_TIMER)
+ else if (data[0] == ADDIDATA_COUNTER) {
+ devpriv->b_TimerSelectMode = ADDIDATA_COUNTER;
+ devpriv->b_ModeSelectRegister = data[5];
+
+ //First Stop The Counter
+ ul_Command1 =
+ inl(devpriv->iobase + ((data[5] - 1) * 0x20) +
+ APCI1564_TCW_PROG);
+ ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+ outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); //Stop The Timer
+
+ /************************/
+ /* Set the reload value */
+ /************************/
+ outl(data[3],
+ devpriv->iobase + ((data[5] - 1) * 0x20) +
+ APCI1564_TCW_RELOAD_VALUE);
+
+ /******************************/
+ /* Set the mode : */
+ /* - Disable the hardware */
+ /* - Disable the counter mode */
+ /* - Disable the warning */
+ /* - Disable the reset */
+ /* - Disable the timer mode */
+ /* - Enable the counter mode */
+ /******************************/
+ ul_Command1 =
+ (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
+ (ULONG) ((ULONG) data[4] << 16UL);
+ outl(ul_Command1,
+ devpriv->iobase + ((data[5] - 1) * 0x20) +
+ APCI1564_TCW_PROG);
+
+ // Enable or Disable Interrupt
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
+ outl(ul_Command1,
+ devpriv->iobase + ((data[5] - 1) * 0x20) +
+ APCI1564_TCW_PROG);
+
+ /*****************************/
+ /* Set the Up/Down selection */
+ /*****************************/
+ ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
+ outl(ul_Command1,
+ devpriv->iobase + ((data[5] - 1) * 0x20) +
+ APCI1564_TCW_PROG);
+ } // else if (data[0]==ADDIDATA_COUNTER)
+ else {
+ printk(" Invalid subdevice.");
+ } // else if (data[0]==ADDIDATA_WATCHDOG)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Start / Stop The Selected Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 0 Timer |
+| 1 Counter |
+| 2 Watchdog | | data[1] : 1 Start |
+| 0 Stop |
+| 2 Trigger |
+| Clear (Only Counter) |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command1 = 0;
+ if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ switch (data[1]) {
+ case 0: //stop the watchdog
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG); //disable the watchdog
+ break;
+ case 1: //start the watchdog
+ outl(0x0001,
+ devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP_WATCHDOG +
+ APCI1564_TCW_PROG);
+ break;
+ case 2: //Software trigger
+ outl(0x0201,
+ devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP_WATCHDOG +
+ APCI1564_TCW_PROG);
+ break;
+ default:
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } // switch (data[1])
+ } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+ if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ if (data[1] == 1) {
+ ul_Command1 =
+ inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+
+ //Enable the Timer
+ outl(ul_Command1,
+ devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ } // if (data[1]==1)
+ else if (data[1] == 0) {
+ //Stop The Timer
+
+ ul_Command1 =
+ inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+ outl(ul_Command1,
+ devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ } // else if(data[1]==0)
+ } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+ if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+ ul_Command1 =
+ inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+ 1) * 0x20) + APCI1564_TCW_PROG);
+ if (data[1] == 1) {
+ //Start the Counter subdevice
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+ } // if (data[1] == 1)
+ else if (data[1] == 0) {
+ // Stops the Counter subdevice
+ ul_Command1 = 0;
+
+ } // else if (data[1] == 0)
+ else if (data[1] == 2) {
+ // Clears the Counter subdevice
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
+ } // else if (data[1] == 3)
+ outl(ul_Command1,
+ devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+ 1) * 0x20) + APCI1564_TCW_PROG);
+ } // if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_ReadTimerCounterWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read The Selected Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command1 = 0;
+
+ if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ // Stores the status of the Watchdog
+ data[0] =
+ inl(devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP_WATCHDOG +
+ APCI1564_TCW_TRIG_STATUS) & 0x1;
+ data[1] =
+ inl(devpriv->i_IobaseAmcc +
+ APCI1564_DIGITAL_OP_WATCHDOG);
+ } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+ else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ // Stores the status of the Timer
+ data[0] =
+ inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_TRIG_STATUS) & 0x1;
+
+ // Stores the Actual value of the Timer
+ data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER);
+ } // else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+ else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) {
+ // Read the Counter Actual Value.
+ data[0] =
+ inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+ 1) * 0x20) +
+ APCI1564_TCW_SYNC_ENABLEDISABLE);
+ ul_Command1 =
+ inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister -
+ 1) * 0x20) + APCI1564_TCW_TRIG_STATUS);
+
+ /***********************************/
+ /* Get the software trigger status */
+ /***********************************/
+ data[1] = (BYTE) ((ul_Command1 >> 1) & 1);
+
+ /***********************************/
+ /* Get the hardware trigger status */
+ /***********************************/
+ data[2] = (BYTE) ((ul_Command1 >> 2) & 1);
+
+ /*********************************/
+ /* Get the software clear status */
+ /*********************************/
+ data[3] = (BYTE) ((ul_Command1 >> 3) & 1);
+
+ /***************************/
+ /* Get the overflow status */
+ /***************************/
+ data[4] = (BYTE) ((ul_Command1 >> 0) & 1);
+ } // else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER)
+ else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+ && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)
+ && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) {
+ printk("\n Invalid Subdevice !!!\n");
+ } // else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER))
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_ReadInterruptStatus |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task :Reads the interrupt status register |
++----------------------------------------------------------------------------+
+| Input Parameters : |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ *data = ui_Type;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : static void v_APCI1564_Interrupt |
+| (int irq , void *d) |
++----------------------------------------------------------------------------+
+| Task : Interrupt handler for the interruptible digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq : irq number |
+| void *d : void pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+static void v_APCI1564_Interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ UINT ui_DO, ui_DI;
+ UINT ui_Timer;
+ UINT ui_C1, ui_C2, ui_C3, ui_C4;
+ ULONG ul_Command2 = 0;
+ ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_IRQ) & 0x01;
+ ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_IRQ) & 0x01;
+ ui_Timer =
+ inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_IRQ) & 0x01;
+ ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 +
+ APCI1564_TCW_IRQ) & 0x1;
+ ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 +
+ APCI1564_TCW_IRQ) & 0x1;
+ ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 +
+ APCI1564_TCW_IRQ) & 0x1;
+ ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 +
+ APCI1564_TCW_IRQ) & 0x1;
+ if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
+ && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
+ printk("\nInterrupt from unknown source\n");
+ } // if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0)
+
+ if (ui_DI == 1) {
+ ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_IRQ);
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_IRQ);
+ ui_InterruptStatus_1564 =
+ inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
+ APCI1564_DIGITAL_IP_INTERRUPT_STATUS);
+ ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0;
+ send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
+ outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); //enable the interrupt
+ return;
+ }
+
+ if (ui_DO == 1) {
+ // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
+ ui_Type =
+ inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
+ //Disable the Interrupt
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+ APCI1564_DIGITAL_OP_INTERRUPT);
+
+ //Sends signal to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ } // if (ui_DO)
+
+ if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_TIMER)) {
+ // Disable Timer Interrupt
+ ul_Command2 =
+ inl(devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ // Enable Timer Interrupt
+
+ outl(ul_Command2,
+ devpriv->i_IobaseAmcc + APCI1564_TIMER +
+ APCI1564_TCW_PROG);
+ } // if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER))
+
+ if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+ // Disable Counter Interrupt
+ ul_Command2 =
+ inl(devpriv->iobase + APCI1564_COUNTER1 +
+ APCI1564_TCW_PROG);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER1 +
+ APCI1564_TCW_PROG);
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ // Enable Counter Interrupt
+ outl(ul_Command2,
+ devpriv->iobase + APCI1564_COUNTER1 +
+ APCI1564_TCW_PROG);
+ } // if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER))
+
+ if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+ // Disable Counter Interrupt
+ ul_Command2 =
+ inl(devpriv->iobase + APCI1564_COUNTER2 +
+ APCI1564_TCW_PROG);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER2 +
+ APCI1564_TCW_PROG);
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ // Enable Counter Interrupt
+ outl(ul_Command2,
+ devpriv->iobase + APCI1564_COUNTER2 +
+ APCI1564_TCW_PROG);
+ } // if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
+
+ if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+ // Disable Counter Interrupt
+ ul_Command2 =
+ inl(devpriv->iobase + APCI1564_COUNTER3 +
+ APCI1564_TCW_PROG);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER3 +
+ APCI1564_TCW_PROG);
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ // Enable Counter Interrupt
+ outl(ul_Command2,
+ devpriv->iobase + APCI1564_COUNTER3 +
+ APCI1564_TCW_PROG);
+ } // if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
+
+ if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) {
+ // Disable Counter Interrupt
+ ul_Command2 =
+ inl(devpriv->iobase + APCI1564_COUNTER4 +
+ APCI1564_TCW_PROG);
+ outl(0x0,
+ devpriv->iobase + APCI1564_COUNTER4 +
+ APCI1564_TCW_PROG);
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+
+ // Enable Counter Interrupt
+ outl(ul_Command2,
+ devpriv->iobase + APCI1564_COUNTER4 +
+ APCI1564_TCW_PROG);
+ } // if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER))
+ return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | |
++----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI1564_Reset(struct comedi_device * dev)
+{
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ); //disable the interrupts
+ inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); //Reset the interrupt status register
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2);
+ devpriv->b_DigitalOutputRegister = 0;
+ ui_Type = 0;
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); //Resets the output channels
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT); //Disables the interrupt.
+ outl(0x0,
+ devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG +
+ APCI1564_TCW_RELOAD_VALUE);
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER);
+ outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG);
+
+ outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG);
+ outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG);
+ outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG);
+ outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG);
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
new file mode 100644
index 000000000000..f0c461ca5396
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+/********* Definitions for APCI-1564 card *****/
+
+#define APCI1564_BOARD_VENDOR_ID 0x15B8
+#define APCI1564_ADDRESS_RANGE 128
+
+//DIGITAL INPUT-OUTPUT DEFINE
+// Input defines
+#define APCI1564_DIGITAL_IP 0x04
+#define APCI1564_DIGITAL_IP_INTERRUPT_MODE1 4
+#define APCI1564_DIGITAL_IP_INTERRUPT_MODE2 8
+#define APCI1564_DIGITAL_IP_IRQ 16
+
+// Output defines
+#define APCI1564_DIGITAL_OP 0x18
+#define APCI1564_DIGITAL_OP_RW 0
+#define APCI1564_DIGITAL_OP_INTERRUPT 4
+#define APCI1564_DIGITAL_OP_IRQ 12
+
+//Digital Input IRQ Function Selection
+#define ADDIDATA_OR 0
+#define ADDIDATA_AND 1
+
+//Digital Input Interrupt Status
+#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS 12
+
+//Digital Output Interrupt Status
+#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS 8
+
+//Digital Input Interrupt Enable Disable.
+#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE 0x4
+#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB
+
+//Digital Output Interrupt Enable Disable.
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_TIMER 0
+#define ADDIDATA_COUNTER 1
+#define ADDIDATA_WATCHDOG 2
+#define APCI1564_DIGITAL_OP_WATCHDOG 0x28
+#define APCI1564_TIMER 0x48
+#define APCI1564_COUNTER1 0x0
+#define APCI1564_COUNTER2 0x20
+#define APCI1564_COUNTER3 0x40
+#define APCI1564_COUNTER4 0x60
+#define APCI1564_TCW_SYNC_ENABLEDISABLE 0
+#define APCI1564_TCW_RELOAD_VALUE 4
+#define APCI1564_TCW_TIMEBASE 8
+#define APCI1564_TCW_PROG 12
+#define APCI1564_TCW_TRIG_STATUS 16
+#define APCI1564_TCW_IRQ 20
+#define APCI1564_TCW_WARN_TIMEVAL 24
+#define APCI1564_TCW_WARN_TIMEBASE 28
+
+// Hardware Layer functions for Apci1564
+
+//DI
+// for di read
+INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//DO
+int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// TIMER
+// timer value is passed as u seconds
+INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// INTERRUPT
+static void v_APCI1564_Interrupt(int irq, void *d);
+
+// RESET
+INT i_APCI1564_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
new file mode 100644
index 000000000000..906d635da6b2
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
@@ -0,0 +1,780 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : API APCI1648 | Compiler : gcc |
+ | Module name : TTL.C | Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: S. Weber | Date : 25/05/2005 |
+ +-----------------------------------------------------------------------+
+ | Description : APCI-16XX TTL I/O module |
+ | |
+ | |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ |25.05.2005| S.Weber | Creation |
+ | | | |
+ +-----------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "hwdrv_apci16xx.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI16XX_InsnConfigInitTTLIO |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task APCI16XX_TTL_INIT (using defaults) : |
+| Configure the TTL I/O operating mode from all ports |
+| You must calling this function be |
+| for you call any other function witch access of TTL. |
+| APCI16XX_TTL_INITDIRECTION(user inputs for direction) |
++----------------------------------------------------------------------------+
+| Input Parameters : b_InitType = (BYTE) data[0]; |
+| b_Port0Mode = (BYTE) data[1]; |
+| b_Port1Mode = (BYTE) data[2]; |
+| b_Port2Mode = (BYTE) data[3]; |
+| b_Port3Mode = (BYTE) data[4]; |
+| ........ |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :>0: No error |
+| -1: Port 0 mode selection is wrong |
+| -2: Port 1 mode selection is wrong |
+| -3: Port 2 mode selection is wrong |
+| -4: Port 3 mode selection is wrong |
+| -X: Port X-1 mode selection is wrong |
+| .... |
+| -100 : Config command error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Command = 0;
+ BYTE b_Cpt = 0;
+ BYTE b_NumberOfPort =
+ (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /*******************/
+ /* Get the command */
+ /* **************** */
+
+ b_Command = (BYTE) data[0];
+
+ /********************/
+ /* Test the command */
+ /********************/
+
+ if ((b_Command == APCI16XX_TTL_INIT) ||
+ (b_Command == APCI16XX_TTL_INITDIRECTION) ||
+ (b_Command == APCI16XX_TTL_OUTPUTMEMORY)) {
+ /***************************************/
+ /* Test the initialisation buffer size */
+ /***************************************/
+
+ if ((b_Command == APCI16XX_TTL_INITDIRECTION)
+ && ((BYTE) (insn->n - 1) != b_NumberOfPort)) {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("\nBuffer size error");
+ i_ReturnValue = -101;
+ }
+
+ if ((b_Command == APCI16XX_TTL_OUTPUTMEMORY)
+ && ((BYTE) (insn->n) != 2)) {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("\nBuffer size error");
+ i_ReturnValue = -101;
+ }
+ } else {
+ /************************/
+ /* Config command error */
+ /************************/
+
+ printk("\nCommand selection error");
+ i_ReturnValue = -100;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("\nBuffer size error");
+ i_ReturnValue = -101;
+ }
+
+ /**************************************************************************/
+ /* Test if no error occur and APCI16XX_TTL_INITDIRECTION command selected */
+ /**************************************************************************/
+
+ if ((i_ReturnValue >= 0) && (b_Command == APCI16XX_TTL_INITDIRECTION)) {
+ memset(devpriv->ul_TTLPortConfiguration, 0,
+ sizeof(devpriv->ul_TTLPortConfiguration));
+
+ /*************************************/
+ /* Test the port direction selection */
+ /*************************************/
+
+ for (b_Cpt = 1;
+ (b_Cpt <= b_NumberOfPort) && (i_ReturnValue >= 0);
+ b_Cpt++) {
+ /**********************/
+ /* Test the direction */
+ /**********************/
+
+ if ((data[b_Cpt] != 0) && (data[b_Cpt] != 0xFF)) {
+ /************************/
+ /* Port direction error */
+ /************************/
+
+ printk("\nPort %d direction selection error",
+ (INT) b_Cpt);
+ i_ReturnValue = -(INT) b_Cpt;
+ }
+
+ /**************************/
+ /* Save the configuration */
+ /**************************/
+
+ devpriv->ul_TTLPortConfiguration[(b_Cpt - 1) / 4] =
+ devpriv->ul_TTLPortConfiguration[(b_Cpt -
+ 1) / 4] | (data[b_Cpt] << (8 * ((b_Cpt -
+ 1) % 4)));
+ }
+ }
+
+ /**************************/
+ /* Test if no error occur */
+ /**************************/
+
+ if (i_ReturnValue >= 0) {
+ /***********************************/
+ /* Test if TTL port initilaisation */
+ /***********************************/
+
+ if ((b_Command == APCI16XX_TTL_INIT)
+ || (b_Command == APCI16XX_TTL_INITDIRECTION)) {
+ /******************************/
+ /* Set all port configuration */
+ /******************************/
+
+ for (b_Cpt = 0; b_Cpt <= b_NumberOfPort; b_Cpt++) {
+ if ((b_Cpt % 4) == 0) {
+ /*************************/
+ /* Set the configuration */
+ /*************************/
+
+ outl(devpriv->
+ ul_TTLPortConfiguration[b_Cpt /
+ 4],
+ devpriv->iobase + 32 + b_Cpt);
+ }
+ }
+ }
+ }
+
+ /************************************************/
+ /* Test if output memory initialisation command */
+ /************************************************/
+
+ if (b_Command == APCI16XX_TTL_OUTPUTMEMORY) {
+ if (data[1]) {
+ devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+ } else {
+ devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+ }
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| INPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI16XX_InsnBitsReadTTLIO |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read the status from selected TTL digital input |
+| (b_InputChannel) |
++----------------------------------------------------------------------------+
+| Task : Read the status from digital input port |
+| (b_SelectedPort) |
++----------------------------------------------------------------------------+
+| Input Parameters : |
+| APCI16XX_TTL_READCHANNEL |
+| b_SelectedPort= CR_RANGE(insn->chanspec); |
+| b_InputChannel= CR_CHAN(insn->chanspec); |
+| b_ReadType = (BYTE) data[0]; |
+| |
+| APCI16XX_TTL_READPORT |
+| b_SelectedPort= CR_RANGE(insn->chanspec); |
+| b_ReadType = (BYTE) data[0]; |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] 0 : Channle is not active |
+| 1 : Channle is active |
++----------------------------------------------------------------------------+
+| Return Value : >0 : No error |
+| -100 : Config command error |
+| -101 : Data size error |
+| -102 : The selected TTL input port is wrong |
+| -103 : The selected TTL digital input is wrong |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Command = 0;
+ BYTE b_NumberOfPort =
+ (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+ BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
+ BYTE b_InputChannel = CR_CHAN(insn->chanspec);
+ BYTE *pb_Status;
+ DWORD dw_Status;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /*******************/
+ /* Get the command */
+ /* **************** */
+
+ b_Command = (BYTE) data[0];
+
+ /********************/
+ /* Test the command */
+ /********************/
+
+ if ((b_Command == APCI16XX_TTL_READCHANNEL)
+ || (b_Command == APCI16XX_TTL_READPORT)) {
+ /**************************/
+ /* Test the selected port */
+ /**************************/
+
+ if (b_SelectedPort < b_NumberOfPort) {
+ /**********************/
+ /* Test if input port */
+ /**********************/
+
+ if (((devpriv->ul_TTLPortConfiguration
+ [b_SelectedPort /
+ 4] >> (8 *
+ (b_SelectedPort
+ %
+ 4))) &
+ 0xFF) == 0) {
+ /***************************/
+ /* Test the channel number */
+ /***************************/
+
+ if ((b_Command ==
+ APCI16XX_TTL_READCHANNEL)
+ && (b_InputChannel > 7)) {
+ /*******************************************/
+ /* The selected TTL digital input is wrong */
+ /*******************************************/
+
+ printk("\nChannel selection error");
+ i_ReturnValue = -103;
+ }
+ } else {
+ /****************************************/
+ /* The selected TTL input port is wrong */
+ /****************************************/
+
+ printk("\nPort selection error");
+ i_ReturnValue = -102;
+ }
+ } else {
+ /****************************************/
+ /* The selected TTL input port is wrong */
+ /****************************************/
+
+ printk("\nPort selection error");
+ i_ReturnValue = -102;
+ }
+ } else {
+ /************************/
+ /* Config command error */
+ /************************/
+
+ printk("\nCommand selection error");
+ i_ReturnValue = -100;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("\nBuffer size error");
+ i_ReturnValue = -101;
+ }
+
+ /**************************/
+ /* Test if no error occur */
+ /**************************/
+
+ if (i_ReturnValue >= 0) {
+ pb_Status = (PBYTE) & data[0];
+
+ /*******************************/
+ /* Get the digital inpu status */
+ /*******************************/
+
+ dw_Status =
+ inl(devpriv->iobase + 8 + ((b_SelectedPort / 4) * 4));
+ dw_Status = (dw_Status >> (8 * (b_SelectedPort % 4))) & 0xFF;
+
+ /***********************/
+ /* Save the port value */
+ /***********************/
+
+ *pb_Status = (BYTE) dw_Status;
+
+ /***************************************/
+ /* Test if read channel status command */
+ /***************************************/
+
+ if (b_Command == APCI16XX_TTL_READCHANNEL) {
+ *pb_Status = (*pb_Status >> b_InputChannel) & 1;
+ }
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI16XX_InsnReadTTLIOAllPortValue |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read the status from all digital input ports |
++----------------------------------------------------------------------------+
+| Input Parameters : - |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Port 0 to 3 data |
+| data[1] : Port 4 to 7 data |
+| .... |
++----------------------------------------------------------------------------+
+| Return Value : 0: No error |
+| -100 : Read command error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_Command = (BYTE) CR_AREF(insn->chanspec);
+ INT i_ReturnValue = insn->n;
+ BYTE b_Cpt = 0;
+ BYTE b_NumberOfPort = 0;
+ unsigned int *pls_ReadData = data;
+
+ /********************/
+ /* Test the command */
+ /********************/
+
+ if ((b_Command == APCI16XX_TTL_READ_ALL_INPUTS)
+ || (b_Command == APCI16XX_TTL_READ_ALL_OUTPUTS)) {
+ /**********************************/
+ /* Get the number of 32-Bit ports */
+ /**********************************/
+
+ b_NumberOfPort =
+ (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 32);
+ if ((b_NumberOfPort * 32) <
+ devpriv->ps_BoardInfo->i_NbrTTLChannel) {
+ b_NumberOfPort = b_NumberOfPort + 1;
+ }
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= b_NumberOfPort) {
+ if (b_Command == APCI16XX_TTL_READ_ALL_INPUTS) {
+ /**************************/
+ /* Read all digital input */
+ /**************************/
+
+ for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
+ /************************/
+ /* Read the 32-Bit port */
+ /************************/
+
+ pls_ReadData[b_Cpt] =
+ inl(devpriv->iobase + 8 +
+ (b_Cpt * 4));
+
+ /**************************************/
+ /* Mask all channels used als outputs */
+ /**************************************/
+
+ pls_ReadData[b_Cpt] =
+ pls_ReadData[b_Cpt] &
+ (~devpriv->
+ ul_TTLPortConfiguration[b_Cpt]);
+ }
+ } else {
+ /****************************/
+ /* Read all digital outputs */
+ /****************************/
+
+ for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
+ /************************/
+ /* Read the 32-Bit port */
+ /************************/
+
+ pls_ReadData[b_Cpt] =
+ inl(devpriv->iobase + 20 +
+ (b_Cpt * 4));
+
+ /**************************************/
+ /* Mask all channels used als outputs */
+ /**************************************/
+
+ pls_ReadData[b_Cpt] =
+ pls_ReadData[b_Cpt] & devpriv->
+ ul_TTLPortConfiguration[b_Cpt];
+ }
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("\nBuffer size error");
+ i_ReturnValue = -101;
+ }
+ } else {
+ /*****************/
+ /* Command error */
+ /*****************/
+
+ printk("\nCommand selection error");
+ i_ReturnValue = -100;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| OUTPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI16XX_InsnBitsWriteTTLIO |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Set the state from selected TTL digital output |
+| (b_OutputChannel) |
++----------------------------------------------------------------------------+
+| Task : Set the state from digital output port |
+| (b_SelectedPort) |
++----------------------------------------------------------------------------+
+| Input Parameters : |
+| APCI16XX_TTL_WRITECHANNEL_ON | APCI16XX_TTL_WRITECHANNEL_OFF |
+| b_SelectedPort = CR_RANGE(insn->chanspec); |
+| b_OutputChannel= CR_CHAN(insn->chanspec); |
+| b_Command = (BYTE) data[0]; |
+| |
+| APCI16XX_TTL_WRITEPORT_ON | APCI16XX_TTL_WRITEPORT_OFF |
+| b_SelectedPort = CR_RANGE(insn->chanspec); |
+| b_Command = (BYTE) data[0]; |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : TTL output port 0 to 3 data |
+| data[1] : TTL output port 4 to 7 data |
+| .... |
++----------------------------------------------------------------------------+
+| Return Value : >0 : No error |
+| -100 : Command error |
+| -101 : Data size error |
+| -102 : The selected TTL output port is wrong |
+| -103 : The selected TTL digital output is wrong |
+| -104 : Output memory disabled |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Command = 0;
+ BYTE b_NumberOfPort =
+ (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
+ BYTE b_SelectedPort = CR_RANGE(insn->chanspec);
+ BYTE b_OutputChannel = CR_CHAN(insn->chanspec);
+ DWORD dw_Status = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /*******************/
+ /* Get the command */
+ /* **************** */
+
+ b_Command = (BYTE) data[0];
+
+ /********************/
+ /* Test the command */
+ /********************/
+
+ if ((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) ||
+ (b_Command == APCI16XX_TTL_WRITEPORT_ON) ||
+ (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) ||
+ (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) {
+ /**************************/
+ /* Test the selected port */
+ /**************************/
+
+ if (b_SelectedPort < b_NumberOfPort) {
+ /***********************/
+ /* Test if output port */
+ /***********************/
+
+ if (((devpriv->ul_TTLPortConfiguration
+ [b_SelectedPort /
+ 4] >> (8 *
+ (b_SelectedPort
+ %
+ 4))) &
+ 0xFF) == 0xFF) {
+ /***************************/
+ /* Test the channel number */
+ /***************************/
+
+ if (((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) || (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF)) && (b_OutputChannel > 7)) {
+ /********************************************/
+ /* The selected TTL digital output is wrong */
+ /********************************************/
+
+ printk("\nChannel selection error");
+ i_ReturnValue = -103;
+ }
+
+ if (((b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE)) {
+ /********************************************/
+ /* The selected TTL digital output is wrong */
+ /********************************************/
+
+ printk("\nOutput memory disabled");
+ i_ReturnValue = -104;
+ }
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (((b_Command == APCI16XX_TTL_WRITEPORT_ON) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (insn->n < 2)) {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("\nBuffer size error");
+ i_ReturnValue = -101;
+ }
+ } else {
+ /*****************************************/
+ /* The selected TTL output port is wrong */
+ /*****************************************/
+
+ printk("\nPort selection error %lX",
+ (unsigned long)devpriv->
+ ul_TTLPortConfiguration[0]);
+ i_ReturnValue = -102;
+ }
+ } else {
+ /****************************************/
+ /* The selected TTL output port is wrong */
+ /****************************************/
+
+ printk("\nPort selection error %d %d",
+ b_SelectedPort, b_NumberOfPort);
+ i_ReturnValue = -102;
+ }
+ } else {
+ /************************/
+ /* Config command error */
+ /************************/
+
+ printk("\nCommand selection error");
+ i_ReturnValue = -100;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("\nBuffer size error");
+ i_ReturnValue = -101;
+ }
+
+ /**************************/
+ /* Test if no error occur */
+ /**************************/
+
+ if (i_ReturnValue >= 0) {
+ /********************************/
+ /* Get the digital output state */
+ /********************************/
+
+ dw_Status =
+ inl(devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
+
+ /**********************************/
+ /* Test if output memory not used */
+ /**********************************/
+
+ if (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE) {
+ /*********************************/
+ /* Clear the selected port value */
+ /*********************************/
+
+ dw_Status =
+ dw_Status & (0xFFFFFFFFUL -
+ (0xFFUL << (8 * (b_SelectedPort % 4))));
+ }
+
+ /******************************/
+ /* Test if setting channel ON */
+ /******************************/
+
+ if (b_Command == APCI16XX_TTL_WRITECHANNEL_ON) {
+ dw_Status =
+ dw_Status | (1UL << ((8 * (b_SelectedPort %
+ 4)) + b_OutputChannel));
+ }
+
+ /***************************/
+ /* Test if setting port ON */
+ /***************************/
+
+ if (b_Command == APCI16XX_TTL_WRITEPORT_ON) {
+ dw_Status =
+ dw_Status | ((data[1] & 0xFF) << (8 *
+ (b_SelectedPort % 4)));
+ }
+
+ /*******************************/
+ /* Test if setting channel OFF */
+ /*******************************/
+
+ if (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) {
+ dw_Status =
+ dw_Status & (0xFFFFFFFFUL -
+ (1UL << ((8 * (b_SelectedPort % 4)) +
+ b_OutputChannel)));
+ }
+
+ /****************************/
+ /* Test if setting port OFF */
+ /****************************/
+
+ if (b_Command == APCI16XX_TTL_WRITEPORT_OFF) {
+ dw_Status =
+ dw_Status & (0xFFFFFFFFUL -
+ ((data[1] & 0xFF) << (8 * (b_SelectedPort %
+ 4))));
+ }
+
+ outl(dw_Status,
+ devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : - |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_Reset(struct comedi_device * dev)
+{
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
new file mode 100644
index 000000000000..5bf91e13a035
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
+#endif
+
+#ifndef ADDIDATA_ENABLE
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+#endif
+
+#define APCI16XX_TTL_INIT 0
+#define APCI16XX_TTL_INITDIRECTION 1
+#define APCI16XX_TTL_OUTPUTMEMORY 2
+
+#define APCI16XX_TTL_READCHANNEL 0
+#define APCI16XX_TTL_READPORT 1
+
+#define APCI16XX_TTL_WRITECHANNEL_ON 0
+#define APCI16XX_TTL_WRITECHANNEL_OFF 1
+#define APCI16XX_TTL_WRITEPORT_ON 2
+#define APCI16XX_TTL_WRITEPORT_OFF 3
+
+#define APCI16XX_TTL_READ_ALL_INPUTS 0
+#define APCI16XX_TTL_READ_ALL_OUTPUTS 1
+
+#ifdef __KERNEL__
+
+static const struct comedi_lrange range_apci16xx_ttl = { 12,
+ {BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1)}
+};
+
+/*
++----------------------------------------------------------------------------+
+| TTL INISIALISATION FUNCTION |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
+
+/*
++----------------------------------------------------------------------------+
+| TTL INPUT FUNCTION |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
+
+int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+/*
++----------------------------------------------------------------------------+
+| TTL OUTPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
+
+int i_APCI16XX_Reset(struct comedi_device *dev);
+#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
new file mode 100644
index 000000000000..31f55da39ea8
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
@@ -0,0 +1,460 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-2016 | Compiler : GCC |
+ | Module name : hwdrv_apci2016.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-2016 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci2016.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2016_ConfigDigitalOutput |
+| (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 |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 1 Digital Memory On |
+| 0 Digital Memory Off |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_ConfigDigitalOutput(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_APCI2016_WriteDigitalOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Writes port value To the selected port |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_NoOfChannels : No Of Channels To Write |
+| UINT *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_NoOfChannel;
+ UINT ui_Temp, ui_Temp1;
+ ui_NoOfChannel = CR_CHAN(insn->chanspec);
+ if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+ comedi_error(dev,
+ "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+ return -EINVAL;
+ } // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
+ if (devpriv->b_OutputMemoryStatus) {
+ ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP);
+ } // if (devpriv->b_OutputMemoryStatus )
+ else {
+ ui_Temp = 0;
+ } // else if (devpriv->b_OutputMemoryStatus )
+ if ((data[1] != 0) && (data[1] != 1)) {
+ comedi_error(dev,
+ "Invalid Data[1] value !!!, Data[1] should be 0 or 1\n");
+ return -EINVAL;
+ } // if ((data[1]!=0) && (data[1]!=1))
+
+ if (data[3] == 0) {
+ if (data[1] == 0) {
+ data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP);
+ } // if (data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+ case 2:
+ data[0] =
+ (data[0] << (2 *
+ data[2])) | ui_Temp;
+ break;
+ case 4:
+ data[0] =
+ (data[0] << (4 *
+ data[2])) | ui_Temp;
+ break;
+ case 8:
+ data[0] =
+ (data[0] << (8 *
+ data[2])) | ui_Temp;
+ break;
+ case 15:
+ data[0] = data[0] | ui_Temp;
+ break;
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //switch(ui_NoOfChannels)
+ outw(data[0],
+ devpriv->iobase + APCI2016_DIGITAL_OP);
+ } // if (data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } // else if (data[1]==1)
+ } // else if (data[1]==0)
+ } // if (data[3]==0)
+ else {
+ if (data[3] == 1) {
+ if (data[1] == 0) {
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
+ data[0] = data[0] & ui_Temp;
+ outw(data[0],
+ devpriv->iobase + APCI2016_DIGITAL_OP);
+ } // if (data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+ case 2:
+ data[0] = ~data[0] & 0x3;
+ ui_Temp1 = 3;
+ ui_Temp1 =
+ ui_Temp1 << 2 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (2 *
+ data
+ [2])) ^
+ 0xffff) & ui_Temp;
+ break;
+ case 4:
+ data[0] = ~data[0] & 0xf;
+ ui_Temp1 = 15;
+ ui_Temp1 =
+ ui_Temp1 << 4 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (4 *
+ data
+ [2])) ^
+ 0xffff) & ui_Temp;
+ break;
+ case 8:
+ data[0] = ~data[0] & 0xff;
+ ui_Temp1 = 255;
+ ui_Temp1 =
+ ui_Temp1 << 8 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (8 *
+ data
+ [2])) ^
+ 0xffff) & ui_Temp;
+ break;
+ case 15:
+ break;
+ default:
+ comedi_error(dev,
+ " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //switch(ui_NoOfChannels)
+ outw(data[0],
+ devpriv->iobase +
+ APCI2016_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==1);
+ else {
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } //if else data[3]==1)
+ } //if else data[3]==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2016_BitsDigitalOutput |
+| (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 |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_BitsDigitalOutput(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);
+ if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+ comedi_error(dev,
+ "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
+ return -EINVAL;
+ } // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15))
+ if ((data[0] != 0) && (data[0] != 1)) {
+ comedi_error(dev,
+ "Invalid Data[0] value !!!, Data[0] should be 0 or 1\n");
+ return -EINVAL;
+ } // if ((data[0]!=0) && (data[0]!=1))
+ ui_Temp = data[0];
+ *data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW);
+ if (ui_Temp == 0) {
+ *data = (*data >> ui_NoOfChannel) & 0x1;
+ } // if (ui_Temp==0)
+ else {
+ if (ui_Temp == 1) {
+ switch (ui_NoOfChannel) {
+ case 2:
+ *data = (*data >> (2 * data[1])) & 3;
+ break;
+
+ case 4:
+ *data = (*data >> (4 * data[1])) & 15;
+ break;
+
+ case 8:
+ *data = (*data >> (8 * data[1])) & 255;
+ break;
+
+ case 15:
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //switch(ui_NoOfChannel)
+ } // if (ui_Temp==1)
+ else {
+ printk("\nSpecified channel not supported \n");
+ } // else if (ui_Temp==1)
+ } // if (ui_Temp==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2016_ConfigWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Configures The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure |
+| struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ if (data[0] == 0) {
+ //Disable the watchdog
+ outw(0x0,
+ devpriv->i_IobaseAddon +
+ APCI2016_WATCHDOG_ENABLEDISABLE);
+ //Loading the Reload value
+ outw(data[1],
+ devpriv->i_IobaseAddon +
+ APCI2016_WATCHDOG_RELOAD_VALUE);
+ data[1] = data[1] >> 16;
+ outw(data[1],
+ devpriv->i_IobaseAddon +
+ APCI2016_WATCHDOG_RELOAD_VALUE + 2);
+ } else {
+ printk("\nThe input parameters are wrong\n");
+ }
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2016_StartStopWriteWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Start / Stop The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure |
+| struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ switch (data[0]) {
+ case 0: //stop the watchdog
+ outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE); //disable the watchdog
+ break;
+ case 1: //start the watchdog
+ outw(0x0001,
+ devpriv->i_IobaseAddon +
+ APCI2016_WATCHDOG_ENABLEDISABLE);
+ break;
+ case 2: //Software trigger
+ outw(0x0201,
+ devpriv->i_IobaseAddon +
+ APCI2016_WATCHDOG_ENABLEDISABLE);
+ break;
+ default:
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } // switch(data[0])
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2016_ReadWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure |
+| struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ udelay(5);
+ data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2016_Reset(struct comedi_device *dev) | |
++----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2016_Reset(struct comedi_device * dev)
+{
+ outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP); // Resets the digital output channels
+ outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
+ outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE);
+ outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2);
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
new file mode 100644
index 000000000000..9261aacd25f1
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+/********* Definitions for APCI-2016 card *****/
+
+#define APCI2016_BOARD_VENDOR_ID 0x15B8
+#define APCI2016_ADDRESS_RANGE 8
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI2016_DIGITAL_OP 0x04
+#define APCI2016_DIGITAL_OP_RW 4
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_WATCHDOG 2
+#define APCI2016_DIGITAL_OP_WATCHDOG 0
+#define APCI2016_WATCHDOG_ENABLEDISABLE 12
+#define APCI2016_WATCHDOG_RELOAD_VALUE 4
+#define APCI2016_WATCHDOG_STATUS 16
+
+// Hardware Layer functions for Apci2016
+
+//DO
+int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// TIMER
+// timer value is passed as u seconds
+
+int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// Interrupt functions.....
+
+// void v_APCI2016_Interrupt(int irq, void *d) ;
+
+ //void v_APCI2016_Interrupt(int irq, void *d);
+// RESET
+INT i_APCI2016_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
new file mode 100644
index 000000000000..1347bc388f3e
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
@@ -0,0 +1,579 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-2032 | Compiler : GCC |
+ | Module name : hwdrv_apci2032.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-2032 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+
+#include "hwdrv_apci2032.h"
+UINT ui_InterruptData, ui_Type;
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2032_ConfigDigitalOutput |
+| (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 |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[1] : 1 Enable VCC Interrupt |
+| 0 Disable VCC Interrupt |
+| data[2] : 1 Enable CC Interrupt |
+| 0 Disable CC Interrupt |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command = 0;
+ devpriv->tsk_Current = current;
+
+ if ((data[0] != 0) && (data[0] != 1)) {
+ comedi_error(dev,
+ "Not a valid Data !!! ,Data should be 1 or 0\n");
+ return -EINVAL;
+ } //if ( (data[0]!=0) && (data[0]!=1) )
+ if (data[0]) {
+ devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
+ } // if (data[0])
+ else {
+ devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
+ } //else if (data[0])
+
+ if (data[1] == ADDIDATA_ENABLE) {
+ ul_Command = ul_Command | 0x1;
+ } //if (data[1] == ADDIDATA_ENABLE)
+ else {
+ ul_Command = ul_Command & 0xFFFFFFFE;
+ } //elseif (data[1] == ADDIDATA_ENABLE)
+ if (data[2] == ADDIDATA_ENABLE) {
+ ul_Command = ul_Command | 0x2;
+ } //if (data[2] == ADDIDATA_ENABLE)
+ else {
+ ul_Command = ul_Command & 0xFFFFFFFD;
+ } //elseif (data[2] == ADDIDATA_ENABLE)
+ outl(ul_Command, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
+ ui_InterruptData = inl(devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2032_WriteDigitalOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Writes port value To the selected port |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT ui_NoOfChannels : No Of Channels To Write |
+| UINT *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Temp, ui_Temp1;
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+ if (devpriv->b_OutputMemoryStatus) {
+ ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
+
+ } //if(devpriv->b_OutputMemoryStatus )
+ else {
+ ui_Temp = 0;
+ } //if(devpriv->b_OutputMemoryStatus )
+ if (data[3] == 0) {
+ if (data[1] == 0) {
+ data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] =
+ (data[0] << (2 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 4:
+ data[0] =
+ (data[0] << (4 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 8:
+ data[0] =
+ (data[0] << (8 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 16:
+ data[0] =
+ (data[0] << (16 *
+ data[2])) | ui_Temp;
+ break;
+ case 31:
+ data[0] = data[0] | ui_Temp;
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outl(data[0],
+ devpriv->iobase + APCI2032_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==0)
+ else {
+ if (data[3] == 1) {
+ if (data[1] == 0) {
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ (data[0] << ui_NoOfChannel) ^
+ 0xffffffff;
+ data[0] = data[0] & ui_Temp;
+ outl(data[0],
+ devpriv->iobase + APCI2032_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] = ~data[0] & 0x3;
+ ui_Temp1 = 3;
+ ui_Temp1 =
+ ui_Temp1 << 2 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (2 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+
+ case 4:
+ data[0] = ~data[0] & 0xf;
+ ui_Temp1 = 15;
+ ui_Temp1 =
+ ui_Temp1 << 4 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (4 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+
+ case 8:
+ data[0] = ~data[0] & 0xff;
+ ui_Temp1 = 255;
+ ui_Temp1 =
+ ui_Temp1 << 8 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (8 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+
+ case 16:
+ data[0] = ~data[0] & 0xffff;
+ ui_Temp1 = 65535;
+ ui_Temp1 =
+ ui_Temp1 << 16 *
+ data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (16 *
+ data
+ [2])) ^
+ 0xffffffff) & ui_Temp;
+ break;
+
+ case 31:
+ break;
+ default:
+ comedi_error(dev,
+ " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outl(data[0],
+ devpriv->iobase +
+ APCI2032_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==1);
+ else {
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } //if else data[3]==1)
+ } //if else data[3]==0)
+ return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2032_ReadDigitalOutput |
+| (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 |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2032_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->iobase + APCI2032_DIGITAL_OP_RW);
+ if (ui_Temp == 0) {
+ *data = (*data >> ui_NoOfChannel) & 0x1;
+ } //if (ui_Temp==0)
+ else {
+ if (ui_Temp == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ *data = (*data >> (2 * data[1])) & 3;
+ break;
+
+ case 4:
+ *data = (*data >> (4 * data[1])) & 15;
+ break;
+
+ case 8:
+ *data = (*data >> (8 * data[1])) & 255;
+ break;
+
+ case 16:
+ *data = (*data >> (16 * data[1])) & 65535;
+ break;
+
+ case 31:
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+ } //if (ui_Temp==1)
+ else {
+ printk("\nSpecified channel not supported \n");
+ } //elseif (ui_Temp==1)
+ }
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI2032_ConfigWatchdog(comedi_device
+ *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
+| |
++----------------------------------------------------------------------------+
+| Task : Configures The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ if (data[0] == 0) {
+ //Disable the watchdog
+ outl(0x0,
+ devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ APCI2032_TCW_PROG);
+ //Loading the Reload value
+ outl(data[1],
+ devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ APCI2032_TCW_RELOAD_VALUE);
+ } else {
+ printk("\nThe input parameters are wrong\n");
+ return -EINVAL;
+ }
+
+ return insn->n;
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : int i_APCI2032_StartStopWriteWatchdog |
+ | (struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data); |
+ +----------------------------------------------------------------------------+
+ | Task : Start / Stop The Watchdog |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : struct comedi_device *dev : Driver handle |
+ | struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+ | unsigned int *data : Data Pointer to read status |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -- |
+ +----------------------------------------------------------------------------+
+ | Return Value : TRUE : No error occur |
+ | : FALSE : Error occur. Return the error |
+ | |
+ +----------------------------------------------------------------------------+
+ */
+
+int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ switch (data[0]) {
+ case 0: //stop the watchdog
+ outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); //disable the watchdog
+ break;
+ case 1: //start the watchdog
+ outl(0x0001,
+ devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ APCI2032_TCW_PROG);
+ break;
+ case 2: //Software trigger
+ outl(0x0201,
+ devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ APCI2032_TCW_PROG);
+ break;
+ default:
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ }
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2032_ReadWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data); |
++----------------------------------------------------------------------------+
+| Task : Read The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2032_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ data[0] =
+ inl(devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
+ APCI2032_TCW_TRIG_STATUS) & 0x1;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : void v_APCI2032_Interrupt |
+| (int irq , void *d) |
++----------------------------------------------------------------------------+
+| Task : Writes port value To the selected port |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq : irq number |
+| void *d : void pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+void v_APCI2032_Interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ unsigned int ui_DO;
+
+ ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1; //Check if VCC OR CC interrupt has occured.
+
+ if (ui_DO == 0) {
+ printk("\nInterrupt from unKnown source\n");
+ } // if(ui_DO==0)
+ if (ui_DO) {
+ // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt.
+ ui_Type =
+ inl(devpriv->iobase +
+ APCI2032_DIGITAL_OP_INTERRUPT_STATUS) & 0x3;
+ outl(0x0,
+ devpriv->iobase + APCI2032_DIGITAL_OP +
+ APCI2032_DIGITAL_OP_INTERRUPT);
+ if (ui_Type == 1) {
+ //Sends signal to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+ } // if (ui_Type==1)
+ else {
+ if (ui_Type == 2) {
+ // Sends signal to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+ } //if (ui_Type==2)
+ } //else if (ui_Type==1)
+ } //if(ui_DO)
+
+ return;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2032_ReadInterruptStatus |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task :Reads the interrupt status register |
++----------------------------------------------------------------------------+
+| Input Parameters : |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ *data = ui_Type;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2032_Reset(struct comedi_device *dev) |
+| |
++----------------------------------------------------------------------------+
+| Task :Resets the registers of the card |
++----------------------------------------------------------------------------+
+| Input Parameters : |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2032_Reset(struct comedi_device * dev)
+{
+ devpriv->b_DigitalOutputRegister = 0;
+ ui_Type = 0;
+ outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP); //Resets the output channels
+ outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT); //Disables the interrupt.
+ outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); //disable the watchdog
+ outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE); //reload=0
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
new file mode 100644
index 000000000000..55002e0288b5
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+/********* Definitions for APCI-2032 card *****/
+
+// Card Specific information
+#define APCI2032_BOARD_VENDOR_ID 0x15B8
+#define APCI2032_ADDRESS_RANGE 63
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI2032_DIGITAL_OP 0
+#define APCI2032_DIGITAL_OP_RW 0
+#define APCI2032_DIGITAL_OP_INTERRUPT 4
+#define APCI2032_DIGITAL_OP_IRQ 12
+
+//Digital Output Interrupt Status
+#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS 8
+
+//Digital Output Interrupt Enable Disable.
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD
+
+//ADDIDATA Enable Disable
+
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define ADDIDATA_WATCHDOG 2
+#define APCI2032_DIGITAL_OP_WATCHDOG 16
+#define APCI2032_TCW_RELOAD_VALUE 4
+#define APCI2032_TCW_TIMEBASE 8
+#define APCI2032_TCW_PROG 12
+#define APCI2032_TCW_TRIG_STATUS 16
+#define APCI2032_TCW_IRQ 20
+
+// Hardware Layer functions for Apci2032
+
+//DO
+int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// TIMER
+// timer value is passed as u seconds
+INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// Interrupt functions.....
+
+void v_APCI2032_Interrupt(int irq, void *d);
+
+//Reset functions
+int i_APCI2032_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
new file mode 100644
index 000000000000..947e18ef3ab3
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
@@ -0,0 +1,549 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-2200 | Compiler : GCC |
+ | Module name : hwdrv_apci2200.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-2200 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci2200.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_Read1DigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the digital input |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_TmpValue = 0;
+ UINT ui_Channel;
+ ui_Channel = CR_CHAN(insn->chanspec);
+ if (ui_Channel >= 0 && ui_Channel <= 7) {
+ ui_TmpValue = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+ *data = (ui_TmpValue >> ui_Channel) & 0x1;
+ } //if(ui_Channel >= 0 && ui_Channel <=7)
+ else {
+ printk("\nThe specified channel does not exist\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ } //else if(ui_Channel >= 0 && ui_Channel <=7)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_ReadMoreDigitalInput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Return the status of the Requested digital inputs |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ UINT ui_PortValue = data[0];
+ UINT ui_Mask = 0;
+ UINT ui_NoOfChannels;
+
+ ui_NoOfChannels = CR_CHAN(insn->chanspec);
+
+ *data = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
+ switch (ui_NoOfChannels) {
+ case 2:
+ ui_Mask = 3;
+ *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
+ break;
+ case 4:
+ ui_Mask = 15;
+ *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
+ break;
+ case 7:
+ break;
+
+ default:
+ printk("\nWrong parameters\n");
+ return -EINVAL; // "sorry channel spec wrong "
+ break;
+ } //switch(ui_NoOfChannels)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_ConfigDigitalOutput (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 |
+| unsigned int *data : Data Pointer contains |
+| configuration parameters as below |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| data[0] :1:Memory on |
+| 0:Memory off |
+| |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ devpriv->b_OutputMemoryStatus = data[0];
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_WriteDigitalOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Writes port value To the selected port |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Temp, ui_Temp1;
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+ if (devpriv->b_OutputMemoryStatus) {
+ ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+
+ } //if(devpriv->b_OutputMemoryStatus )
+ else {
+ ui_Temp = 0;
+ } //if(devpriv->b_OutputMemoryStatus )
+ if (data[3] == 0) {
+ if (data[1] == 0) {
+ data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] =
+ (data[0] << (2 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 4:
+ data[0] =
+ (data[0] << (4 *
+ data[2])) | ui_Temp;
+ break;
+
+ case 8:
+ data[0] =
+ (data[0] << (8 *
+ data[2])) | ui_Temp;
+ break;
+ case 15:
+ data[0] = data[0] | ui_Temp;
+ break;
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outw(data[0],
+ devpriv->iobase + APCI2200_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==0)
+ else {
+ if (data[3] == 1) {
+ if (data[1] == 0) {
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
+ data[0] = data[0] & ui_Temp;
+ outw(data[0],
+ devpriv->iobase + APCI2200_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ data[0] = ~data[0] & 0x3;
+ ui_Temp1 = 3;
+ ui_Temp1 =
+ ui_Temp1 << 2 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (2 *
+ data
+ [2])) ^
+ 0xffff) & ui_Temp;
+ break;
+
+ case 4:
+ data[0] = ~data[0] & 0xf;
+ ui_Temp1 = 15;
+ ui_Temp1 =
+ ui_Temp1 << 4 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (4 *
+ data
+ [2])) ^
+ 0xffff) & ui_Temp;
+ break;
+
+ case 8:
+ data[0] = ~data[0] & 0xff;
+ ui_Temp1 = 255;
+ ui_Temp1 =
+ ui_Temp1 << 8 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (8 *
+ data
+ [2])) ^
+ 0xffff) & ui_Temp;
+ break;
+ case 15:
+ break;
+
+ default:
+ comedi_error(dev,
+ " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+
+ outw(data[0],
+ devpriv->iobase +
+ APCI2200_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==1);
+ else {
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } //if else data[3]==1)
+ } //if else data[3]==0)
+ return (insn->n);;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_ReadDigitalOutput |
+| (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 |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ UINT ui_Temp;
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+ ui_Temp = data[0];
+ *data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+ if (ui_Temp == 0) {
+ *data = (*data >> ui_NoOfChannel) & 0x1;
+ } //if(ui_Temp==0)
+ else {
+ if (ui_Temp == 1) {
+ switch (ui_NoOfChannel) {
+
+ case 2:
+ *data = (*data >> (2 * data[1])) & 3;
+ break;
+
+ case 4:
+ *data = (*data >> (4 * data[1])) & 15;
+ break;
+
+ case 8:
+ *data = (*data >> (8 * data[1])) & 255;
+ break;
+
+ case 15:
+ break;
+
+ default:
+ comedi_error(dev, " chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+
+ } //switch(ui_NoOfChannels)
+ } //if(ui_Temp==1)
+ else {
+ printk("\nSpecified channel not supported \n");
+ } //elseif(ui_Temp==1)
+ } //elseif(ui_Temp==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : Configures The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ if (data[0] == 0) {
+ //Disable the watchdog
+ outw(0x0,
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_ENABLEDISABLE);
+ //Loading the Reload value
+ outw(data[1],
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_RELOAD_VALUE);
+ data[1] = data[1] >> 16;
+ outw(data[1],
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_RELOAD_VALUE + 2);
+ } //if(data[0]==0)
+ else {
+ printk("\nThe input parameters are wrong\n");
+ return -EINVAL;
+ } //elseif(data[0]==0)
+
+ return insn->n;
+}
+
+ /*
+ +----------------------------------------------------------------------------+
+ | Function Name : int i_APCI2200_StartStopWriteWatchdog |
+ | (struct comedi_device *dev,struct comedi_subdevice *s,
+ struct comedi_insn *insn,unsigned int *data); |
+ +----------------------------------------------------------------------------+
+ | Task : Start / Stop The Watchdog |
+ +----------------------------------------------------------------------------+
+ | Input Parameters : struct comedi_device *dev : Driver handle |
+ | struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+ | unsigned int *data : Data Pointer to read status |
+ +----------------------------------------------------------------------------+
+ | Output Parameters : -- |
+ +----------------------------------------------------------------------------+
+ | Return Value : TRUE : No error occur |
+ | : FALSE : Error occur. Return the error |
+ | |
+ +----------------------------------------------------------------------------+
+ */
+
+int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ switch (data[0]) {
+ case 0: //stop the watchdog
+ outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); //disable the watchdog
+ break;
+ case 1: //start the watchdog
+ outw(0x0001,
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_ENABLEDISABLE);
+ break;
+ case 2: //Software trigger
+ outw(0x0201,
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_ENABLEDISABLE);
+ break;
+ default:
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } // switch(data[0])
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_ReadWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
+ unsigned int *data); |
++----------------------------------------------------------------------------+
+| Task : Read The Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| struct comedi_subdevice *s, :pointer to subdevice structure
+ struct comedi_insn *insn :pointer to insn structure |
+| unsigned int *data : Data Pointer to read status |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ data[0] =
+ inw(devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_STATUS) & 0x1;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | |
++----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI2200_Reset(struct comedi_device * dev)
+{
+ outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP); //RESETS THE DIGITAL OUTPUTS
+ outw(0x0,
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_ENABLEDISABLE);
+ outw(0x0,
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_RELOAD_VALUE);
+ outw(0x0,
+ devpriv->iobase + APCI2200_WATCHDOG +
+ APCI2200_WATCHDOG_RELOAD_VALUE + 2);
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
new file mode 100644
index 000000000000..0a115b4c44c9
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+/********* Definitions for APCI-2200 card *****/
+
+// Card Specific information
+#define APCI2200_BOARD_VENDOR_ID 0x15b8
+#define APCI2200_ADDRESS_RANGE 64
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI2200_DIGITAL_OP 4
+#define APCI2200_DIGITAL_IP 0
+
+// TIMER COUNTER WATCHDOG DEFINES
+
+#define APCI2200_WATCHDOG 0x08
+#define APCI2200_WATCHDOG_ENABLEDISABLE 12
+#define APCI2200_WATCHDOG_RELOAD_VALUE 4
+#define APCI2200_WATCHDOG_STATUS 16
+
+// Hardware Layer functions for Apci2200
+
+//Digital Input
+INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//Digital Output
+int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// TIMER
+int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//reset
+INT i_APCI2200_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
new file mode 100644
index 000000000000..68eb8dfd5139
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -0,0 +1,2697 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : APCI-3120 | Compiler : GCC |
+ | Module name : hwdrv_apci3120.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-----------------------------------------------------------------------+
+ | Description :APCI3120 Module. Hardware abstraction Layer for APCI3120|
+ +-----------------------------------------------------------------------+
+ | UPDATE'S |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+#include "hwdrv_apci3120.h"
+static UINT ui_Temp = 0;
+
+// FUNCTION DEFINITIONS
+
+/*
++----------------------------------------------------------------------------+
+| ANALOG INPUT SUBDEVICE |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev,|
+| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : Calls card specific function |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT i;
+
+ if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
+ return -1;
+
+ // Check for Conversion time to be added ??
+ devpriv->ui_EocEosConversionTime = data[2];
+
+ if (data[0] == APCI3120_EOS_MODE) {
+
+ //Test the number of the channel
+ for (i = 0; i < data[3]; i++) {
+
+ if (CR_CHAN(data[4 + i]) >= this_board->i_NbrAiChannel) {
+ printk("bad channel list\n");
+ return -2;
+ }
+ }
+
+ devpriv->b_InterruptMode = APCI3120_EOS_MODE;
+
+ if (data[1]) {
+ devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+ } else
+ devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ // Copy channel list and Range List to devpriv
+
+ devpriv->ui_AiNbrofChannels = data[3];
+ for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) {
+ devpriv->ui_AiChannelList[i] = data[4 + i];
+ }
+
+ } else // EOC
+ {
+ devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+ if (data[1]) {
+ devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+ } else {
+ devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ }
+ }
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, |
+| struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : card specific function |
+| Reads analog input in synchronous mode |
+| EOC and EOS is selected as per configured |
+| if no conversion time is set uses default conversion |
+| time 10 microsec. |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ USHORT us_ConvertTiming, us_TmpValue, i;
+ BYTE b_Tmp;
+
+ // fix convertion time to 10 us
+ if (!devpriv->ui_EocEosConversionTime) {
+ printk("No timer0 Value using 10 us\n");
+ us_ConvertTiming = 10;
+ } else
+ us_ConvertTiming = (USHORT) (devpriv->ui_EocEosConversionTime / 1000); // nano to useconds
+
+ // this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]);
+
+ // Clear software registers
+ devpriv->b_TimerSelectMode = 0;
+ devpriv->b_ModeSelectRegister = 0;
+ devpriv->us_OutputRegister = 0;
+// devpriv->b_DigitalOutputRegister=0;
+
+ if (insn->unused[0] == 222) // second insn read
+ {
+
+ for (i = 0; i < insn->n; i++) {
+ data[i] = devpriv->ui_AiReadData[i];
+ }
+
+ } else {
+ devpriv->tsk_Current = current; // Save the current process task structure
+ //Testing if board have the new Quartz and calculate the time value
+ //to set in the timer
+
+ us_TmpValue =
+ (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+ //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+ if ((us_TmpValue & 0x00B0) == 0x00B0
+ || !strcmp(this_board->pc_DriverName, "apci3001")) {
+ us_ConvertTiming = (us_ConvertTiming * 2) - 2;
+ } else {
+ us_ConvertTiming =
+ ((us_ConvertTiming * 12926) / 10000) - 1;
+ }
+
+ us_TmpValue = (USHORT) devpriv->b_InterruptMode;
+
+ switch (us_TmpValue) {
+
+ case APCI3120_EOC_MODE:
+
+ // Testing the interrupt flag and set the EOC bit
+ // Clears the FIFO
+ inw(devpriv->iobase + APCI3120_RESET_FIFO);
+
+ // Initialize the sequence array
+
+ //if (!i_APCI3120_SetupChannelList(dev,s,1,chanlist,0)) return -EINVAL;
+
+ if (!i_APCI3120_SetupChannelList(dev, s, 1,
+ &insn->chanspec, 0))
+ return -EINVAL;
+
+ //Initialize Timer 0 mode 4
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0xFC) |
+ APCI3120_TIMER_0_MODE_4;
+ outb(devpriv->b_TimerSelectMode,
+ devpriv->iobase + APCI3120_TIMER_CRT1);
+
+ // Reset the scan bit and Disables the EOS, DMA, EOC interrupt
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_SCAN;
+
+ if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+
+ //Disables the EOS,DMA and enables the EOC interrupt
+ devpriv->b_ModeSelectRegister =
+ (devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_EOS_INT) |
+ APCI3120_ENABLE_EOC_INT;
+ inw(devpriv->iobase);
+
+ } else {
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
+ }
+
+ outb(devpriv->b_ModeSelectRegister,
+ devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ // Sets gate 0
+ devpriv->us_OutputRegister =
+ (devpriv->
+ us_OutputRegister & APCI3120_CLEAR_PA_PR) |
+ APCI3120_ENABLE_TIMER0;
+ outw(devpriv->us_OutputRegister,
+ devpriv->iobase + APCI3120_WR_ADDRESS);
+
+ // Select Timer 0
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_0_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+ //Set the convertion time
+ outw(us_ConvertTiming,
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ us_TmpValue =
+ (USHORT) inw(dev->iobase + APCI3120_RD_STATUS);
+
+ if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
+
+ do {
+ // Waiting for the end of conversion
+ us_TmpValue =
+ inw(devpriv->iobase +
+ APCI3120_RD_STATUS);
+ } while ((us_TmpValue & APCI3120_EOC) ==
+ APCI3120_EOC);
+
+ //Read the result in FIFO and put it in insn data pointer
+ us_TmpValue = inw(devpriv->iobase + 0);
+ *data = us_TmpValue;
+
+ inw(devpriv->iobase + APCI3120_RESET_FIFO);
+ }
+
+ break;
+
+ case APCI3120_EOS_MODE:
+
+ inw(devpriv->iobase);
+ // Clears the FIFO
+ inw(devpriv->iobase + APCI3120_RESET_FIFO);
+ // clear PA PR and disable timer 0
+
+ devpriv->us_OutputRegister =
+ (devpriv->
+ us_OutputRegister & APCI3120_CLEAR_PA_PR) |
+ APCI3120_DISABLE_TIMER0;
+
+ outw(devpriv->us_OutputRegister,
+ devpriv->iobase + APCI3120_WR_ADDRESS);
+
+ if (!i_APCI3120_SetupChannelList(dev, s,
+ devpriv->ui_AiNbrofChannels,
+ devpriv->ui_AiChannelList, 0))
+ return -EINVAL;
+
+ //Initialize Timer 0 mode 2
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0xFC) |
+ APCI3120_TIMER_0_MODE_2;
+ outb(devpriv->b_TimerSelectMode,
+ devpriv->iobase + APCI3120_TIMER_CRT1);
+
+ //Select Timer 0
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_0_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+ //Set the convertion time
+ outw(us_ConvertTiming,
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ //Set the scan bit
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister | APCI3120_ENABLE_SCAN;
+ outb(devpriv->b_ModeSelectRegister,
+ devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ //If Interrupt function is loaded
+ if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+ //Disables the EOC,DMA and enables the EOS interrupt
+ devpriv->b_ModeSelectRegister =
+ (devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_EOC_INT) |
+ APCI3120_ENABLE_EOS_INT;
+ inw(devpriv->iobase);
+
+ } else
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
+
+ outb(devpriv->b_ModeSelectRegister,
+ devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+ //Sets gate 0
+
+ devpriv->us_OutputRegister =
+ devpriv->
+ us_OutputRegister | APCI3120_ENABLE_TIMER0;
+ outw(devpriv->us_OutputRegister,
+ devpriv->iobase + APCI3120_WR_ADDRESS);
+
+ //Start conversion
+ outw(0, devpriv->iobase + APCI3120_START_CONVERSION);
+
+ //Waiting of end of convertion if interrupt is not installed
+ if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
+ //Waiting the end of convertion
+ do {
+ us_TmpValue =
+ inw(devpriv->iobase +
+ APCI3120_RD_STATUS);
+ }
+ while ((us_TmpValue & APCI3120_EOS) !=
+ APCI3120_EOS);
+
+ for (i = 0; i < devpriv->ui_AiNbrofChannels;
+ i++) {
+ //Read the result in FIFO and write them in shared memory
+ us_TmpValue = inw(devpriv->iobase);
+ data[i] = (UINT) us_TmpValue;
+ }
+
+ devpriv->b_InterruptMode = APCI3120_EOC_MODE; // Restore defaults.
+ }
+ break;
+
+ default:
+ printk("inputs wrong\n");
+
+ }
+ devpriv->ui_EocEosConversionTime = 0; // re initializing the variable;
+ }
+
+ return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev,|
+| struct comedi_subdevice *s)|
+| |
++----------------------------------------------------------------------------+
+| Task : Stops Cyclic acquisition |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| |
++----------------------------------------------------------------------------+
+| Return Value :0 |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s)
+{
+ // Disable A2P Fifo write and AMWEN signal
+ outw(0, devpriv->i_IobaseAddon + 4);
+
+ //Disable Bus Master ADD ON
+ outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+ outw(0, devpriv->i_IobaseAddon + 2);
+ outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(0, devpriv->i_IobaseAddon + 2);
+
+ //Disable BUS Master PCI
+ outl(0, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+
+ //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR)&(~AINT_WRITE_COMPL), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); // stop amcc irqs
+ //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR)&(~EN_A2P_TRANSFERS), devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR); // stop DMA
+
+ //Disable ext trigger
+ i_APCI3120_ExttrigDisable(dev);
+
+ devpriv->us_OutputRegister = 0;
+ //stop counters
+ outw(devpriv->
+ us_OutputRegister & APCI3120_DISABLE_TIMER0 &
+ APCI3120_DISABLE_TIMER1, dev->iobase + APCI3120_WR_ADDRESS);
+
+ outw(APCI3120_DISABLE_ALL_TIMER, dev->iobase + APCI3120_WR_ADDRESS);
+
+ //DISABLE_ALL_INTERRUPT
+ outb(APCI3120_DISABLE_ALL_INTERRUPT,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ //Flush FIFO
+ inb(dev->iobase + APCI3120_RESET_FIFO);
+ inw(dev->iobase + APCI3120_RD_STATUS);
+ devpriv->ui_AiActualScan = 0;
+ devpriv->ui_AiActualScanPosition = 0;
+ s->async->cur_chan = 0;
+ devpriv->ui_AiBufferPtr = 0;
+ devpriv->b_AiContinuous = 0;
+ devpriv->ui_DmaActualBuffer = 0;
+
+ devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+ devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+ devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ i_APCI3120_Reset(dev);
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_CommandTestAnalogInput(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_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_cmd * cmd)
+{
+ int err = 0;
+ int tmp; // divisor1,divisor2;
+
+ // step 1: make sure trigger sources are trivially valid
+
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW | TRIG_EXT;
+ if (!cmd->start_src || tmp != cmd->start_src)
+ err++;
+
+ tmp = cmd->scan_begin_src;
+ cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+ err++;
+
+ tmp = cmd->convert_src;
+ cmd->convert_src &= TRIG_TIMER;
+ if (!cmd->convert_src || tmp != cmd->convert_src)
+ err++;
+
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+ err++;
+
+ tmp = cmd->stop_src;
+ cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+ if (!cmd->stop_src || tmp != cmd->stop_src)
+ err++;
+
+ if (err)
+ return 1;
+
+ //step 2: make sure trigger sources are unique and mutually compatible
+
+ if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
+ err++;
+ }
+
+ if (cmd->scan_begin_src != TRIG_TIMER &&
+ cmd->scan_begin_src != TRIG_FOLLOW)
+ err++;
+
+ if (cmd->convert_src != TRIG_TIMER)
+ err++;
+
+ if (cmd->scan_end_src != TRIG_COUNT) {
+ cmd->scan_end_src = TRIG_COUNT;
+ err++;
+ }
+
+ if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
+ err++;
+
+ if (err)
+ return 2;
+
+ // step 3: make sure arguments are trivially compatible
+
+ if (cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+
+ if (cmd->scan_begin_src == TRIG_TIMER) // Test Delay timing
+ {
+ if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) {
+ cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs;
+ err++;
+ }
+ }
+
+ if (cmd->convert_src == TRIG_TIMER) // Test Acquisition timing
+ {
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ if ((cmd->convert_arg)
+ && (cmd->convert_arg <
+ this_board->ui_MinAcquisitiontimeNs)) {
+ cmd->convert_arg =
+ this_board->ui_MinAcquisitiontimeNs;
+ err++;
+ }
+ } else {
+ if (cmd->convert_arg <
+ this_board->ui_MinAcquisitiontimeNs) {
+ cmd->convert_arg =
+ this_board->ui_MinAcquisitiontimeNs;
+ err++;
+
+ }
+ }
+ }
+
+ if (!cmd->chanlist_len) {
+ cmd->chanlist_len = 1;
+ err++;
+ }
+ if (cmd->chanlist_len > this_board->i_AiChannelList) {
+ cmd->chanlist_len = this_board->i_AiChannelList;
+ err++;
+ }
+ if (cmd->stop_src == TRIG_COUNT) {
+ if (!cmd->stop_arg) {
+ cmd->stop_arg = 1;
+ err++;
+ }
+ } else { // TRIG_NONE
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+ }
+
+ if (err)
+ return 3;
+
+ // step 4: fix up any arguments
+
+ if (cmd->convert_src == TRIG_TIMER) {
+
+ if (cmd->scan_begin_src == TRIG_TIMER &&
+ cmd->scan_begin_arg <
+ cmd->convert_arg * cmd->scan_end_arg) {
+ cmd->scan_begin_arg =
+ cmd->convert_arg * cmd->scan_end_arg;
+ err++;
+ }
+ }
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : int i_APCI3120_CommandAnalogInput(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_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s)
+{
+ struct comedi_cmd *cmd = &s->async->cmd;
+
+ //loading private structure with cmd structure inputs
+ devpriv->ui_AiFlags = cmd->flags;
+ devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
+ devpriv->ui_AiScanLength = cmd->scan_end_arg;
+ devpriv->pui_AiChannelList = cmd->chanlist;
+
+ //UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data;
+ devpriv->AiData = s->async->prealloc_buf;
+ //UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len;
+ devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ devpriv->ui_AiNbrofScans = cmd->stop_arg;
+ } else {
+ devpriv->ui_AiNbrofScans = 0;
+ }
+
+ devpriv->ui_AiTimer0 = 0; // variables changed to timer0,timer1
+ devpriv->ui_AiTimer1 = 0;
+ if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1))
+ devpriv->b_AiContinuous = 1; // user want neverending analog acquisition
+ // stopped using cancel
+
+ if (cmd->start_src == TRIG_EXT)
+ devpriv->b_ExttrigEnable = APCI3120_ENABLE;
+ else
+ devpriv->b_ExttrigEnable = APCI3120_DISABLE;
+
+ if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ // mode 1 or 3
+ if (cmd->convert_src == TRIG_TIMER) {
+ // mode 1
+
+ devpriv->ui_AiTimer0 = cmd->convert_arg; // timer constant in nano seconds
+ //return this_board->i_hwdrv_CommandAnalogInput(1,dev,s);
+ return i_APCI3120_CyclicAnalogInput(1, dev, s);
+ }
+
+ }
+ if ((cmd->scan_begin_src == TRIG_TIMER)
+ && (cmd->convert_src == TRIG_TIMER)) {
+ // mode 2
+ devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
+ devpriv->ui_AiTimer0 = cmd->convert_arg; // variable changed timer2 to timer0
+ //return this_board->i_hwdrv_CommandAnalogInput(2,dev,s);
+ return i_APCI3120_CyclicAnalogInput(2, dev, s);
+ }
+ return -1;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : int i_APCI3120_CyclicAnalogInput(int mode, |
+| struct comedi_device * dev,struct comedi_subdevice * s) |
++----------------------------------------------------------------------------+
+| Task : This is used for analog input cyclic acquisition |
+| Performs the command operations. |
+| If DMA is configured does DMA initialization |
+| otherwise does the acquisition with EOS interrupt. |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev,
+ struct comedi_subdevice * s)
+{
+ BYTE b_Tmp;
+ UINT ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
+ 0, dmalen1 = 0, ui_TimerValue2 =
+ 0, ui_TimerValue0, ui_ConvertTiming;
+ USHORT us_TmpValue;
+
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ //devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE;
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ /*******************/
+ /* Resets the FIFO */
+ /*******************/
+ inb(dev->iobase + APCI3120_RESET_FIFO);
+
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ //inw(dev->iobase+APCI3120_RD_STATUS);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ /***************************/
+ /* Acquisition initialized */
+ /***************************/
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ devpriv->b_AiCyclicAcquisition = APCI3120_ENABLE;
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ // clear software registers
+ devpriv->b_TimerSelectMode = 0;
+ devpriv->us_OutputRegister = 0;
+ devpriv->b_ModeSelectRegister = 0;
+ //devpriv->b_DigitalOutputRegister=0;
+
+ //COMMENT JK 07.05.04: Followings calls are in i_APCI3120_StartAnalogInputAcquisition
+
+ /****************************/
+ /* Clear Timer Write TC INT */
+ /****************************/
+ outl(APCI3120_CLEAR_WRITE_TC_INT,
+ devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR);
+
+ /************************************/
+ /* Clears the timer status register */
+ /************************************/
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ //inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER);
+ inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ /**************************/
+ /* Disables All Timer */
+ /* Sets PR and PA to 0 */
+ /**************************/
+ devpriv->us_OutputRegister = devpriv->us_OutputRegister &
+ APCI3120_DISABLE_TIMER0 &
+ APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR;
+
+ outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
+ /*******************/
+ /* Resets the FIFO */
+ /*******************/
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ inb(devpriv->iobase + APCI3120_RESET_FIFO);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ devpriv->ui_AiActualScan = 0;
+ devpriv->ui_AiActualScanPosition = 0;
+ s->async->cur_chan = 0;
+ devpriv->ui_AiBufferPtr = 0;
+ devpriv->ui_DmaActualBuffer = 0;
+
+ // value for timer2 minus -2 has to be done .....dunno y??
+ ui_TimerValue2 = devpriv->ui_AiNbrofScans - 2;
+ ui_ConvertTiming = devpriv->ui_AiTimer0;
+
+ if (mode == 2)
+ ui_DelayTiming = devpriv->ui_AiTimer1;
+
+ /**********************************/
+ /* Initializes the sequence array */
+ /**********************************/
+ if (!i_APCI3120_SetupChannelList(dev, s, devpriv->ui_AiNbrofChannels,
+ devpriv->pui_AiChannelList, 0))
+ return -EINVAL;
+
+ us_TmpValue = (USHORT) inw(dev->iobase + APCI3120_RD_STATUS);
+/*** EL241003 : add this section in comment because floats must not be used
+ if((us_TmpValue & 0x00B0)==0x00B0)
+ {
+ f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2);
+ ui_TimerValue0=(UINT)f_ConvertValue;
+ if (mode==2)
+ {
+ f_DelayValue = (((float)ui_DelayTiming * 0.00002) - 2);
+ ui_TimerValue1 = (UINT) f_DelayValue;
+ }
+ }
+ else
+ {
+ f_ConvertValue=(((float)ui_ConvertTiming * 0.0012926) - 1);
+ ui_TimerValue0=(UINT)f_ConvertValue;
+ if (mode == 2)
+ {
+ f_DelayValue = (((float)ui_DelayTiming * 0.000012926) - 1);
+ ui_TimerValue1 = (UINT) f_DelayValue;
+ }
+ }
+***********************************************************************************************/
+/*** EL241003 Begin : add this section to replace floats calculation by integer calculations **/
+ //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+ if ((us_TmpValue & 0x00B0) == 0x00B0
+ || !strcmp(this_board->pc_DriverName, "apci3001")) {
+ ui_TimerValue0 = ui_ConvertTiming * 2 - 2000;
+ ui_TimerValue0 = ui_TimerValue0 / 1000;
+
+ if (mode == 2) {
+ ui_DelayTiming = ui_DelayTiming / 1000;
+ ui_TimerValue1 = ui_DelayTiming * 2 - 200;
+ ui_TimerValue1 = ui_TimerValue1 / 100;
+ }
+ } else {
+ ui_ConvertTiming = ui_ConvertTiming / 1000;
+ ui_TimerValue0 = ui_ConvertTiming * 12926 - 10000;
+ ui_TimerValue0 = ui_TimerValue0 / 10000;
+
+ if (mode == 2) {
+ ui_DelayTiming = ui_DelayTiming / 1000;
+ ui_TimerValue1 = ui_DelayTiming * 12926 - 1;
+ ui_TimerValue1 = ui_TimerValue1 / 1000000;
+ }
+ }
+/*** EL241003 End ******************************************************************************/
+
+ if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+ i_APCI3120_ExttrigEnable(dev); // activate EXT trigger
+ }
+ switch (mode) {
+ case 1:
+ // init timer0 in mode 2
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
+ outb(devpriv->b_TimerSelectMode,
+ dev->iobase + APCI3120_TIMER_CRT1);
+
+ //Select Timer 0
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_0_WORD;
+ outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ //Set the convertion time
+ outw(((USHORT) ui_TimerValue0),
+ dev->iobase + APCI3120_TIMER_VALUE);
+ break;
+
+ case 2:
+ // init timer1 in mode 2
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0xF3) | APCI3120_TIMER_1_MODE_2;
+ outb(devpriv->b_TimerSelectMode,
+ dev->iobase + APCI3120_TIMER_CRT1);
+
+ //Select Timer 1
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_1_WORD;
+ outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ //Set the convertion time
+ outw(((USHORT) ui_TimerValue1),
+ dev->iobase + APCI3120_TIMER_VALUE);
+
+ // init timer0 in mode 2
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
+ outb(devpriv->b_TimerSelectMode,
+ dev->iobase + APCI3120_TIMER_CRT1);
+
+ //Select Timer 0
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_0_WORD;
+ outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+
+ //Set the convertion time
+ outw(((USHORT) ui_TimerValue0),
+ dev->iobase + APCI3120_TIMER_VALUE);
+ break;
+
+ }
+ // ##########common for all modes#################
+
+ /***********************/
+ /* Clears the SCAN bit */
+ /***********************/
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN;
+ devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
+ APCI3120_DISABLE_SCAN;
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ // If DMA is disabled
+ if (devpriv->us_UseDma == APCI3120_DISABLE) {
+ // disable EOC and enable EOS
+ devpriv->b_InterruptMode = APCI3120_EOS_MODE;
+ devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
+
+ devpriv->b_ModeSelectRegister =
+ (devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) |
+ APCI3120_ENABLE_EOS_INT;
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ if (!devpriv->b_AiContinuous) {
+ // configure Timer2 For counting EOS
+ //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0)
+ devpriv->us_OutputRegister =
+ devpriv->
+ us_OutputRegister & APCI3120_DISABLE_TIMER2;
+ outw(devpriv->us_OutputRegister,
+ dev->iobase + APCI3120_WR_ADDRESS);
+
+ // DISABLE TIMER INTERRUPT
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_TIMER_INT & 0xEF;
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ //(1) Init timer 2 in mode 0 and write timer value
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0x0F) |
+ APCI3120_TIMER_2_MODE_0;
+ outb(devpriv->b_TimerSelectMode,
+ dev->iobase + APCI3120_TIMER_CRT1);
+
+ //Writing LOW WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_LOW_WORD;
+ outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ outw(LOWORD(ui_TimerValue2),
+ dev->iobase + APCI3120_TIMER_VALUE);
+
+ //Writing HIGH WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_HIGH_WORD;
+ outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
+ outw(HIWORD(ui_TimerValue2),
+ dev->iobase + APCI3120_TIMER_VALUE);
+
+ //(2) Reset FC_TIMER BIT Clearing timer status register
+ inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+ // enable timer counter and disable watch dog
+ devpriv->b_ModeSelectRegister =
+ (devpriv->
+ b_ModeSelectRegister |
+ APCI3120_ENABLE_TIMER_COUNTER) &
+ APCI3120_DISABLE_WATCHDOG;
+ // select EOS clock input for timer 2
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister |
+ APCI3120_TIMER2_SELECT_EOS;
+ // Enable timer2 interrupt
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister |
+ APCI3120_ENABLE_TIMER_INT;
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ devpriv->b_Timer2Mode = APCI3120_COUNTER;
+ devpriv->b_Timer2Interrupt = APCI3120_ENABLE;
+ }
+ } else {
+ // If DMA Enabled
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ //inw(dev->iobase+0);// reset EOC bit
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+ devpriv->b_InterruptMode = APCI3120_DMA_MODE;
+
+ /************************************/
+ /* Disables the EOC, EOS interrupt */
+ /************************************/
+ devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
+ APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT;
+
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ dmalen0 = devpriv->ui_DmaBufferSize[0];
+ dmalen1 = devpriv->ui_DmaBufferSize[1];
+
+ if (!devpriv->b_AiContinuous) {
+
+ if (dmalen0 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2)) { // must we fill full first buffer?
+ dmalen0 =
+ devpriv->ui_AiNbrofScans *
+ devpriv->ui_AiScanLength * 2;
+ } else if (dmalen1 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2 - dmalen0)) // and must we fill full second buffer when first is once filled?
+ dmalen1 =
+ devpriv->ui_AiNbrofScans *
+ devpriv->ui_AiScanLength * 2 - dmalen0;
+ }
+
+ if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) {
+ // don't we want wake up every scan?
+ if (dmalen0 > (devpriv->ui_AiScanLength * 2)) {
+ dmalen0 = devpriv->ui_AiScanLength * 2;
+ if (devpriv->ui_AiScanLength & 1)
+ dmalen0 += 2;
+ }
+ if (dmalen1 > (devpriv->ui_AiScanLength * 2)) {
+ dmalen1 = devpriv->ui_AiScanLength * 2;
+ if (devpriv->ui_AiScanLength & 1)
+ dmalen1 -= 2;
+ if (dmalen1 < 4)
+ dmalen1 = 4;
+ }
+ } else { // isn't output buff smaller that our DMA buff?
+ if (dmalen0 > (devpriv->ui_AiDataLength)) {
+ dmalen0 = devpriv->ui_AiDataLength;
+ }
+ if (dmalen1 > (devpriv->ui_AiDataLength)) {
+ dmalen1 = devpriv->ui_AiDataLength;
+ }
+ }
+ devpriv->ui_DmaBufferUsesize[0] = dmalen0;
+ devpriv->ui_DmaBufferUsesize[1] = dmalen1;
+
+ //Initialize DMA
+
+ // Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS register
+ //1
+ ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+ outl(ui_Tmp, devpriv->i_IobaseAmcc + AMCC_OP_REG_AGCSTS);
+
+ // changed since 16 bit interface for add on
+ /*********************/
+ /* ENABLE BUS MASTER */
+ /*********************/
+ outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+ outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+ devpriv->i_IobaseAddon + 2);
+
+ outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH,
+ devpriv->i_IobaseAddon + 2);
+
+ // TO VERIFIED
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ outw(0x1000, devpriv->i_IobaseAddon + 2);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ //2 No change
+ // A2P FIFO MANAGEMENT
+ // A2P fifo reset & transfer control enable
+ /***********************/
+ /* A2P FIFO MANAGEMENT */
+ /***********************/
+ outl(APCI3120_A2P_FIFO_MANAGEMENT, devpriv->i_IobaseAmcc +
+ APCI3120_AMCC_OP_MCSR);
+
+ //3
+ //beginning address of dma buf
+ //The 32 bit address of dma buffer is converted into two 16 bit addresses
+ // Can done by using _attach and put into into an array
+ // array used may be for differnet pages
+
+ // DMA Start Adress Low
+ outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+ outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
+ devpriv->i_IobaseAddon + 2);
+
+ /*************************/
+ /* DMA Start Adress High */
+ /*************************/
+ outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+ outw((devpriv->ul_DmaBufferHw[0] / 65536),
+ devpriv->i_IobaseAddon + 2);
+
+ //4
+ // amount of bytes to be transfered set transfer count
+ // used ADDON MWTC register
+ //commented testing outl(devpriv->ui_DmaBufferUsesize[0], devpriv->i_IobaseAddon+AMCC_OP_REG_AMWTC);
+
+ /**************************/
+ /* Nbr of acquisition LOW */
+ /**************************/
+ outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+ outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF),
+ devpriv->i_IobaseAddon + 2);
+
+ /***************************/
+ /* Nbr of acquisition HIGH */
+ /***************************/
+ outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+ outw((devpriv->ui_DmaBufferUsesize[0] / 65536),
+ devpriv->i_IobaseAddon + 2);
+
+ //5
+ // To configure A2P FIFO
+ // testing outl( FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);
+
+ /******************/
+ /* A2P FIFO RESET */
+ /******************/
+ // TO VERIFY
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ outl(0x04000000UL, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ //6
+ //ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+ // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ //outw(3,devpriv->i_IobaseAddon + 4);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ //7
+ //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
+ /***************************************************/
+ /* A2P FIFO CONFIGURATE, END OF DMA INTERRUPT INIT */
+ /***************************************************/
+ outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+ APCI3120_ENABLE_WRITE_TC_INT),
+ devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ /******************************************/
+ /* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */
+ /******************************************/
+ outw(3, devpriv->i_IobaseAddon + 4);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+
+ /******************/
+ /* A2P FIFO RESET */
+ /******************/
+ //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver
+ outl(0x04000000UL,
+ devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR);
+ //END JK 07.05.04: Comparison between WIN32 and Linux driver
+ }
+
+ if ((devpriv->us_UseDma == APCI3120_DISABLE)
+ && !devpriv->b_AiContinuous) {
+ // set gate 2 to start conversion
+ devpriv->us_OutputRegister =
+ devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2;
+ outw(devpriv->us_OutputRegister,
+ dev->iobase + APCI3120_WR_ADDRESS);
+ }
+
+ switch (mode) {
+ case 1:
+ // set gate 0 to start conversion
+ devpriv->us_OutputRegister =
+ devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
+ outw(devpriv->us_OutputRegister,
+ dev->iobase + APCI3120_WR_ADDRESS);
+ break;
+ case 2:
+ // set gate 0 and gate 1
+ devpriv->us_OutputRegister =
+ devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1;
+ devpriv->us_OutputRegister =
+ devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
+ outw(devpriv->us_OutputRegister,
+ dev->iobase + APCI3120_WR_ADDRESS);
+ break;
+
+ }
+
+ return 0;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| INTERNAL FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name : int i_APCI3120_Reset(struct comedi_device *dev) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Task : Hardware reset function |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_Reset(struct comedi_device * dev)
+{
+ unsigned int i;
+ unsigned short us_TmpValue;
+
+ devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+ devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+ devpriv->ui_EocEosConversionTime = 0; // set eoc eos conv time to 0
+ devpriv->b_OutputMemoryStatus = 0;
+
+ // variables used in timer subdevice
+ devpriv->b_Timer2Mode = 0;
+ devpriv->b_Timer2Interrupt = 0;
+ devpriv->b_ExttrigEnable = 0; // Disable ext trigger
+
+ /* Disable all interrupts, watchdog for the anolog output */
+ devpriv->b_ModeSelectRegister = 0;
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ // Disables all counters, ext trigger and clears PA, PR
+ devpriv->us_OutputRegister = 0;
+ outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
+ //Code to set the all anolog o/p channel to 0v
+ //8191 is decimal value for zero(0 v)volt in bipolar mode(default)
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 1
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 2
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 3
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 4
+
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 5
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 6
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 7
+ outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 8
+
+ // Reset digital output to L0W
+
+//ES05 outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT);
+ udelay(10);
+
+ inw(dev->iobase + 0); //make a dummy read
+ inb(dev->iobase + APCI3120_RESET_FIFO); // flush FIFO
+ inw(dev->iobase + APCI3120_RD_STATUS); // flush A/D status register
+
+ //code to reset the RAM sequence
+ for (i = 0; i < 16; i++) {
+ us_TmpValue = i << 8; //select the location
+ outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+ }
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : int i_APCI3120_SetupChannelList(struct comedi_device * dev, |
+| struct comedi_subdevice * s, int n_chan,unsigned int *chanlist|
+| ,char check) |
+| |
++----------------------------------------------------------------------------+
+| Task :This function will first check channel list is ok or not|
+|and then initialize the sequence RAM with the polarity, Gain,Channel number |
+|If the last argument of function "check"is 1 then it only checks the channel|
+|list is ok or not. |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device * dev |
+| struct comedi_subdevice * s |
+| int n_chan |
+ unsigned int *chanlist
+ char check
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdevice * s,
+ int n_chan, unsigned int *chanlist, char check)
+{
+ unsigned int i; //, differencial=0, bipolar=0;
+ unsigned int gain;
+ unsigned short us_TmpValue;
+
+ /* correct channel and range number check itself comedi/range.c */
+ if (n_chan < 1) {
+ if (!check)
+ comedi_error(dev, "range/channel list is empty!");
+ return 0;
+ }
+ // All is ok, so we can setup channel/range list
+ if (check)
+ return 1;
+
+ //Code to set the PA and PR...Here it set PA to 0..
+ devpriv->us_OutputRegister =
+ devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR;
+ devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8;
+ outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
+ for (i = 0; i < n_chan; i++) {
+ // store range list to card
+ us_TmpValue = CR_CHAN(chanlist[i]); // get channel number;
+
+ if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES) {
+ us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff); // set bipolar
+ } else {
+ us_TmpValue |= APCI3120_UNIPOLAR; // enable unipolar......
+ }
+
+ gain = CR_RANGE(chanlist[i]); // get gain number
+ us_TmpValue |= ((gain & 0x03) << 4); //<<4 for G0 and G1 bit in RAM
+ us_TmpValue |= i << 8; //To select the RAM LOCATION....
+ outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+
+ printk("\n Gain = %i",
+ (((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2));
+ printk("\n Channel = %i", CR_CHAN(chanlist[i]));
+ printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR);
+ }
+ return 1; // we can serve this with scan logic
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : int i_APCI3120_ExttrigEnable(struct comedi_device * dev) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Task : Enable the external trigger |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device * dev |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_ExttrigEnable(struct comedi_device * dev)
+{
+
+ devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
+ outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : int i_APCI3120_ExttrigDisable(struct comedi_device * dev) |
+| |
++----------------------------------------------------------------------------+
+| Task : Disables the external trigger |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device * dev |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_ExttrigDisable(struct comedi_device * dev)
+{
+ devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
+ outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| INTERRUPT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name : void v_APCI3120_Interrupt(int irq, void *d) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Task :Interrupt handler for APCI3120 |
+| When interrupt occurs this gets called. |
+| First it finds which interrupt has been generated and |
+| handles corresponding interrupt |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq |
+| void *d |
+| |
++----------------------------------------------------------------------------+
+| Return Value : void |
+| |
++----------------------------------------------------------------------------+
+*/
+
+void v_APCI3120_Interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ USHORT int_daq;
+
+ unsigned int int_amcc, ui_Check, i;
+ USHORT us_TmpValue;
+ BYTE b_DummyRead;
+
+ struct comedi_subdevice *s = dev->subdevices + 0;
+ ui_Check = 1;
+
+ int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000; // get IRQ reasons
+ int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); // get AMCC INT register
+
+ if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
+ comedi_error(dev, "IRQ from unknow source");
+ return;
+ }
+
+ outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); // shutdown IRQ reasons in AMCC
+
+ int_daq = (int_daq >> 12) & 0xF;
+
+ if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+ //Disable ext trigger
+ i_APCI3120_ExttrigDisable(dev);
+ devpriv->b_ExttrigEnable = APCI3120_DISABLE;
+ }
+ //clear the timer 2 interrupt
+ inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER);
+
+ if (int_amcc & MASTER_ABORT_INT)
+ comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
+ if (int_amcc & TARGET_ABORT_INT)
+ comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
+
+ // Ckeck if EOC interrupt
+ if (((int_daq & 0x8) == 0)
+ && (devpriv->b_InterruptMode == APCI3120_EOC_MODE)) {
+ if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
+
+ // Read the AI Value
+
+ devpriv->ui_AiReadData[0] =
+ (UINT) inw(devpriv->iobase + 0);
+ devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
+ } else {
+ //Disable EOC Interrupt
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT;
+ outb(devpriv->b_ModeSelectRegister,
+ devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ }
+ }
+
+ // Check If EOS interrupt
+ if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) {
+
+ if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) // enable this in without DMA ???
+ {
+
+ if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
+ ui_Check = 0;
+ i_APCI3120_InterruptHandleEos(dev);
+ devpriv->ui_AiActualScan++;
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister |
+ APCI3120_ENABLE_EOS_INT;
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase +
+ APCI3120_WRITE_MODE_SELECT);
+ } else {
+ ui_Check = 0;
+ for (i = 0; i < devpriv->ui_AiNbrofChannels;
+ i++) {
+ us_TmpValue = inw(devpriv->iobase + 0);
+ devpriv->ui_AiReadData[i] =
+ (UINT) us_TmpValue;
+ }
+ devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+ devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+
+ send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample
+
+ }
+
+ } else {
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+ devpriv->b_EocEosInterrupt = APCI3120_DISABLE; //Default settings
+ devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+ }
+
+ }
+ //Timer2 interrupt
+ if (int_daq & 0x1) {
+
+ switch (devpriv->b_Timer2Mode) {
+ case APCI3120_COUNTER:
+
+ devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ // stop timer 2
+ devpriv->us_OutputRegister =
+ devpriv->
+ us_OutputRegister & APCI3120_DISABLE_ALL_TIMER;
+ outw(devpriv->us_OutputRegister,
+ dev->iobase + APCI3120_WR_ADDRESS);
+
+ //stop timer 0 and timer 1
+ i_APCI3120_StopCyclicAcquisition(dev, s);
+ devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+
+ //UPDATE-0.7.57->0.7.68comedi_done(dev,s);
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(dev, s);
+
+ break;
+
+ case APCI3120_TIMER:
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+ break;
+
+ case APCI3120_WATCHDOG:
+
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+ break;
+
+ default:
+
+ // disable Timer Interrupt
+
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_TIMER_INT;
+
+ outb(devpriv->b_ModeSelectRegister,
+ dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ }
+
+ b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+
+ }
+
+ if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) {
+ if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
+
+ /****************************/
+ /* Clear Timer Write TC INT */
+ /****************************/
+
+ outl(APCI3120_CLEAR_WRITE_TC_INT,
+ devpriv->i_IobaseAmcc +
+ APCI3120_AMCC_OP_REG_INTCSR);
+
+ /************************************/
+ /* Clears the timer status register */
+ /************************************/
+ inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+ v_APCI3120_InterruptDma(irq, d); // do some data transfer
+ } else {
+ /* Stops the Timer */
+ outw(devpriv->
+ us_OutputRegister & APCI3120_DISABLE_TIMER0 &
+ APCI3120_DISABLE_TIMER1,
+ dev->iobase + APCI3120_WR_ADDRESS);
+ }
+
+ }
+
+ return;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InterruptHandleEos(struct comedi_device *dev) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Task : This function handles EOS interrupt. |
+| This function copies the acquired data(from FIFO) |
+| to Comedi buffer. |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| |
+| |
++----------------------------------------------------------------------------+
+| Return Value : 0 |
+| |
++----------------------------------------------------------------------------+
+*/
+
+/*
+ * int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
+{
+ int n_chan,i;
+ short *data;
+ struct comedi_subdevice *s=dev->subdevices+0;
+ struct comedi_async *async = s->async;
+ data=async->data+async->buf_int_ptr;
+ n_chan=devpriv->ui_AiNbrofChannels;
+
+ for(i=0;i<n_chan;i++)
+ {
+ data[i]=inw(dev->iobase+0);
+ }
+ async->buf_int_count+=n_chan*sizeof(short);
+ async->buf_int_ptr+=n_chan*sizeof(short);
+ comedi_eos(dev,s);
+ if (s->async->buf_int_ptr>=s->async->data_len) // for buffer rool over
+ {
+*//* buffer rollover */
+/* s->async->buf_int_ptr=0;
+ comedi_eobuf(dev,s);
+ }
+ return 0;
+}*/
+int i_APCI3120_InterruptHandleEos(struct comedi_device * dev)
+{
+ int n_chan, i;
+ struct comedi_subdevice *s = dev->subdevices + 0;
+ int err = 1;
+
+ n_chan = devpriv->ui_AiNbrofChannels;
+
+ s->async->events = 0;
+
+ for (i = 0; i < n_chan; i++)
+ err &= comedi_buf_put(s->async, inw(dev->iobase + 0));
+
+ s->async->events |= COMEDI_CB_EOS;
+
+ if (err == 0)
+ s->async->events |= COMEDI_CB_OVERFLOW;
+
+ comedi_event(dev, s);
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : void v_APCI3120_InterruptDma(int irq, void *d) |
+| |
++----------------------------------------------------------------------------+
+| Task : This is a handler for the DMA interrupt |
+| This function copies the data to Comedi Buffer. |
+| For continuous DMA it reinitializes the DMA operation. |
+| For single mode DMA it stop the acquisition. |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq, void *d |
+| |
++----------------------------------------------------------------------------+
+| Return Value : void |
+| |
++----------------------------------------------------------------------------+
+*/
+
+void v_APCI3120_InterruptDma(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ struct comedi_subdevice *s = dev->subdevices + 0;
+ unsigned int next_dma_buf, samplesinbuf;
+ unsigned long low_word, high_word, var;
+
+ UINT ui_Tmp;
+ samplesinbuf =
+ devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
+ inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
+
+ if (samplesinbuf <
+ devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) {
+ comedi_error(dev, "Interrupted DMA transfer!");
+ }
+ if (samplesinbuf & 1) {
+ comedi_error(dev, "Odd count of bytes in DMA ring!");
+ i_APCI3120_StopCyclicAcquisition(dev, s);
+ devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+
+ return;
+ }
+ samplesinbuf = samplesinbuf >> 1; // number of received samples
+ if (devpriv->b_DmaDoubleBuffer) {
+ // switch DMA buffers if is used double buffering
+ next_dma_buf = 1 - devpriv->ui_DmaActualBuffer;
+
+ ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+ outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
+
+ // changed since 16 bit interface for add on
+ outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+ outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+ devpriv->i_IobaseAddon + 2);
+ outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); // 0x1000 is out putted in windows driver
+
+ var = devpriv->ul_DmaBufferHw[next_dma_buf];
+ low_word = var & 0xffff;
+ var = devpriv->ul_DmaBufferHw[next_dma_buf];
+ high_word = var / 65536;
+
+ /* DMA Start Adress Low */
+ outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+ outw(low_word, devpriv->i_IobaseAddon + 2);
+
+ /* DMA Start Adress High */
+ outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(high_word, devpriv->i_IobaseAddon + 2);
+
+ var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
+ low_word = var & 0xffff;
+ var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
+ high_word = var / 65536;
+
+ /* Nbr of acquisition LOW */
+ outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+ outw(low_word, devpriv->i_IobaseAddon + 2);
+
+ /* Nbr of acquisition HIGH */
+ outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(high_word, devpriv->i_IobaseAddon + 2);
+
+ // To configure A2P FIFO
+ // ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+ // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+ outw(3, devpriv->i_IobaseAddon + 4);
+ //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
+ outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+ APCI3120_ENABLE_WRITE_TC_INT),
+ devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+
+ }
+/*UPDATE-0.7.57->0.7.68
+ ptr=(short *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer];
+
+
+ // if there is not enough space left in the buffer to copy all data contained in the DMABufferVirtual
+ if(s->async->buf_int_ptr+samplesinbuf*sizeof(short)>=devpriv->ui_AiDataLength)
+ {
+ m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(short);
+ v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,m);
+ s->async->buf_int_count+=m*sizeof(short);
+ ptr+=m*sizeof(short);
+ samplesinbuf-=m;
+ s->async->buf_int_ptr=0;
+ comedi_eobuf(dev,s);
+ }
+
+ if (samplesinbuf)
+ {
+ v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,samplesinbuf);
+
+ s->async->buf_int_count+=samplesinbuf*sizeof(short);
+ s->async->buf_int_ptr+=samplesinbuf*sizeof(short);
+ if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS))
+ {
+ comedi_bufcheck(dev,s);
+ }
+ }
+ if (!devpriv->b_AiContinuous)
+ if ( devpriv->ui_AiActualScan>=devpriv->ui_AiNbrofScans )
+ {
+ // all data sampled
+ i_APCI3120_StopCyclicAcquisition(dev,s);
+ devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE;
+ //DPRINTK("\n Single DMA completed..\n");
+ comedi_done(dev,s);
+ return;
+ }
+*/
+ if (samplesinbuf) {
+ v_APCI3120_InterruptDmaMoveBlock16bit(dev, s,
+ devpriv->ul_DmaBufferVirtual[devpriv->
+ ui_DmaActualBuffer], samplesinbuf);
+
+ if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) {
+ s->async->events |= COMEDI_CB_EOS;
+ comedi_event(dev, s);
+ }
+ }
+ if (!devpriv->b_AiContinuous)
+ if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) {
+ // all data sampled
+ i_APCI3120_StopCyclicAcquisition(dev, s);
+ devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(dev, s);
+ return;
+ }
+
+ if (devpriv->b_DmaDoubleBuffer) { // switch dma buffers
+ devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
+ } else {
+ // restart DMA if is not used double buffering
+ //ADDED REINITIALISE THE DMA
+ ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+ outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
+
+ // changed since 16 bit interface for add on
+ outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+ outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+ devpriv->i_IobaseAddon + 2);
+ outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); //
+ // A2P FIFO MANAGEMENT
+ // A2P fifo reset & transfer control enable
+ outl(APCI3120_A2P_FIFO_MANAGEMENT,
+ devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+
+ var = devpriv->ul_DmaBufferHw[0];
+ low_word = var & 0xffff;
+ var = devpriv->ul_DmaBufferHw[0];
+ high_word = var / 65536;
+ outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+ outw(low_word, devpriv->i_IobaseAddon + 2);
+ outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(high_word, devpriv->i_IobaseAddon + 2);
+
+ var = devpriv->ui_DmaBufferUsesize[0];
+ low_word = var & 0xffff; //changed
+ var = devpriv->ui_DmaBufferUsesize[0];
+ high_word = var / 65536;
+ outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+ outw(low_word, devpriv->i_IobaseAddon + 2);
+ outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+ outw(high_word, devpriv->i_IobaseAddon + 2);
+
+ // To configure A2P FIFO
+ //ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+ // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+ outw(3, devpriv->i_IobaseAddon + 4);
+ //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI)
+ outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+ APCI3120_ENABLE_WRITE_TC_INT),
+ devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+ }
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device|
+|*dev,struct comedi_subdevice *s,short *dma,short *data,int n) |
+| |
++----------------------------------------------------------------------------+
+| Task : This function copies the data from DMA buffer to the |
+| Comedi buffer |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| short *dma |
+| short *data,int n |
++----------------------------------------------------------------------------+
+| Return Value : void |
+| |
++----------------------------------------------------------------------------+
+*/
+
+/*void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n)
+{
+ int i,j,m;
+
+ j=s->async->cur_chan;
+ m=devpriv->ui_AiActualScanPosition;
+ for(i=0;i<n;i++)
+ {
+ *data=*dma;
+ data++; dma++;
+ j++;
+ if(j>=devpriv->ui_AiNbrofChannels)
+ {
+ m+=j;
+ j=0;
+ if(m>=devpriv->ui_AiScanLength)
+ {
+ m=0;
+ devpriv->ui_AiActualScan++;
+ if (devpriv->ui_AiFlags & TRIG_WAKE_EOS)
+;//UPDATE-0.7.57->0.7.68 comedi_eos(dev,s);
+ }
+ }
+ }
+ devpriv->ui_AiActualScanPosition=m;
+ s->async->cur_chan=j;
+
+}
+*/
+void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev,
+ struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples)
+{
+ devpriv->ui_AiActualScan +=
+ (s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
+ s->async->cur_chan += num_samples;
+ s->async->cur_chan %= devpriv->ui_AiScanLength;
+
+ cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short));
+}
+
+/*
++----------------------------------------------------------------------------+
+| TIMER SUBDEVICE |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, |
+| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task :Configure Timer 2 |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
+| |
+| data[0]= TIMER configure as timer |
+| = WATCHDOG configure as watchdog |
+| data[1] = Timer constant |
+| data[2] = Timer2 interrupt (1)enable or(0) disable |
+| |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ UINT ui_Timervalue2;
+ USHORT us_TmpValue;
+ BYTE b_Tmp;
+
+ if (!data[1])
+ comedi_error(dev, "config:No timer constant !");
+
+ devpriv->b_Timer2Interrupt = (BYTE) data[2]; // save info whether to enable or disable interrupt
+
+ ui_Timervalue2 = data[1] / 1000; // convert nano seconds to u seconds
+
+ //this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(BYTE)data[0]);
+ us_TmpValue = (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+ //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+ // and calculate the time value to set in the timer
+ if ((us_TmpValue & 0x00B0) == 0x00B0
+ || !strcmp(this_board->pc_DriverName, "apci3001")) {
+ //Calculate the time value to set in the timer
+ ui_Timervalue2 = ui_Timervalue2 / 50;
+ } else {
+ //Calculate the time value to set in the timer
+ ui_Timervalue2 = ui_Timervalue2 / 70;
+ }
+
+ //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0)
+ devpriv->us_OutputRegister =
+ devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2;
+ outw(devpriv->us_OutputRegister, devpriv->iobase + APCI3120_WR_ADDRESS);
+
+ // Disable TIMER Interrupt
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF;
+
+ // Disable Eoc and Eos Interrupts
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT &
+ APCI3120_DISABLE_EOS_INT;
+ outb(devpriv->b_ModeSelectRegister,
+ devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+ if (data[0] == APCI3120_TIMER) //initialize timer
+ {
+
+ //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT ;
+ //outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT);
+
+ //Set the Timer 2 in mode 2(Timer)
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2;
+ outb(devpriv->b_TimerSelectMode,
+ devpriv->iobase + APCI3120_TIMER_CRT1);
+
+ //Configure the timer 2 for writing the LOW WORD of timer is Delay value
+ //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+ //you can set the digital output and configure the timer 2,and if you don't make this, digital output
+ //are erase (Set to 0)
+
+ //Writing LOW WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_LOW_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+ outw(LOWORD(ui_Timervalue2),
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ //Writing HIGH WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_HIGH_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+ outw(HIWORD(ui_Timervalue2),
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+ // timer2 in Timer mode enabled
+ devpriv->b_Timer2Mode = APCI3120_TIMER;
+
+ } else // Initialize Watch dog
+ {
+
+ //Set the Timer 2 in mode 5(Watchdog)
+
+ devpriv->b_TimerSelectMode =
+ (devpriv->
+ b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_5;
+ outb(devpriv->b_TimerSelectMode,
+ devpriv->iobase + APCI3120_TIMER_CRT1);
+
+ //Configure the timer 2 for writing the LOW WORD of timer is Delay value
+ //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0
+ //you can set the digital output and configure the timer 2,and if you don't make this, digital output
+ //are erase (Set to 0)
+
+ //Writing LOW WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_LOW_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+ outw(LOWORD(ui_Timervalue2),
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ //Writing HIGH WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_HIGH_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+ outw(HIWORD(ui_Timervalue2),
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+ //watchdog enabled
+ devpriv->b_Timer2Mode = APCI3120_WATCHDOG;
+
+ }
+
+ return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, |
+| struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : To start and stop the timer |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
+| |
+| data[0] = 1 (start) |
+| data[0] = 0 (stop ) |
+| data[0] = 2 (write new value) |
+| data[1]= new value |
+| |
+| devpriv->b_Timer2Mode = 0 DISABLE |
+| 1 Timer |
+| 2 Watch dog |
+| |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+
+ UINT ui_Timervalue2 = 0;
+ USHORT us_TmpValue;
+ BYTE b_Tmp;
+
+ if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+ && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
+ comedi_error(dev, "\nwrite:timer2 not configured ");
+ return -EINVAL;
+ }
+
+ if (data[0] == 2) // write new value
+ {
+ if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
+ comedi_error(dev,
+ "write :timer2 not configured in TIMER MODE");
+ return -EINVAL;
+ }
+
+ if (data[1])
+ ui_Timervalue2 = data[1];
+ else
+ ui_Timervalue2 = 0;
+ }
+
+ //this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2);
+
+ switch (data[0]) {
+ case APCI3120_START:
+
+ // Reset FC_TIMER BIT
+ inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+ if (devpriv->b_Timer2Mode == APCI3120_TIMER) //start timer
+ {
+ //Enable Timer
+ devpriv->b_ModeSelectRegister =
+ devpriv->b_ModeSelectRegister & 0x0B;
+ } else //start watch dog
+ {
+ //Enable WatchDog
+ devpriv->b_ModeSelectRegister =
+ (devpriv->
+ b_ModeSelectRegister & 0x0B) |
+ APCI3120_ENABLE_WATCHDOG;
+ }
+
+ //enable disable interrupt
+ if ((devpriv->b_Timer2Interrupt) == APCI3120_ENABLE) {
+
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister |
+ APCI3120_ENABLE_TIMER_INT;
+ // save the task structure to pass info to user
+ devpriv->tsk_Current = current;
+ } else {
+
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_TIMER_INT;
+ }
+ outb(devpriv->b_ModeSelectRegister,
+ devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ if (devpriv->b_Timer2Mode == APCI3120_TIMER) //start timer
+ {
+ //For Timer mode is Gate2 must be activated **timer started
+ devpriv->us_OutputRegister =
+ devpriv->
+ us_OutputRegister | APCI3120_ENABLE_TIMER2;
+ outw(devpriv->us_OutputRegister,
+ devpriv->iobase + APCI3120_WR_ADDRESS);
+ }
+
+ break;
+
+ case APCI3120_STOP:
+ if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
+ //Disable timer
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_TIMER_COUNTER;
+ } else {
+ //Disable WatchDog
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister &
+ APCI3120_DISABLE_WATCHDOG;
+ }
+ // Disable timer interrupt
+ devpriv->b_ModeSelectRegister =
+ devpriv->
+ b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT;
+
+ // Write above states to register
+ outb(devpriv->b_ModeSelectRegister,
+ devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
+
+ // Reset Gate 2
+ devpriv->us_OutputRegister =
+ devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT;
+ outw(devpriv->us_OutputRegister,
+ devpriv->iobase + APCI3120_WR_ADDRESS);
+
+ // Reset FC_TIMER BIT
+ inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+
+ // Disable timer
+ //devpriv->b_Timer2Mode=APCI3120_DISABLE;
+
+ break;
+
+ case 2: //write new value to Timer
+ if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
+ comedi_error(dev,
+ "write :timer2 not configured in TIMER MODE");
+ return -EINVAL;
+ }
+ // ui_Timervalue2=data[1]; // passed as argument
+ us_TmpValue =
+ (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+ //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001
+ // and calculate the time value to set in the timer
+ if ((us_TmpValue & 0x00B0) == 0x00B0
+ || !strcmp(this_board->pc_DriverName, "apci3001")) {
+ //Calculate the time value to set in the timer
+ ui_Timervalue2 = ui_Timervalue2 / 50;
+ } else {
+ //Calculate the time value to set in the timer
+ ui_Timervalue2 = ui_Timervalue2 / 70;
+ }
+ //Writing LOW WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_LOW_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+ outw(LOWORD(ui_Timervalue2),
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ //Writing HIGH WORD
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_HIGH_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+ outw(HIWORD(ui_Timervalue2),
+ devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ break;
+ default:
+ return -EINVAL; // Not a valid input
+ }
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : int i_APCI3120_InsnReadTimer(struct comedi_device *dev, |
+| struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Task : read the Timer value |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
+| |
++----------------------------------------------------------------------------+
+| Return Value : |
+| for Timer: data[0]= Timer constant |
+| |
+| for watchdog: data[0]=0 (still running) |
+| data[0]=1 (run down) |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_Tmp;
+ USHORT us_TmpValue, us_TmpValue_2, us_StatusValue;
+
+ if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
+ && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
+ comedi_error(dev, "\nread:timer2 not configured ");
+ }
+
+ //this_board->i_hwdrv_InsnReadTimer(dev,data);
+ if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
+
+ //Read the LOW WORD of Timer 2 register
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_LOW_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+ us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ //Read the HIGH WORD of Timer 2 register
+ b_Tmp = ((devpriv->
+ b_DigitalOutputRegister) & 0xF0) |
+ APCI3120_SELECT_TIMER_2_HIGH_WORD;
+ outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
+
+ us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
+
+ // combining both words
+ data[0] = (UINT) ((us_TmpValue) | ((us_TmpValue_2) << 16));
+
+ } else // Read watch dog status
+ {
+
+ us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS);
+ us_StatusValue =
+ ((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1;
+ if (us_StatusValue == 1) {
+ // RESET FC_TIMER BIT
+ inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
+ }
+ data[0] = us_StatusValue; // when data[0] = 1 then the watch dog has rundown
+ }
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| DIGITAL INPUT SUBDEVICE |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, |
+| struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) |
+| |
+| |
++----------------------------------------------------------------------------+
+| Task : Reads the value of the specified Digital input channel|
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ UINT ui_Chan, ui_TmpValue;
+
+ ui_Chan = CR_CHAN(insn->chanspec); // channel specified
+
+ //this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data);
+ if (ui_Chan >= 0 && ui_Chan <= 3) {
+ ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+
+ // since only 1 channel reqd to bring it to last bit it is rotated
+ // 8 +(chan - 1) times then ANDed with 1 for last bit.
+ *data = (ui_TmpValue >> (ui_Chan + 8)) & 1;
+ //return 0;
+ } else {
+ // comedi_error(dev," chan spec wrong");
+ return -EINVAL; // "sorry channel spec wrong "
+ }
+ return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, |
+|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : Reads the value of the Digital input Port i.e.4channels|
+| value is returned in data[0] |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_TmpValue;
+ ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS);
+ /***** state of 4 channels in the 11, 10, 9, 8 bits of status reg
+ rotated right 8 times to bring them to last four bits
+ ANDed with oxf for value.
+ *****/
+
+ *data = (ui_TmpValue >> 8) & 0xf;
+ //this_board->i_hwdrv_InsnBitsDigitalInput(dev,data);
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| DIGITAL OUTPUT SUBDEVICE |
++----------------------------------------------------------------------------+
+*/
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device |
+| *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task :Configure the output memory ON or OFF |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters :struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnConfigDigitalOutput(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]) {
+ devpriv->b_OutputMemoryStatus = APCI3120_ENABLE;
+
+ } else {
+ devpriv->b_OutputMemoryStatus = APCI3120_DISABLE;
+ devpriv->b_DigitalOutputRegister = 0;
+ }
+ if (!devpriv->b_OutputMemoryStatus) {
+ ui_Temp = 0;
+
+ } //if(!devpriv->b_OutputMemoryStatus )
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, |
+| struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : write diatal output port |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
+ data[0] Value to be written
+ data[1] :1 Set digital o/p ON
+ data[1] 2 Set digital o/p OFF with memory ON
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
+
+ comedi_error(dev, "Data is not valid !!! \n");
+ return -EINVAL;
+ }
+
+ switch (data[1]) {
+ case 1:
+ data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
+ break;
+
+ case 2:
+ data[0] = data[0];
+ break;
+ default:
+ printk("\nThe parameter passed is in error \n");
+ return -EINVAL;
+ } // switch(data[1])
+ outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+
+ devpriv->b_DigitalOutputRegister = data[0] & 0xF0;
+
+ return insn->n;
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
+|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : Write digiatl output |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
+ data[0] Value to be written
+ data[1] :1 Set digital o/p ON
+ data[1] 2 Set digital o/p OFF with memory ON
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+
+ UINT ui_Temp1;
+
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+
+ if ((data[0] != 0) && (data[0] != 1)) {
+ comedi_error(dev,
+ "Not a valid Data !!! ,Data should be 1 or 0\n");
+ return -EINVAL;
+ }
+ if ((ui_NoOfChannel > (this_board->i_NbrDoChannel - 1))
+ || (ui_NoOfChannel < 0)) {
+ comedi_error(dev,
+ "This board doesn't have specified channel !!! \n");
+ return -EINVAL;
+ }
+
+ switch (data[1]) {
+ case 1:
+ data[0] = (data[0] << ui_NoOfChannel);
+//ES05 data[0]=(data[0]<<4)|ui_Temp;
+ data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
+ break;
+
+ case 2:
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp1 = ui_Temp1 << 4;
+//ES05 ui_Temp=ui_Temp|ui_Temp1;
+ devpriv->b_DigitalOutputRegister =
+ devpriv->b_DigitalOutputRegister | ui_Temp1;
+
+ data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
+ data[0] = data[0] << 4;
+//ES05 data[0]=data[0]& ui_Temp;
+ data[0] = data[0] & devpriv->b_DigitalOutputRegister;
+ break;
+ default:
+ printk("\nThe parameter passed is in error \n");
+ return -EINVAL;
+ } // switch(data[1])
+ outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+
+//ES05 ui_Temp=data[0] & 0xf0;
+ devpriv->b_DigitalOutputRegister = data[0] & 0xf0;
+ return (insn->n);
+
+}
+
+/*
++----------------------------------------------------------------------------+
+| ANALOG OUTPUT SUBDEVICE |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,|
+|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) |
+| |
++----------------------------------------------------------------------------+
+| Task : Write analog output |
+| |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ UINT ui_Range, ui_Channel;
+ USHORT us_TmpValue;
+
+ ui_Range = CR_RANGE(insn->chanspec);
+ ui_Channel = CR_CHAN(insn->chanspec);
+
+ //this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]);
+ if (ui_Range) // if 1 then unipolar
+ {
+
+ if (data[0] != 0)
+ data[0] =
+ ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
+ 13) | (data[0] + 8191));
+ else
+ data[0] =
+ ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
+ 13) | 8192);
+
+ } else // if 0 then bipolar
+ {
+ data[0] =
+ ((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) |
+ data[0]);
+
+ }
+
+ //out put n values at the given channel.
+ // rt_printk("\nwaiting for DA_READY BIT");
+ do //Waiting of DA_READY BIT
+ {
+ us_TmpValue =
+ ((USHORT) inw(devpriv->iobase +
+ APCI3120_RD_STATUS)) & 0x0001;
+ } while (us_TmpValue != 0x0001);
+
+ if (ui_Channel <= 3)
+ // for channel 0-3 out at the register 1 (wrDac1-8)
+ // data[i] typecasted to ushort since word write is to be done
+ outw((USHORT) data[0],
+ devpriv->iobase + APCI3120_ANALOG_OUTPUT_1);
+ else
+ // for channel 4-7 out at the register 2 (wrDac5-8)
+ //data[i] typecasted to ushort since word write is to be done
+ outw((USHORT) data[0],
+ devpriv->iobase + APCI3120_ANALOG_OUTPUT_2);
+
+ return insn->n;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
new file mode 100644
index 000000000000..59d5d87a845b
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
@@ -0,0 +1,241 @@
+
+// hwdrv_apci3120.h
+
+/*
+ * 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.
+ */
+
+// comedi related defines
+
+//ANALOG INPUT RANGE
+static const struct comedi_lrange range_apci3120_ai = { 8, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2),
+ UNI_RANGE(1)
+ }
+};
+
+// ANALOG OUTPUT RANGE
+static const struct comedi_lrange range_apci3120_ao = { 2, {
+ BIP_RANGE(10),
+ UNI_RANGE(10)
+ }
+};
+
+#define APCI3120_BIPOLAR_RANGES 4 // used for test on mixture of BIP/UNI ranges
+
+#define APCI3120_BOARD_VENDOR_ID 0x10E8
+#define APCI3120_ADDRESS_RANGE 16
+
+#define APCI3120_DISABLE 0
+#define APCI3120_ENABLE 1
+
+#define APCI3120_START 1
+#define APCI3120_STOP 0
+
+#define APCI3120_EOC_MODE 1
+#define APCI3120_EOS_MODE 2
+#define APCI3120_DMA_MODE 3
+
+//DIGITAL INPUT-OUTPUT DEFINE
+
+#define APCI3120_DIGITAL_OUTPUT 0x0D
+#define APCI3120_RD_STATUS 0x02
+#define APCI3120_RD_FIFO 0x00
+
+// digital output insn_write ON /OFF selection
+#define APCI3120_SET4DIGITALOUTPUTON 1
+#define APCI3120_SET4DIGITALOUTPUTOFF 0
+
+// analog output SELECT BIT
+#define APCI3120_ANALOG_OP_CHANNEL_1 0x0000
+#define APCI3120_ANALOG_OP_CHANNEL_2 0x4000
+#define APCI3120_ANALOG_OP_CHANNEL_3 0x8000
+#define APCI3120_ANALOG_OP_CHANNEL_4 0xC000
+#define APCI3120_ANALOG_OP_CHANNEL_5 0x0000
+#define APCI3120_ANALOG_OP_CHANNEL_6 0x4000
+#define APCI3120_ANALOG_OP_CHANNEL_7 0x8000
+#define APCI3120_ANALOG_OP_CHANNEL_8 0xC000
+
+// Enable external trigger bit in nWrAddress
+#define APCI3120_ENABLE_EXT_TRIGGER 0x8000
+
+//ANALOG OUTPUT AND INPUT DEFINE
+#define APCI3120_UNIPOLAR 0x80 //$$ RAM sequence polarity BIT
+#define APCI3120_BIPOLAR 0x00 //$$ RAM sequence polarity BIT
+#define APCI3120_ANALOG_OUTPUT_1 0x08 // (ADDRESS )
+#define APCI3120_ANALOG_OUTPUT_2 0x0A // (ADDRESS )
+#define APCI3120_1_GAIN 0x00 //$$ RAM sequence Gain Bits for gain 1
+#define APCI3120_2_GAIN 0x10 //$$ RAM sequence Gain Bits for gain 2
+#define APCI3120_5_GAIN 0x20 //$$ RAM sequence Gain Bits for gain 5
+#define APCI3120_10_GAIN 0x30 //$$ RAM sequence Gain Bits for gain 10
+#define APCI3120_SEQ_RAM_ADDRESS 0x06 //$$ EARLIER NAMED APCI3120_FIFO_ADDRESS
+#define APCI3120_RESET_FIFO 0x0C //(ADDRESS)
+#define APCI3120_TIMER_0_MODE_2 0x01 //$$ Bits for timer mode
+#define APCI3120_TIMER_0_MODE_4 0x2
+#define APCI3120_SELECT_TIMER_0_WORD 0x00
+#define APCI3120_ENABLE_TIMER0 0x1000 //$$Gatebit 0 in nWrAddress
+#define APCI3120_CLEAR_PR 0xF0FF
+#define APCI3120_CLEAR_PA 0xFFF0
+#define APCI3120_CLEAR_PA_PR (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA)
+
+// nWrMode_Select
+#define APCI3120_ENABLE_SCAN 0x8 //$$ bit in nWrMode_Select
+#define APCI3120_DISABLE_SCAN (~APCI3120_ENABLE_SCAN)
+#define APCI3120_ENABLE_EOS_INT 0x2 //$$ bit in nWrMode_Select
+
+#define APCI3120_DISABLE_EOS_INT (~APCI3120_ENABLE_EOS_INT)
+#define APCI3120_ENABLE_EOC_INT 0x1
+#define APCI3120_DISABLE_EOC_INT (~APCI3120_ENABLE_EOC_INT)
+#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+#define APCI3120_DISABLE_ALL_INTERRUPT (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+
+//status register bits
+#define APCI3120_EOC 0x8000
+#define APCI3120_EOS 0x2000
+
+// software trigger dummy register
+#define APCI3120_START_CONVERSION 0x02 //(ADDRESS)
+
+//TIMER DEFINE
+#define APCI3120_QUARTZ_A 70
+#define APCI3120_QUARTZ_B 50
+#define APCI3120_TIMER 1
+#define APCI3120_WATCHDOG 2
+#define APCI3120_TIMER_DISABLE 0
+#define APCI3120_TIMER_ENABLE 1
+#define APCI3120_ENABLE_TIMER2 0x4000 //$$ gatebit 2 in nWrAddress
+#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2)
+#define APCI3120_ENABLE_TIMER_INT 0x04 //$$ ENAIRQ_FC_Bit in nWrModeSelect
+#define APCI3120_DISABLE_TIMER_INT (~APCI3120_ENABLE_TIMER_INT)
+#define APCI3120_WRITE_MODE_SELECT 0x0E // (ADDRESS)
+#define APCI3120_SELECT_TIMER_0_WORD 0x00
+#define APCI3120_SELECT_TIMER_1_WORD 0x01
+#define APCI3120_TIMER_1_MODE_2 0x4
+
+//$$ BIT FOR MODE IN nCsTimerCtr1
+#define APCI3120_TIMER_2_MODE_0 0x0
+#define APCI3120_TIMER_2_MODE_2 0x10
+#define APCI3120_TIMER_2_MODE_5 0x30
+
+//$$ BIT FOR MODE IN nCsTimerCtr0
+#define APCI3120_SELECT_TIMER_2_LOW_WORD 0x02
+#define APCI3120_SELECT_TIMER_2_HIGH_WORD 0x03
+
+#define APCI3120_TIMER_CRT0 0x0D //(ADDRESS for cCsTimerCtr0)
+#define APCI3120_TIMER_CRT1 0x0C //(ADDRESS for cCsTimerCtr1)
+
+#define APCI3120_TIMER_VALUE 0x04 //ADDRESS for nCsTimerWert
+#define APCI3120_TIMER_STATUS_REGISTER 0x0D //ADDRESS for delete timer 2 interrupt
+#define APCI3120_RD_STATUS 0x02 //ADDRESS
+#define APCI3120_WR_ADDRESS 0x00 //ADDRESS
+#define APCI3120_ENABLE_WATCHDOG 0x20 //$$BIT in nWrMode_Select
+#define APCI3120_DISABLE_WATCHDOG (~APCI3120_ENABLE_WATCHDOG)
+#define APCI3120_ENABLE_TIMER_COUNTER 0x10 //$$BIT in nWrMode_Select
+#define APCI3120_DISABLE_TIMER_COUNTER (~APCI3120_ENABLE_TIMER_COUNTER)
+#define APCI3120_FC_TIMER 0x1000 //bit in status register
+#define APCI3120_ENABLE_TIMER0 0x1000
+#define APCI3120_ENABLE_TIMER1 0x2000
+#define APCI3120_ENABLE_TIMER2 0x4000
+#define APCI3120_DISABLE_TIMER0 (~APCI3120_ENABLE_TIMER0)
+#define APCI3120_DISABLE_TIMER1 (~APCI3120_ENABLE_TIMER1)
+#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2)
+
+#define APCI3120_TIMER2_SELECT_EOS 0xC0 // ADDED on 20-6
+#define APCI3120_COUNTER 3 // on 20-6
+#define APCI3120_DISABLE_ALL_TIMER ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 ) // on 20-6
+
+#define MAX_ANALOGINPUT_CHANNELS 32
+
+typedef struct {
+ BYTE b_Type; /* EOC or EOS */
+ BYTE b_InterruptFlag; /* Interrupt use or not */
+ UINT ui_ConvertTiming; /* Selection of the convertion time */
+ BYTE b_NbrOfChannel; /* Number of channel to read */
+ UINT ui_ChannelList[MAX_ANALOGINPUT_CHANNELS]; /* Number of the channel to be read */
+ UINT ui_RangeList[MAX_ANALOGINPUT_CHANNELS]; /* Gain of each channel */
+
+} str_AnalogReadInformation;
+
+// Function Declaration For APCI-3120
+
+// Internal functions
+int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
+ int n_chan, unsigned int *chanlist, char check);
+int i_APCI3120_ExttrigEnable(struct comedi_device *dev);
+int i_APCI3120_ExttrigDisable(struct comedi_device *dev);
+int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+int i_APCI3120_Reset(struct comedi_device *dev);
+int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
+ struct comedi_subdevice *s);
+// Interrupt functions
+void v_APCI3120_Interrupt(int irq, void *d);
+//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n);
+void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ short *dma_buffer,
+ unsigned int num_samples);
+int i_APCI3120_InterruptHandleEos(struct comedi_device *dev);
+void v_APCI3120_InterruptDma(int irq, void *d);
+
+// TIMER
+
+int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//DI
+// for di read
+
+int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//DO
+//int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, BYTE data);
+int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
+int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//AO
+//int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data );
+int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//AI HArdware layer
+
+int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_cmd *cmd);
+int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+//int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
new file mode 100644
index 000000000000..1ff66bee548d
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -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;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
new file mode 100644
index 000000000000..a6f57f55e79c
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+// Card Specific information
+#define APCI3200_BOARD_VENDOR_ID 0x15B8
+//#define APCI3200_ADDRESS_RANGE 264
+
+int MODULE_NO;
+struct {
+ INT i_Gain;
+ INT i_Polarity;
+ INT i_OffsetRange;
+ INT i_Coupling;
+ INT i_SingleDiff;
+ INT i_AutoCalibration;
+ UINT ui_ReloadValue;
+ UINT ui_TimeUnitReloadVal;
+ INT i_Interrupt;
+ INT i_ModuleSelection;
+} Config_Parameters_Module1, Config_Parameters_Module2,
+ Config_Parameters_Module3, Config_Parameters_Module4;
+
+//ANALOG INPUT RANGE
+static const struct comedi_lrange range_apci3200_ai = { 8, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2),
+ UNI_RANGE(1)
+ }
+};
+
+static const struct comedi_lrange range_apci3300_ai = { 4, {
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2),
+ UNI_RANGE(1)
+ }
+};
+
+//Analog Input related Defines
+#define APCI3200_AI_OFFSET_GAIN 0
+#define APCI3200_AI_SC_TEST 4
+#define APCI3200_AI_IRQ 8
+#define APCI3200_AI_AUTOCAL 12
+#define APCI3200_RELOAD_CONV_TIME_VAL 32
+#define APCI3200_CONV_TIME_TIME_BASE 36
+#define APCI3200_RELOAD_DELAY_TIME_VAL 40
+#define APCI3200_DELAY_TIME_TIME_BASE 44
+#define APCI3200_AI_MODULE1 0
+#define APCI3200_AI_MODULE2 64
+#define APCI3200_AI_MODULE3 128
+#define APCI3200_AI_MODULE4 192
+#define TRUE 1
+#define FALSE 0
+#define APCI3200_AI_EOSIRQ 16
+#define APCI3200_AI_EOS 20
+#define APCI3200_AI_CHAN_ID 24
+#define APCI3200_AI_CHAN_VAL 28
+#define ANALOG_INPUT 0
+#define TEMPERATURE 1
+#define RESISTANCE 2
+
+#define ENABLE_EXT_TRIG 1
+#define ENABLE_EXT_GATE 2
+#define ENABLE_EXT_TRIG_GATE 3
+
+#define APCI3200_MAXVOLT 2.5
+#define ADDIDATA_GREATER_THAN_TEST 0
+#define ADDIDATA_LESS_THAN_TEST 1
+
+#define ADDIDATA_UNIPOLAR 1
+#define ADDIDATA_BIPOLAR 2
+
+//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+#define MAX_MODULE 4
+//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+typedef struct {
+ ULONG ul_NumberOfValue;
+ ULONG *pul_ResistanceValue;
+ ULONG *pul_TemperatureValue;
+} str_ADDIDATA_RTDStruct, *pstr_ADDIDATA_RTDStruct;
+
+//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+typedef struct {
+ // Begin JK 05/08/2003 change for Linux
+ unsigned long ul_CurrentSourceCJC;
+ unsigned long ul_CurrentSource[5];
+ // End JK 05/08/2003 change for Linux
+
+ // Begin CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
+ unsigned long ul_GainFactor[8]; // Gain Factor
+ unsigned int w_GainValue[10];
+ // End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1
+} str_Module;
+//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+
+//BEGIN JK 06.07.04: Management of sevrals boards
+typedef struct {
+ INT i_CJCAvailable;
+ INT i_CJCPolarity;
+ INT i_CJCGain;
+ INT i_InterruptFlag;
+ INT i_ADDIDATAPolarity;
+ INT i_ADDIDATAGain;
+ INT i_AutoCalibration;
+ INT i_ADDIDATAConversionTime;
+ INT i_ADDIDATAConversionTimeUnit;
+ INT i_ADDIDATAType;
+ INT i_ChannelNo;
+ INT i_ChannelCount;
+ INT i_ScanType;
+ INT i_FirstChannel;
+ INT i_LastChannel;
+ INT i_Sum;
+ INT i_Offset;
+ UINT ui_Channel_num;
+ INT i_Count;
+ INT i_Initialised;
+ //UINT ui_InterruptChannelValue[96]; //Buffer
+ UINT ui_InterruptChannelValue[144]; //Buffer
+ BYTE b_StructInitialized;
+ //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+ unsigned int ui_ScanValueArray[7 + 12]; // 7 is the maximal number of channels
+ //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68
+
+ //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+ INT i_ConnectionType;
+ INT i_NbrOfModule;
+ str_Module s_Module[MAX_MODULE];
+ //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
+} str_BoardInfos;
+//END JK 06.07.04: Management of sevrals boards
+
+// Hardware Layer functions for Apci3200
+
+//AI
+
+INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
+INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_cmd *cmd);
+INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
+INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+//Interrupt
+void v_APCI3200_Interrupt(int irq, void *d);
+int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
+//Reset functions
+INT i_APCI3200_Reset(struct comedi_device *dev);
+
+int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data);
+int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
+int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, UINT *data);
+int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, UINT *data);
+int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
+ struct comedi_subdevice *s, struct comedi_insn *insn,
+ unsigned int *data);
+int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
new file mode 100644
index 000000000000..20391a91da03
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
@@ -0,0 +1,742 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*.
+
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-------------------------------+---------------------------------------+
+ | Project : APCI-3501 | Compiler : GCC |
+ | Module name : hwdrv_apci3501.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: Eric Stolz | Date : 02/12/2002 |
+ +-------------------------------+---------------------------------------+
+ | Description : Hardware Layer Acces For APCI-3501 |
+ +-----------------------------------------------------------------------+
+ | UPDATES |
+ +----------+-----------+------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Included files |
++----------------------------------------------------------------------------+
+*/
+#include "hwdrv_apci3501.h"
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_ReadDigitalInput |
+| (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 |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+INT i_APCI3501_ReadDigitalInput(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->iobase + APCI3501_DIGITAL_IP);
+ if (ui_Temp == 0) {
+ *data = (*data >> ui_NoOfChannel) & 0x1;
+ } //if (ui_Temp==0)
+ else {
+ if (ui_Temp == 1) {
+
+ *data = *data & 0x3;
+ } //if (ui_Temp==1)
+ else {
+ printk("\nSpecified channel not supported \n");
+ } //elseif (ui_Temp==1)
+ } //elseif (ui_Temp==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_ConfigDigitalOutput |
+| (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 |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[1] : 1 Enable VCC Interrupt |
+| 0 Disable VCC Interrupt |
+| data[2] : 1 Enable CC Interrupt |
+| 0 Disable CC Interrupt |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3501_ConfigDigitalOutput(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_APCI3501_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 |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ UINT ui_Temp, ui_Temp1;
+ UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel
+ if (devpriv->b_OutputMemoryStatus) {
+ ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
+ } //if(devpriv->b_OutputMemoryStatus )
+ else {
+ ui_Temp = 0;
+ } //if(devpriv->b_OutputMemoryStatus )
+ if (data[3] == 0) {
+ if (data[1] == 0) {
+ data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
+ outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ data[0] = (data[0] << (2 * data[2])) | ui_Temp;
+ outl(data[0],
+ devpriv->iobase + APCI3501_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==0)
+ else {
+ if (data[3] == 1) {
+ if (data[1] == 0) {
+ data[0] = ~data[0] & 0x1;
+ ui_Temp1 = 1;
+ ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ (data[0] << ui_NoOfChannel) ^
+ 0xffffffff;
+ data[0] = data[0] & ui_Temp;
+ outl(data[0],
+ devpriv->iobase + APCI3501_DIGITAL_OP);
+ } //if(data[1]==0)
+ else {
+ if (data[1] == 1) {
+ data[0] = ~data[0] & 0x3;
+ ui_Temp1 = 3;
+ ui_Temp1 = ui_Temp1 << 2 * data[2];
+ ui_Temp = ui_Temp | ui_Temp1;
+ data[0] =
+ ((data[0] << (2 *
+ data[2])) ^
+ 0xffffffff) & ui_Temp;
+ outl(data[0],
+ devpriv->iobase +
+ APCI3501_DIGITAL_OP);
+ } // if(data[1]==1)
+ else {
+ printk("\nSpecified channel not supported\n");
+ } //else if(data[1]==1)
+ } //elseif(data[1]==0)
+ } //if(data[3]==1);
+ else {
+ printk("\nSpecified functionality does not exist\n");
+ return -EINVAL;
+ } //if else data[3]==1)
+ } //if else data[3]==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_ReadDigitalOutput |
+| (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 |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_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->iobase + APCI3501_DIGITAL_OP);
+ if (ui_Temp == 0) {
+ *data = (*data >> ui_NoOfChannel) & 0x1;
+ } // if (ui_Temp==0)
+ else {
+ if (ui_Temp == 1) {
+ *data = *data & 0x3;
+
+ } // if (ui_Temp==1)
+ else {
+ printk("\nSpecified channel not supported \n");
+ } // else if (ui_Temp==1)
+ } // else if (ui_Temp==0)
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_ConfigAnalogOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Configures The Analog 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] : Voltage Mode |
+| 0:Mode 0 |
+| 1:Mode 1 |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ outl(data[0],
+ devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+ APCI3501_AO_VOLT_MODE);
+
+ if (data[0]) {
+ devpriv->b_InterruptMode = MODE1;
+ } else {
+ devpriv->b_InterruptMode = MODE0;
+ }
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_WriteAnalogOutput |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Writes To the Selected Anlog Output 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 |
+| |
+| |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s,
+ struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;;
+
+ ul_Channel_no = CR_CHAN(insn->chanspec);
+
+ if (devpriv->b_InterruptMode == MODE1) {
+ ul_Polarity = 0x80000000;
+ if ((*data < 0) || (*data > 16384)) {
+ printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
+ }
+
+ } // end if(devpriv->b_InterruptMode==MODE1)
+ else {
+ ul_Polarity = 0;
+ if ((*data < 0) || (*data > 8192)) {
+ printk("\nIn WriteAnalogOutput :: Not Valid Data\n");
+ }
+
+ } // end else
+
+ if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) {
+ printk("\nIn WriteAnalogOutput :: Not Valid Channel\n");
+ } // end if((ul_Channel_no<0)||(ul_Channel_no>7))
+
+ ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+
+ while (ul_DAC_Ready == 0) {
+ ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+ ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
+ }
+
+ if (ul_DAC_Ready) {
+// Output the Value on the output channels.
+ ul_Command1 =
+ (ULONG) ((ULONG) (ul_Channel_no & 0xFF) |
+ (ULONG) ((*data << 0x8) & 0x7FFFFF00L) |
+ (ULONG) (ul_Polarity));
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+ APCI3501_AO_PROG);
+ }
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_ConfigTimerCounterWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Configures The Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 0 Configure As Timer |
+| 1 Configure As Counter |
+| 2 Configure As Watchdog |
+| data[1] : 1 Enable Interrupt |
+| 0 Disable Interrupt |
+| data[2] : Time Unit |
+| data[3] : Reload Value |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command1 = 0;
+ devpriv->tsk_Current = current;
+ if (data[0] == ADDIDATA_WATCHDOG) {
+
+ devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+ //Disable the watchdog
+ outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Wa
+
+ if (data[1] == 1) {
+ //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
+ outl(0x02,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ } else {
+ outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Timer interrupt
+ }
+
+ //Loading the Timebase value
+ outl(data[2],
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_TIMEBASE);
+
+ //Loading the Reload value
+ outl(data[3],
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_RELOAD_VALUE);
+ //Set the mode
+ ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL; //e2->e0
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ } //end if(data[0]==ADDIDATA_WATCHDOG)
+
+ else if (data[0] == ADDIDATA_TIMER) {
+ //First Stop The Timer
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+ outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //Stop The Timer
+ devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+ if (data[1] == 1) {
+ //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES
+ outl(0x02,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ } else {
+ outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Timer interrupt
+ }
+
+ // Loading Timebase
+ outl(data[2],
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_TIMEBASE);
+
+ //Loading the Reload value
+ outl(data[3],
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_RELOAD_VALUE);
+
+ // printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG));
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 =
+ (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
+ outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //mode 2
+
+ } //end if(data[0]==ADDIDATA_TIMER)
+
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_StartStopWriteTimerCounterWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Start / Stop The Selected Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 0 Timer |
+| 1 Counter |
+| 2 Watchdog | | data[1] : 1 Start |
+| 0 Stop | 2 Trigger |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ ULONG ul_Command1 = 0;
+ int i_Temp;
+ if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+
+ if (data[1] == 1) {
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+ //Enable the Watchdog
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ }
+
+ else if (data[1] == 0) //Stop The Watchdog
+ {
+ //Stop The Watchdog
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+ outl(0x0,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ } else if (data[1] == 2) {
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ } //if(data[1]==2)
+ } // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+
+ if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ if (data[1] == 1) {
+
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+ //Enable the Timer
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ } else if (data[1] == 0) {
+ //Stop The Timer
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ }
+
+ else if (data[1] == 2) {
+ //Trigger the Timer
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_PROG);
+ }
+
+ } // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+ i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_TRIG_STATUS) & 0x1;
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_ReadTimerCounterWatchdog |
+| (struct comedi_device *dev,struct comedi_subdevice *s, |
+| struct comedi_insn *insn,unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read The Selected Timer , Counter or Watchdog |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev : Driver handle |
+| UINT *data : Data Pointer contains |
+| configuration parameters as below |
+| |
+| data[0] : 0 Timer |
+| 1 Counter |
+| 2 Watchdog | | data[1] : Timer Counter Watchdog Number |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+
+ if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ data[0] =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_TRIG_STATUS) & 0x1;
+ data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
+ } // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG)
+
+ else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+ data[0] =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_TRIG_STATUS) & 0x1;
+ data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG);
+ } // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER)
+
+ else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+ && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
+ printk("\nIn ReadTimerCounterWatchdog :: Invalid Subdevice \n");
+ }
+ return insn->n;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3501_Reset(struct comedi_device *dev) |
+| |
++----------------------------------------------------------------------------+
+| Task :Resets the registers of the card |
++----------------------------------------------------------------------------+
+| Input Parameters : |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : |
+| |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3501_Reset(struct comedi_device * dev)
+{
+ int i_Count = 0, i_temp = 0;
+ ULONG ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
+ outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
+ outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+ APCI3501_AO_VOLT_MODE);
+
+ ul_Polarity = 0x80000000;
+
+ for (i_Count = 0; i_Count <= 7; i_Count++) {
+ ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+
+ while (ul_DAC_Ready == 0) {
+ ul_DAC_Ready =
+ inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT);
+ ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1;
+ }
+
+ if (ul_DAC_Ready) {
+ // Output the Value on the output channels.
+ ul_Command1 =
+ (ULONG) ((ULONG) (i_Count & 0xFF) |
+ (ULONG) ((i_temp << 0x8) & 0x7FFFFF00L) |
+ (ULONG) (ul_Polarity));
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_ANALOG_OUTPUT +
+ APCI3501_AO_PROG);
+ }
+ }
+
+ return 0;
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : static void v_APCI3501_Interrupt |
+| (int irq , void *d) |
++----------------------------------------------------------------------------+
+| Task : Interrupt processing Routine |
++----------------------------------------------------------------------------+
+| Input Parameters : int irq : irq number |
+| void *d : void pointer |
++----------------------------------------------------------------------------+
+| Output Parameters : -- |
++----------------------------------------------------------------------------+
+| Return Value : TRUE : No error occur |
+| : FALSE : Error occur. Return the error |
+| |
++----------------------------------------------------------------------------+
+*/
+void v_APCI3501_Interrupt(int irq, void *d)
+{
+ int i_temp;
+ struct comedi_device *dev = d;
+ unsigned int ui_Timer_AOWatchdog;
+ unsigned long ul_Command1;
+ // Disable Interrupt
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+
+ ul_Command1 = (ul_Command1 & 0xFFFFF9FDul);
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+
+ ui_Timer_AOWatchdog =
+ inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_IRQ) & 0x1;
+
+ if ((!ui_Timer_AOWatchdog)) {
+ comedi_error(dev, "IRQ from unknow source");
+ return;
+ }
+
+ // Enable Interrupt
+ //Send a signal to from kernel to user space
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+ ul_Command1 =
+ inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+ ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1);
+ outl(ul_Command1,
+ devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
+ i_temp = inl(devpriv->iobase + APCI3501_WATCHDOG +
+ APCI3501_TCW_TRIG_STATUS) & 0x1;
+ return;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
new file mode 100644
index 000000000000..51e7b66544ac
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+// Card Specific information
+#define APCI3501_BOARD_VENDOR_ID 0x15B8
+#define APCI3501_ADDRESS_RANGE 255
+
+#define APCI3501_DIGITAL_IP 0x50
+#define APCI3501_DIGITAL_OP 0x40
+#define APCI3501_ANALOG_OUTPUT 0x00
+
+//Analog Output related Defines
+#define APCI3501_AO_VOLT_MODE 0
+#define APCI3501_AO_PROG 4
+#define APCI3501_AO_TRIG_SCS 8
+#define UNIPOLAR 0
+#define BIPOLAR 1
+#define MODE0 0
+#define MODE1 1
+// ANALOG OUTPUT RANGE
+struct comedi_lrange range_apci3501_ao = { 2, {
+ BIP_RANGE(10),
+ UNI_RANGE(10)
+ }
+};
+
+//Watchdog Related Defines
+
+#define APCI3501_WATCHDOG 0x20
+#define APCI3501_TCW_SYNC_ENABLEDISABLE 0
+#define APCI3501_TCW_RELOAD_VALUE 4
+#define APCI3501_TCW_TIMEBASE 8
+#define APCI3501_TCW_PROG 12
+#define APCI3501_TCW_TRIG_STATUS 16
+#define APCI3501_TCW_IRQ 20
+#define APCI3501_TCW_WARN_TIMEVAL 24
+#define APCI3501_TCW_WARN_TIMEBASE 28
+#define ADDIDATA_TIMER 0
+#define ADDIDATA_WATCHDOG 2
+
+// Hardware Layer functions for Apci3501
+
+//AO
+INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//DI
+// for di read
+//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data);
+
+INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+//DO
+int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+
+// TIMER
+// timer value is passed as u seconds
+INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data);
+int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data);
+//Interrupt
+void v_APCI3501_Interrupt(int irq, void *d);
+
+//Reset functions
+int i_APCI3501_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
new file mode 100644
index 000000000000..b7268e4da64e
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
@@ -0,0 +1,1691 @@
+/**
+@verbatim
+
+Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
+
+ ADDI-DATA GmbH
+ Dieselstrasse 3
+ D-77833 Ottersweier
+ Tel: +19(0)7223/9493-0
+ Fax: +49(0)7223/9493-92
+ http://www.addi-data-com
+ info@addi-data.com
+
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+You shoud also find the complete GPL in the COPYING file accompanying this source code.
+
+@endverbatim
+*/
+/*
+ +-----------------------------------------------------------------------+
+ | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
+ +-----------------------------------------------------------------------+
+ | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
+ | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+ +-----------------------------------------------------------------------+
+ | Project : APCI-3XXX | Compiler : GCC |
+ | Module name : hwdrv_apci3xxx.c| Version : 2.96 |
+ +-------------------------------+---------------------------------------+
+ | Project manager: S. Weber | Date : 15/09/2005 |
+ +-----------------------------------------------------------------------+
+ | Description :APCI3XXX Module. Hardware abstraction Layer for APCI3XXX|
+ +-----------------------------------------------------------------------+
+ | UPDATE'S |
+ +-----------------------------------------------------------------------+
+ | Date | Author | Description of updates |
+ +----------+-----------+------------------------------------------------+
+ | | | |
+ | | | |
+ +----------+-----------+------------------------------------------------+
+*/
+
+#include "hwdrv_apci3xxx.h"
+
+/*
++----------------------------------------------------------------------------+
+| ANALOG INPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_TestConversionStarted |
+| (struct comedi_device *dev) |
++----------------------------------------------------------------------------+
+| Task Test if any conversion started |
++----------------------------------------------------------------------------+
+| Input Parameters : - |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 : Conversion not started |
+| 1 : Conversion started |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev)
+{
+ if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_AnalogInputConfigOperatingMode |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task Converting mode and convert time selection |
++----------------------------------------------------------------------------+
+| Input Parameters : b_SingleDiff = (BYTE) data[1]; |
+| b_TimeBase = (BYTE) data[2]; (0: ns, 1:micros 2:ms)|
+| dw_ReloadValue = (DWORD) data[3]; |
+| ........ |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :>0 : No error |
+| -1 : Single/Diff selection error |
+| -2 : Convert time base unity selection error |
+| -3 : Convert time value selection error |
+| -10: Any conversion started |
+| .... |
+| -100 : Config command error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_TimeBase = 0;
+ BYTE b_SingleDiff = 0;
+ DWORD dw_ReloadValue = 0;
+ DWORD dw_TestReloadValue = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n == 4) {
+ /****************************/
+ /* Get the Singel/Diff flag */
+ /****************************/
+
+ b_SingleDiff = (BYTE) data[1];
+
+ /****************************/
+ /* Get the time base unitiy */
+ /****************************/
+
+ b_TimeBase = (BYTE) data[2];
+
+ /*************************************/
+ /* Get the convert time reload value */
+ /*************************************/
+
+ dw_ReloadValue = (DWORD) data[3];
+
+ /**********************/
+ /* Test the time base */
+ /**********************/
+
+ if ((devpriv->ps_BoardInfo->
+ b_AvailableConvertUnit & (1 << b_TimeBase)) !=
+ 0) {
+ /*******************************/
+ /* Test the convert time value */
+ /*******************************/
+
+ if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) {
+ dw_TestReloadValue = dw_ReloadValue;
+
+ if (b_TimeBase == 1) {
+ dw_TestReloadValue =
+ dw_TestReloadValue * 1000UL;
+ }
+ if (b_TimeBase == 2) {
+ dw_TestReloadValue =
+ dw_TestReloadValue * 1000000UL;
+ }
+
+ /*******************************/
+ /* Test the convert time value */
+ /*******************************/
+
+ if (dw_TestReloadValue >=
+ devpriv->ps_BoardInfo->
+ ui_MinAcquisitiontimeNs) {
+ if ((b_SingleDiff == APCI3XXX_SINGLE)
+ || (b_SingleDiff ==
+ APCI3XXX_DIFF)) {
+ if (((b_SingleDiff == APCI3XXX_SINGLE) && (devpriv->ps_BoardInfo->i_NbrAiChannel == 0)) || ((b_SingleDiff == APCI3XXX_DIFF) && (devpriv->ps_BoardInfo->i_NbrAiChannelDiff == 0))) {
+ /*******************************/
+ /* Single/Diff selection error */
+ /*******************************/
+
+ printk("Single/Diff selection error\n");
+ i_ReturnValue = -1;
+ } else {
+ /**********************************/
+ /* Test if conversion not started */
+ /**********************************/
+
+ if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
+ devpriv->
+ ui_EocEosConversionTime
+ =
+ (UINT)
+ dw_ReloadValue;
+ devpriv->
+ b_EocEosConversionTimeBase
+ =
+ b_TimeBase;
+ devpriv->
+ b_SingelDiff
+ =
+ b_SingleDiff;
+ devpriv->
+ b_AiInitialisation
+ = 1;
+
+ /*******************************/
+ /* Set the convert timing unit */
+ /*******************************/
+
+ writel((DWORD)
+ b_TimeBase,
+ (void *)
+ (devpriv->
+ dw_AiBase
+ +
+ 36));
+
+ /**************************/
+ /* Set the convert timing */
+ /*************************/
+
+ writel(dw_ReloadValue, (void *)(devpriv->dw_AiBase + 32));
+ } else {
+ /**************************/
+ /* Any conversion started */
+ /**************************/
+
+ printk("Any conversion started\n");
+ i_ReturnValue =
+ -10;
+ }
+ }
+ } else {
+ /*******************************/
+ /* Single/Diff selection error */
+ /*******************************/
+
+ printk("Single/Diff selection error\n");
+ i_ReturnValue = -1;
+ }
+ } else {
+ /************************/
+ /* Time selection error */
+ /************************/
+
+ printk("Convert time value selection error\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /************************/
+ /* Time selection error */
+ /************************/
+
+ printk("Convert time value selection error\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*****************************/
+ /* Time base selection error */
+ /*****************************/
+
+ printk("Convert time base unity selection error\n");
+ i_ReturnValue = -2;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_InsnConfigAnalogInput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task Converting mode and convert time selection |
++----------------------------------------------------------------------------+
+| Input Parameters : b_ConvertMode = (BYTE) data[0]; |
+| b_TimeBase = (BYTE) data[1]; (0: ns, 1:micros 2:ms)|
+| dw_ReloadValue = (DWORD) data[2]; |
+| ........ |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :>0: No error |
+| .... |
+| -100 : Config command error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ switch ((BYTE) data[0]) {
+ case APCI3XXX_CONFIGURATION:
+ i_ReturnValue =
+ i_APCI3XXX_AnalogInputConfigOperatingMode(dev,
+ s, insn, data);
+ break;
+
+ default:
+ i_ReturnValue = -100;
+ printk("Config command error %d\n", data[0]);
+ break;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_InsnReadAnalogInput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task Read 1 analog input |
++----------------------------------------------------------------------------+
+| Input Parameters : b_Range = CR_RANGE(insn->chanspec); |
+| b_Channel = CR_CHAN(insn->chanspec); |
+| dw_NbrOfAcquisition = insn->n; |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :>0: No error |
+| -3 : Channel selection error |
+| -4 : Configuration selelection error |
+| -10: Any conversion started |
+| .... |
+| -100 : Config command error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec);
+ BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ DWORD dw_Temp = 0;
+ DWORD dw_Configuration = 0;
+ DWORD dw_AcquisitionCpt = 0;
+ BYTE b_Interrupt = 0;
+
+ /*************************************/
+ /* Test if operating mode configured */
+ /*************************************/
+
+ if (devpriv->b_AiInitialisation) {
+ /***************************/
+ /* Test the channel number */
+ /***************************/
+
+ if (((b_Channel < devpriv->ps_BoardInfo->i_NbrAiChannel)
+ && (devpriv->b_SingelDiff == APCI3XXX_SINGLE))
+ || ((b_Channel < devpriv->ps_BoardInfo->
+ i_NbrAiChannelDiff)
+ && (devpriv->b_SingelDiff == APCI3XXX_DIFF))) {
+ /**********************************/
+ /* Test the channel configuration */
+ /**********************************/
+
+ if (b_Configuration > 7) {
+ /***************************/
+ /* Channel not initialised */
+ /***************************/
+
+ i_ReturnValue = -4;
+ printk("Channel %d range %d selection error\n",
+ b_Channel, b_Configuration);
+ }
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ i_ReturnValue = -3;
+ printk("Channel %d selection error\n", b_Channel);
+ }
+
+ /**************************/
+ /* Test if no error occur */
+ /**************************/
+
+ if (i_ReturnValue >= 0) {
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if ((b_Interrupt != 0) || ((b_Interrupt == 0)
+ && (insn->n >= 1))) {
+ /**********************************/
+ /* Test if conversion not started */
+ /**********************************/
+
+ if (i_APCI3XXX_TestConversionStarted(dev) == 0) {
+ /******************/
+ /* Clear the FIFO */
+ /******************/
+
+ writel(0x10000UL,
+ (void *)(devpriv->dw_AiBase +
+ 12));
+
+ /*******************************/
+ /* Get and save the delay mode */
+ /*******************************/
+
+ dw_Temp =
+ readl((void *)(devpriv->
+ dw_AiBase + 4));
+ dw_Temp = dw_Temp & 0xFFFFFEF0UL;
+
+ /***********************************/
+ /* Channel configuration selection */
+ /***********************************/
+
+ writel(dw_Temp,
+ (void *)(devpriv->dw_AiBase +
+ 4));
+
+ /**************************/
+ /* Make the configuration */
+ /**************************/
+
+ dw_Configuration =
+ (b_Configuration & 3) |
+ ((DWORD) (b_Configuration >> 2)
+ << 6) | ((DWORD) devpriv->
+ b_SingelDiff << 7);
+
+ /***************************/
+ /* Write the configuration */
+ /***************************/
+
+ writel(dw_Configuration,
+ (void *)(devpriv->dw_AiBase +
+ 0));
+
+ /*********************/
+ /* Channel selection */
+ /*********************/
+
+ writel(dw_Temp | 0x100UL,
+ (void *)(devpriv->dw_AiBase +
+ 4));
+ writel((DWORD) b_Channel,
+ (void *)(devpriv->dw_AiBase +
+ 0));
+
+ /***********************/
+ /* Restaure delay mode */
+ /***********************/
+
+ writel(dw_Temp,
+ (void *)(devpriv->dw_AiBase +
+ 4));
+
+ /***********************************/
+ /* Set the number of sequence to 1 */
+ /***********************************/
+
+ writel(1,
+ (void *)(devpriv->dw_AiBase +
+ 48));
+
+ /***************************/
+ /* Save the interrupt flag */
+ /***************************/
+
+ devpriv->b_EocEosInterrupt =
+ b_Interrupt;
+
+ /*******************************/
+ /* Save the number of channels */
+ /*******************************/
+
+ devpriv->ui_AiNbrofChannels = 1;
+
+ /******************************/
+ /* Test if interrupt not used */
+ /******************************/
+
+ if (b_Interrupt == 0) {
+ for (dw_AcquisitionCpt = 0;
+ dw_AcquisitionCpt <
+ insn->n;
+ dw_AcquisitionCpt++) {
+ /************************/
+ /* Start the conversion */
+ /************************/
+
+ writel(0x80000UL,
+ (void *)
+ (devpriv->
+ dw_AiBase
+ + 8));
+
+ /****************/
+ /* Wait the EOS */
+ /****************/
+
+ do {
+ dw_Temp =
+ readl(
+ (void *)
+ (devpriv->
+ dw_AiBase
+ +
+ 20));
+ dw_Temp =
+ dw_Temp
+ & 1;
+ }
+ while (dw_Temp != 1);
+
+ /*************************/
+ /* Read the analog value */
+ /*************************/
+
+ data[dw_AcquisitionCpt]
+ =
+ (unsigned int)
+ readl((void
+ *)
+ (devpriv->
+ dw_AiBase
+ + 28));
+ }
+ } else {
+ /************************/
+ /* Start the conversion */
+ /************************/
+
+ writel(0x180000UL,
+ (void *)(devpriv->
+ dw_AiBase + 8));
+ }
+ } else {
+ /**************************/
+ /* Any conversion started */
+ /**************************/
+
+ printk("Any conversion started\n");
+ i_ReturnValue = -10;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+ }
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ printk("Operating mode not configured\n");
+ i_ReturnValue = -1;
+ }
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name : void v_APCI3XXX_Interrupt (int irq, |
+| void *d) |
++----------------------------------------------------------------------------+
+| Task :Interrupt handler for APCI3XXX |
+| When interrupt occurs this gets called. |
+| First it finds which interrupt has been generated and |
+| handles corresponding interrupt |
++----------------------------------------------------------------------------+
+| Input Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : - |
++----------------------------------------------------------------------------+
+*/
+
+void v_APCI3XXX_Interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ BYTE b_CopyCpt = 0;
+ DWORD dw_Status = 0;
+
+ /***************************/
+ /* Test if interrupt occur */
+ /***************************/
+
+ if (((dw_Status = readl((void *)(devpriv->dw_AiBase + 16))) & 0x2UL) ==
+ 0x2UL) {
+ /***********************/
+ /* Reset the interrupt */
+ /***********************/
+
+ writel(dw_Status, (void *)(devpriv->dw_AiBase + 16));
+
+ /*****************************/
+ /* Test if interrupt enabled */
+ /*****************************/
+
+ if (devpriv->b_EocEosInterrupt == 1) {
+ /********************************/
+ /* Read all analog inputs value */
+ /********************************/
+
+ for (b_CopyCpt = 0;
+ b_CopyCpt < devpriv->ui_AiNbrofChannels;
+ b_CopyCpt++) {
+ devpriv->ui_AiReadData[b_CopyCpt] =
+ (UINT) readl((void *)(devpriv->
+ dw_AiBase + 28));
+ }
+
+ /**************************/
+ /* Set the interrupt flag */
+ /**************************/
+
+ devpriv->b_EocEosInterrupt = 2;
+
+ /**********************************************/
+ /* Send a signal to from kernel to user space */
+ /**********************************************/
+
+ send_sig(SIGIO, devpriv->tsk_Current, 0);
+ }
+ }
+}
+
+/*
++----------------------------------------------------------------------------+
+| ANALOG OUTPUT SUBDEVICE |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_InsnWriteAnalogOutput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task Read 1 analog input |
++----------------------------------------------------------------------------+
+| Input Parameters : b_Range = CR_RANGE(insn->chanspec); |
+| b_Channel = CR_CHAN(insn->chanspec); |
+| data[0] = analog value; |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :>0: No error |
+| -3 : Channel selection error |
+| -4 : Configuration selelection error |
+| .... |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec);
+ BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ DWORD dw_Status = 0;
+ INT i_ReturnValue = insn->n;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /***************************/
+ /* Test the channel number */
+ /***************************/
+
+ if (b_Channel < devpriv->ps_BoardInfo->i_NbrAoChannel) {
+ /**********************************/
+ /* Test the channel configuration */
+ /**********************************/
+
+ if (b_Range < 2) {
+ /***************************/
+ /* Set the range selection */
+ /***************************/
+
+ writel(b_Range,
+ (void *)(devpriv->dw_AiBase + 96));
+
+ /**************************************************/
+ /* Write the analog value to the selected channel */
+ /**************************************************/
+
+ writel((data[0] << 8) | b_Channel,
+ (void *)(devpriv->dw_AiBase + 100));
+
+ /****************************/
+ /* Wait the end of transfer */
+ /****************************/
+
+ do {
+ dw_Status =
+ readl((void *)(devpriv->
+ dw_AiBase + 96));
+ }
+ while ((dw_Status & 0x100) != 0x100);
+ } else {
+ /***************************/
+ /* Channel not initialised */
+ /***************************/
+
+ i_ReturnValue = -4;
+ printk("Channel %d range %d selection error\n",
+ b_Channel, b_Range);
+ }
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ i_ReturnValue = -3;
+ printk("Channel %d selection error\n", b_Channel);
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| TTL FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_InsnConfigInitTTLIO |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task You must calling this function be |
+| for you call any other function witch access of TTL. |
+| APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)|
++----------------------------------------------------------------------------+
+| Input Parameters : b_InitType = (BYTE) data[0]; |
+| b_Port2Mode = (BYTE) data[1]; |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value :>0: No error |
+| -1: Port 2 mode selection is wrong |
+| .... |
+| -100 : Config command error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Command = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /*******************/
+ /* Get the command */
+ /* **************** */
+
+ b_Command = (BYTE) data[0];
+
+ /********************/
+ /* Test the command */
+ /********************/
+
+ if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
+ /***************************************/
+ /* Test the initialisation buffer size */
+ /***************************************/
+
+ if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)
+ && (insn->n != 2)) {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+ } else {
+ /************************/
+ /* Config command error */
+ /************************/
+
+ printk("Command selection error\n");
+ i_ReturnValue = -100;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ /*********************************************************************************/
+ /* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */
+ /*********************************************************************************/
+
+ if ((i_ReturnValue >= 0)
+ && (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) {
+ /**********************/
+ /* Test the direction */
+ /**********************/
+
+ if ((data[1] == 0) || (data[1] == 0xFF)) {
+ /**************************/
+ /* Save the configuration */
+ /**************************/
+
+ devpriv->ul_TTLPortConfiguration[0] =
+ devpriv->ul_TTLPortConfiguration[0] | data[1];
+ } else {
+ /************************/
+ /* Port direction error */
+ /************************/
+
+ printk("Port 2 direction selection error\n");
+ i_ReturnValue = -1;
+ }
+ }
+
+ /**************************/
+ /* Test if no error occur */
+ /**************************/
+
+ if (i_ReturnValue >= 0) {
+ /***********************************/
+ /* Test if TTL port initilaisation */
+ /***********************************/
+
+ if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) {
+ /*************************/
+ /* Set the configuration */
+ /*************************/
+
+ outl(data[1], devpriv->iobase + 224);
+ }
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| TTL INPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_InsnBitsTTLIO |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Write the selected output mask and read the status from|
+| all TTL channles |
++----------------------------------------------------------------------------+
+| Input Parameters : dw_ChannelMask = data [0]; |
+| dw_BitMask = data [1]; |
++----------------------------------------------------------------------------+
+| Output Parameters : data[1] : All TTL channles states |
++----------------------------------------------------------------------------+
+| Return Value : >0 : No error |
+| -4 : Channel mask error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_ChannelCpt = 0;
+ DWORD dw_ChannelMask = 0;
+ DWORD dw_BitMask = 0;
+ DWORD dw_Status = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 2) {
+ /*******************************/
+ /* Get the channe and bit mask */
+ /*******************************/
+
+ dw_ChannelMask = data[0];
+ dw_BitMask = data[1];
+
+ /*************************/
+ /* Test the channel mask */
+ /*************************/
+
+ if (((dw_ChannelMask & 0XFF00FF00) == 0) &&
+ (((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF)
+ || (((devpriv->ul_TTLPortConfiguration[0] &
+ 0xFF) == 0)
+ && ((dw_ChannelMask & 0XFF0000) ==
+ 0)))) {
+ /*********************************/
+ /* Test if set/reset any channel */
+ /*********************************/
+
+ if (dw_ChannelMask) {
+ /****************************************/
+ /* Test if set/rest any port 0 channels */
+ /****************************************/
+
+ if (dw_ChannelMask & 0xFF) {
+ /*******************************************/
+ /* Read port 0 (first digital output port) */
+ /*******************************************/
+
+ dw_Status = inl(devpriv->iobase + 80);
+
+ for (b_ChannelCpt = 0; b_ChannelCpt < 8;
+ b_ChannelCpt++) {
+ if ((dw_ChannelMask >>
+ b_ChannelCpt) &
+ 1) {
+ dw_Status =
+ (dw_Status &
+ (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
+ }
+ }
+
+ outl(dw_Status, devpriv->iobase + 80);
+ }
+
+ /****************************************/
+ /* Test if set/rest any port 2 channels */
+ /****************************************/
+
+ if (dw_ChannelMask & 0xFF0000) {
+ dw_BitMask = dw_BitMask >> 16;
+ dw_ChannelMask = dw_ChannelMask >> 16;
+
+ /********************************************/
+ /* Read port 2 (second digital output port) */
+ /********************************************/
+
+ dw_Status = inl(devpriv->iobase + 112);
+
+ for (b_ChannelCpt = 0; b_ChannelCpt < 8;
+ b_ChannelCpt++) {
+ if ((dw_ChannelMask >>
+ b_ChannelCpt) &
+ 1) {
+ dw_Status =
+ (dw_Status &
+ (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
+ }
+ }
+
+ outl(dw_Status, devpriv->iobase + 112);
+ }
+ }
+
+ /*******************************************/
+ /* Read port 0 (first digital output port) */
+ /*******************************************/
+
+ data[1] = inl(devpriv->iobase + 80);
+
+ /******************************************/
+ /* Read port 1 (first digital input port) */
+ /******************************************/
+
+ data[1] = data[1] | (inl(devpriv->iobase + 64) << 8);
+
+ /************************/
+ /* Test if port 2 input */
+ /************************/
+
+ if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) {
+ data[1] =
+ data[1] | (inl(devpriv->iobase +
+ 96) << 16);
+ } else {
+ data[1] =
+ data[1] | (inl(devpriv->iobase +
+ 112) << 16);
+ }
+ } else {
+ /************************/
+ /* Config command error */
+ /************************/
+
+ printk("Channel mask error\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_InsnReadTTLIO |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read the status from selected channel |
++----------------------------------------------------------------------------+
+| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Selected TTL channel state |
++----------------------------------------------------------------------------+
+| Return Value : 0 : No error |
+| -3 : Channel selection error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ INT i_ReturnValue = insn->n;
+ unsigned int *pls_ReadData = data;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /***********************/
+ /* Test if read port 0 */
+ /***********************/
+
+ if (b_Channel < 8) {
+ /*******************************************/
+ /* Read port 0 (first digital output port) */
+ /*******************************************/
+
+ pls_ReadData[0] = inl(devpriv->iobase + 80);
+ pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1;
+ } else {
+ /***********************/
+ /* Test if read port 1 */
+ /***********************/
+
+ if ((b_Channel > 7) && (b_Channel < 16)) {
+ /******************************************/
+ /* Read port 1 (first digital input port) */
+ /******************************************/
+
+ pls_ReadData[0] = inl(devpriv->iobase + 64);
+ pls_ReadData[0] =
+ (pls_ReadData[0] >> (b_Channel -
+ 8)) & 1;
+ } else {
+ /***********************/
+ /* Test if read port 2 */
+ /***********************/
+
+ if ((b_Channel > 15) && (b_Channel < 24)) {
+ /************************/
+ /* Test if port 2 input */
+ /************************/
+
+ if ((devpriv->ul_TTLPortConfiguration[0]
+ & 0xFF) == 0) {
+ pls_ReadData[0] =
+ inl(devpriv->iobase +
+ 96);
+ pls_ReadData[0] =
+ (pls_ReadData[0] >>
+ (b_Channel - 16)) & 1;
+ } else {
+ pls_ReadData[0] =
+ inl(devpriv->iobase +
+ 112);
+ pls_ReadData[0] =
+ (pls_ReadData[0] >>
+ (b_Channel - 16)) & 1;
+ }
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ i_ReturnValue = -3;
+ printk("Channel %d selection error\n",
+ b_Channel);
+ }
+ }
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| TTL OUTPUT FUNCTIONS |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : INT i_APCI3XXX_InsnWriteTTLIO |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Set the state from TTL output channel |
++----------------------------------------------------------------------------+
+| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
+| b_State = data [0] |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : 0 : No error |
+| -3 : Channel selection error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ BYTE b_State = 0;
+ DWORD dw_Status = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ b_State = (BYTE) data[0];
+
+ /***********************/
+ /* Test if read port 0 */
+ /***********************/
+
+ if (b_Channel < 8) {
+ /*****************************************************************************/
+ /* Read port 0 (first digital output port) and set/reset the selcted channel */
+ /*****************************************************************************/
+
+ dw_Status = inl(devpriv->iobase + 80);
+ dw_Status =
+ (dw_Status & (0xFF -
+ (1 << b_Channel))) | ((b_State & 1) <<
+ b_Channel);
+ outl(dw_Status, devpriv->iobase + 80);
+ } else {
+ /***********************/
+ /* Test if read port 2 */
+ /***********************/
+
+ if ((b_Channel > 15) && (b_Channel < 24)) {
+ /*************************/
+ /* Test if port 2 output */
+ /*************************/
+
+ if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
+ == 0xFF) {
+ /*****************************************************************************/
+ /* Read port 2 (first digital output port) and set/reset the selcted channel */
+ /*****************************************************************************/
+
+ dw_Status = inl(devpriv->iobase + 112);
+ dw_Status =
+ (dw_Status & (0xFF -
+ (1 << (b_Channel -
+ 16)))) |
+ ((b_State & 1) << (b_Channel -
+ 16));
+ outl(dw_Status, devpriv->iobase + 112);
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ i_ReturnValue = -3;
+ printk("Channel %d selection error\n",
+ b_Channel);
+ }
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ i_ReturnValue = -3;
+ printk("Channel %d selection error\n",
+ b_Channel);
+ }
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| DIGITAL INPUT SUBDEVICE |
++----------------------------------------------------------------------------+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3XXX_InsnReadDigitalInput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Reads the value of the specified Digital input channel |
++----------------------------------------------------------------------------+
+| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) (0 to 3) |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Channel value |
++----------------------------------------------------------------------------+
+| Return Value : 0 : No error |
+| -3 : Channel selection error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec);
+ DWORD dw_Temp = 0;
+
+ /***************************/
+ /* Test the channel number */
+ /***************************/
+
+ if (b_Channel <= devpriv->ps_BoardInfo->i_NbrDiChannel) {
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ dw_Temp = inl(devpriv->iobase + 32);
+ *data = (dw_Temp >> b_Channel) & 1;
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ printk("Channel selection error\n");
+ i_ReturnValue = -3;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3XXX_InsnBitsDigitalInput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Reads the value of the Digital input Port i.e.4channels|
++----------------------------------------------------------------------------+
+| Input Parameters : - |
++----------------------------------------------------------------------------+
+| Output Parameters : data[0] : Port value |
++----------------------------------------------------------------------------+
+| Return Value :>0: No error |
+| .... |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ DWORD dw_Temp = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ dw_Temp = inl(devpriv->iobase + 32);
+ *data = dw_Temp & 0xf;
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| DIGITAL OUTPUT SUBDEVICE |
++----------------------------------------------------------------------------+
+
+*/
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3XXX_InsnBitsDigitalOutput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Write the selected output mask and read the status from|
+| all digital output channles |
++----------------------------------------------------------------------------+
+| Input Parameters : dw_ChannelMask = data [0]; |
+| dw_BitMask = data [1]; |
++----------------------------------------------------------------------------+
+| Output Parameters : data[1] : All digital output channles states |
++----------------------------------------------------------------------------+
+| Return Value : >0 : No error |
+| -4 : Channel mask error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_ChannelCpt = 0;
+ DWORD dw_ChannelMask = 0;
+ DWORD dw_BitMask = 0;
+ DWORD dw_Status = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 2) {
+ /*******************************/
+ /* Get the channe and bit mask */
+ /*******************************/
+
+ dw_ChannelMask = data[0];
+ dw_BitMask = data[1];
+
+ /*************************/
+ /* Test the channel mask */
+ /*************************/
+
+ if ((dw_ChannelMask & 0XFFFFFFF0) == 0) {
+ /*********************************/
+ /* Test if set/reset any channel */
+ /*********************************/
+
+ if (dw_ChannelMask & 0xF) {
+ /********************************/
+ /* Read the digital output port */
+ /********************************/
+
+ dw_Status = inl(devpriv->iobase + 48);
+
+ for (b_ChannelCpt = 0; b_ChannelCpt < 4;
+ b_ChannelCpt++) {
+ if ((dw_ChannelMask >> b_ChannelCpt) &
+ 1) {
+ dw_Status =
+ (dw_Status & (0xF -
+ (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
+ }
+ }
+
+ outl(dw_Status, devpriv->iobase + 48);
+ }
+
+ /********************************/
+ /* Read the digital output port */
+ /********************************/
+
+ data[1] = inl(devpriv->iobase + 48);
+ } else {
+ /************************/
+ /* Config command error */
+ /************************/
+
+ printk("Channel mask error\n");
+ i_ReturnValue = -4;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3XXX_InsnWriteDigitalOutput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Set the state from digital output channel |
++----------------------------------------------------------------------------+
+| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
+| b_State = data [0] |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : >0 : No error |
+| -3 : Channel selection error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Channel = CR_CHAN(insn->chanspec);
+ BYTE b_State = 0;
+ DWORD dw_Status = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /***************************/
+ /* Test the channel number */
+ /***************************/
+
+ if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
+ /*******************/
+ /* Get the command */
+ /*******************/
+
+ b_State = (BYTE) data[0];
+
+ /********************************/
+ /* Read the digital output port */
+ /********************************/
+
+ dw_Status = inl(devpriv->iobase + 48);
+
+ dw_Status =
+ (dw_Status & (0xF -
+ (1 << b_Channel))) | ((b_State & 1) <<
+ b_Channel);
+ outl(dw_Status, devpriv->iobase + 48);
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ printk("Channel selection error\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function name :int i_APCI3XXX_InsnReadDigitalOutput |
+| (struct comedi_device *dev, |
+| struct comedi_subdevice *s, |
+| struct comedi_insn *insn, |
+| unsigned int *data) |
++----------------------------------------------------------------------------+
+| Task : Read the state from digital output channel |
++----------------------------------------------------------------------------+
+| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) |
++----------------------------------------------------------------------------+
+| Output Parameters : b_State = data [0] |
++----------------------------------------------------------------------------+
+| Return Value : >0 : No error |
+| -3 : Channel selection error |
+| -101 : Data size error |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev,
+ struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data)
+{
+ INT i_ReturnValue = insn->n;
+ BYTE b_Channel = CR_CHAN(insn->chanspec);
+ DWORD dw_Status = 0;
+
+ /************************/
+ /* Test the buffer size */
+ /************************/
+
+ if (insn->n >= 1) {
+ /***************************/
+ /* Test the channel number */
+ /***************************/
+
+ if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) {
+ /********************************/
+ /* Read the digital output port */
+ /********************************/
+
+ dw_Status = inl(devpriv->iobase + 48);
+
+ dw_Status = (dw_Status >> b_Channel) & 1;
+ *data = dw_Status;
+ } else {
+ /***************************/
+ /* Channel selection error */
+ /***************************/
+
+ printk("Channel selection error\n");
+ i_ReturnValue = -3;
+ }
+ } else {
+ /*******************/
+ /* Data size error */
+ /*******************/
+
+ printk("Buffer size error\n");
+ i_ReturnValue = -101;
+ }
+
+ return (i_ReturnValue);
+}
+
+/*
++----------------------------------------------------------------------------+
+| Function Name : int i_APCI3XXX_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+
+| Task :resets all the registers |
++----------------------------------------------------------------------------+
+| Input Parameters : struct comedi_device *dev |
++----------------------------------------------------------------------------+
+| Output Parameters : - |
++----------------------------------------------------------------------------+
+| Return Value : - |
++----------------------------------------------------------------------------+
+*/
+
+int i_APCI3XXX_Reset(struct comedi_device * dev)
+{
+ unsigned char b_Cpt = 0;
+
+ /*************************/
+ /* Disable the interrupt */
+ /*************************/
+
+ disable_irq(dev->irq);
+
+ /****************************/
+ /* Reset the interrupt flag */
+ /****************************/
+
+ devpriv->b_EocEosInterrupt = 0;
+
+ /***************************/
+ /* Clear the start command */
+ /***************************/
+
+ writel(0, (void *)(devpriv->dw_AiBase + 8));
+
+ /*****************************/
+ /* Reset the interrupt flags */
+ /*****************************/
+
+ writel(readl((void *)(devpriv->dw_AiBase + 16)),
+ (void *)(devpriv->dw_AiBase + 16));
+
+ /*****************/
+ /* clear the EOS */
+ /*****************/
+
+ readl((void *)(devpriv->dw_AiBase + 20));
+
+ /******************/
+ /* Clear the FIFO */
+ /******************/
+
+ for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
+ readl((void *)(devpriv->dw_AiBase + 28));
+ }
+
+ /************************/
+ /* Enable the interrupt */
+ /************************/
+
+ enable_irq(dev->irq);
+
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
new file mode 100644
index 000000000000..788d7c1cf5c1
--- /dev/null
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */
+#endif
+
+#ifndef ADDIDATA_ENABLE
+#define ADDIDATA_ENABLE 1
+#define ADDIDATA_DISABLE 0
+#endif
+
+#define APCI3XXX_SINGLE 0
+#define APCI3XXX_DIFF 1
+#define APCI3XXX_CONFIGURATION 0
+
+#define APCI3XXX_TTL_INIT_DIRECTION_PORT2 0
+
+#ifdef __KERNEL__
+
+static const struct comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2),
+ BIP_RANGE(1),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2),
+ UNI_RANGE(1)}
+};
+
+static const struct comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1),
+ BIP_RANGE(1)}
+};
+
+static const struct comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10),
+ UNI_RANGE(10)}
+};
+#endif