From e507a699b7f63e1f59390b5cc5d5ab48f3714d27 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Mon, 11 Aug 2003 18:32:00 +0000 Subject: [PATCH] driver(s) from ADDI-DATA --- comedi/drivers/addi-data/APCI1710_82x54.c | 1521 ++++++ comedi/drivers/addi-data/APCI1710_82x54.h | 69 + comedi/drivers/addi-data/APCI1710_Chrono.c | 1828 +++++++ comedi/drivers/addi-data/APCI1710_Chrono.h | 78 + comedi/drivers/addi-data/APCI1710_Dig_io.c | 988 ++++ comedi/drivers/addi-data/APCI1710_Dig_io.h | 38 + comedi/drivers/addi-data/APCI1710_INCCPT.c | 5376 +++++++++++++++++++ comedi/drivers/addi-data/APCI1710_INCCPT.h | 308 ++ comedi/drivers/addi-data/APCI1710_Inp_cpt.c | 760 +++ comedi/drivers/addi-data/APCI1710_Inp_cpt.h | 38 + comedi/drivers/addi-data/APCI1710_Pwm.c | 2517 +++++++++ comedi/drivers/addi-data/APCI1710_Pwm.h | 78 + comedi/drivers/addi-data/APCI1710_Ssi.c | 766 +++ comedi/drivers/addi-data/APCI1710_Ssi.h | 40 + comedi/drivers/addi-data/APCI1710_Tor.c | 1737 ++++++ comedi/drivers/addi-data/APCI1710_Tor.h | 56 + comedi/drivers/addi-data/APCI1710_Ttl.c | 961 ++++ comedi/drivers/addi-data/APCI1710_Ttl.h | 39 + comedi/drivers/addi-data/Makefile.am | 8 + comedi/drivers/addi-data/addi_amcc_s5933.h | 447 ++ comedi/drivers/addi-data/addi_common.c | 1154 ++++ comedi/drivers/addi-data/addi_common.h | 475 ++ comedi/drivers/addi-data/addi_eeprom.c | 884 +++ comedi/drivers/addi-data/amcc_s5933_58.h | 438 ++ comedi/drivers/addi-data/hwdrv_APCI1710.c | 1077 ++++ comedi/drivers/addi-data/hwdrv_APCI1710.h | 78 + comedi/drivers/addi-data/hwdrv_apci035.c | 600 +++ comedi/drivers/addi-data/hwdrv_apci035.h | 124 + comedi/drivers/addi-data/hwdrv_apci1032.c | 267 + comedi/drivers/addi-data/hwdrv_apci1032.h | 59 + comedi/drivers/addi-data/hwdrv_apci1500.c | 2726 ++++++++++ comedi/drivers/addi-data/hwdrv_apci1500.h | 126 + comedi/drivers/addi-data/hwdrv_apci1516.c | 484 ++ comedi/drivers/addi-data/hwdrv_apci1516.h | 51 + comedi/drivers/addi-data/hwdrv_apci1564.c | 930 ++++ comedi/drivers/addi-data/hwdrv_apci1564.h | 91 + comedi/drivers/addi-data/hwdrv_apci2016.c | 407 ++ comedi/drivers/addi-data/hwdrv_apci2016.h | 53 + comedi/drivers/addi-data/hwdrv_apci2032.c | 561 ++ comedi/drivers/addi-data/hwdrv_apci2032.h | 62 + comedi/drivers/addi-data/hwdrv_apci2200.c | 492 ++ comedi/drivers/addi-data/hwdrv_apci2200.h | 48 + comedi/drivers/addi-data/hwdrv_apci3120.c | 2441 +++++++++ comedi/drivers/addi-data/hwdrv_apci3120.h | 260 + comedi/drivers/addi-data/hwdrv_apci3200.c | 2414 +++++++++ comedi/drivers/addi-data/hwdrv_apci3200.h | 109 + comedi/drivers/addi-data/hwdrv_apci3501.c | 706 +++ comedi/drivers/addi-data/hwdrv_apci3501.h | 71 + 48 files changed, 34841 insertions(+) create mode 100644 comedi/drivers/addi-data/APCI1710_82x54.c create mode 100644 comedi/drivers/addi-data/APCI1710_82x54.h create mode 100644 comedi/drivers/addi-data/APCI1710_Chrono.c create mode 100644 comedi/drivers/addi-data/APCI1710_Chrono.h create mode 100644 comedi/drivers/addi-data/APCI1710_Dig_io.c create mode 100644 comedi/drivers/addi-data/APCI1710_Dig_io.h create mode 100644 comedi/drivers/addi-data/APCI1710_INCCPT.c create mode 100644 comedi/drivers/addi-data/APCI1710_INCCPT.h create mode 100644 comedi/drivers/addi-data/APCI1710_Inp_cpt.c create mode 100644 comedi/drivers/addi-data/APCI1710_Inp_cpt.h create mode 100644 comedi/drivers/addi-data/APCI1710_Pwm.c create mode 100644 comedi/drivers/addi-data/APCI1710_Pwm.h create mode 100644 comedi/drivers/addi-data/APCI1710_Ssi.c create mode 100644 comedi/drivers/addi-data/APCI1710_Ssi.h create mode 100644 comedi/drivers/addi-data/APCI1710_Tor.c create mode 100644 comedi/drivers/addi-data/APCI1710_Tor.h create mode 100644 comedi/drivers/addi-data/APCI1710_Ttl.c create mode 100644 comedi/drivers/addi-data/APCI1710_Ttl.h create mode 100644 comedi/drivers/addi-data/Makefile.am create mode 100644 comedi/drivers/addi-data/addi_amcc_s5933.h create mode 100644 comedi/drivers/addi-data/addi_common.c create mode 100644 comedi/drivers/addi-data/addi_common.h create mode 100644 comedi/drivers/addi-data/addi_eeprom.c create mode 100644 comedi/drivers/addi-data/amcc_s5933_58.h create mode 100644 comedi/drivers/addi-data/hwdrv_APCI1710.c create mode 100644 comedi/drivers/addi-data/hwdrv_APCI1710.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci035.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci035.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci1032.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci1032.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci1500.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci1500.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci1516.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci1516.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci1564.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci1564.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci2016.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci2016.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci2032.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci2032.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci2200.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci2200.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci3120.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci3120.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci3200.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci3200.h create mode 100644 comedi/drivers/addi-data/hwdrv_apci3501.c create mode 100644 comedi/drivers/addi-data/hwdrv_apci3501.h diff --git a/comedi/drivers/addi-data/APCI1710_82x54.c b/comedi/drivers/addi-data/APCI1710_82x54.c new file mode 100644 index 00000000..6cbe9eff --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_82x54.c @@ -0,0 +1,1521 @@ +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : 82X54.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 29.06.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 82X54 timer module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 29/06/98 | S. Weber | Digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | | | | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + + +#include "APCI1710_82x54.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitTimer | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| BYTE_ b_TimerMode, | +| ULONG_ ul_ReloadValue, | +| BYTE_ b_InputClockSelection, | +| BYTE_ b_InputClockLevel, | +| BYTE_ b_OutputLevel, | +| BYTE_ b_HardwareGateLevel) +INT i_InsnConfig_InitTimer(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +| ++----------------------------------------------------------------------------+ +| Task : Configure the Timer (b_TimerNbr) operating mode | +| (b_TimerMode) from selected module (b_ModulNbr). | +| You must calling this function be for you call any | +| other function witch access of the timer. | +| | +| | +| Timer mode description table | +| | +|+--------+-----------------------------+--------------+--------------------+| +||Selected+ Mode description +u_ReloadValue | Hardware gate input|| +|| mode | | description | action || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 0 is typically used | | || +|| |for event counting. After | | || +|| |the initialisation, OUT | | || +|| |is initially low, and | | || +|| 0 |will remain low until the |Start counting| Hardware gate || +|| |counter reaches zero. | value | || +|| |OUT then goes high and | | || +|| |remains high until a new | | || +|| |count is written. See | | || +|| |"i_APCI1710_WriteTimerValue" | | || +|| |function. | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 1 is similar to mode 0 | | || +|| |except for the gate input | | || +|| 1 |action. The gate input is not|Start counting| Hardware trigger || +|| |used for enabled or disabled | value | || +|| |the timer. | | || +|| |The gate input is used for | | || +|| |triggered the timer. | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |This mode functions like a | | || +|| |divide-by-ul_ReloadValue | | || +|| |counter. It is typically used| | || +|| |to generate a real time clock| | || +|| |interrupt. OUT will initially| | || +|| 2 |be high after the | Division | Hardware gate || +|| |initialisation. When the | factor | || +|| |initial count has decremented| | || +|| |to 1, OUT goes low for one | | || +|| |CLK pule. OUT then goes high | | || +|| |again, the counter reloads | | || +|| |the initial count | | || +|| |(ul_ReloadValue) and the | | || +|| |process is repeated. | | || +|| |This action can generated a | | || +|| |interrupt. See function | | || +|| |"i_APCI1710_SetBoardInt- | | || +|| |RoutineX" | | || +|| |and "i_APCI1710_EnableTimer" | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 3 is typically used for | | || +|| |baud rate generation. This | | || +|| |mode is similar to mode 2 | | || +|| |except for the duty cycle of | | || +|| 3 |OUT. OUT will initially be | Division | Hardware gate || +|| |high after the initialisation| factor | || +|| |When half the initial count | | || +|| |(ul_ReloadValue) has expired,| | || +|| |OUT goes low for the | | || +|| |remainder of the count. The | | || +|| |mode is periodic; the | | || +|| |sequence above is repeated | | || +|| |indefinitely. | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |OUT will be initially high | | || +|| |after the initialisation. | | || +|| |When the initial count | | || +|| 4 |expires OUT will go low for |Start counting| Hardware gate || +|| |one CLK pulse and then go | value | || +|| |high again. | | || +|| |The counting sequences is | | || +|| |triggered by writing a new | | || +|| |value. See | | || +|| |"i_APCI1710_WriteTimerValue" | | || +|| |function. If a new count is | | || +|| |written during counting, | | || +|| |it will be loaded on the | | || +|| |next CLK pulse | | || +|+--------+-----------------------------+--------------+--------------------+| +|| |Mode 5 is similar to mode 4 | | || +|| |except for the gate input | | || +|| |action. The gate input is not| | || +|| 5 |used for enabled or disabled |Start counting| Hardware trigger || +|| |the timer. The gate input is | value | || +|| |used for triggered the timer.| | || +|+--------+-----------------------------+--------------+--------------------+| +| | +| | +| | +| Input clock selection table | +| | +| +--------------------------------+------------------------------------+ | +| | b_InputClockSelection | Description | | +| | parameter | | | +| +--------------------------------+------------------------------------+ | +| | APCI1710_PCI_BUS_CLOCK | For the timer input clock, the PCI | | +| | | bus clock / 4 is used. This PCI bus| | +| | | clock can be 30MHz or 33MHz. For | | +| | | Timer 0 only this selection are | | +| | | available. | | +| +--------------------------------+------------------------------------+ | +| | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the| | +| | | possibility to inject a input clock| | +| | | for Timer 1 or Timer 2. The source | | +| | | from this clock can eat the output | | +| | | clock from Timer 0 or any other | | +| | | clock source. | | +| +--------------------------------+------------------------------------+ | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to | +| configure (0 to 2) | +| BYTE_ b_TimerMode : Timer mode selection | +| (0 to 5) | +| 0: Interrupt on terminal| +| count | +| 1: Hardware | +| retriggerable one- | +| shot | +| 2: Rate generator | +| 3: Square wave mode | +| 4: Software triggered | +| strobe | +| 5: Hardware triggered | +| strobe | +| See timer mode | +| description table. | +| ULONG_ ul_ReloadValue : Start counting value | +| or division factor | +| See timer mode | +| description table. | +| BYTE_ b_InputClockSelection : Selection from input | +| timer clock. | +| See input clock | +| selection table. | +| BYTE_ b_InputClockLevel : Selection from input | +| clock level. | +| 0 : Low active | +| (Input inverted) | +| 1 : High active | +| BYTE_ b_OutputLevel, : Selection from output | +| clock level. | +| 0 : Low active | +| 1 : High active | +| (Output inverted) | +| BYTE_ b_HardwareGateLevel : Selection from | +| hardware gate level. | +| 0 : Low active | +| (Input inverted) | +| 1 : High active | +| If you will not used | +| the hardware gate set | +| this value to 0. +|b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec); + b_TimerMode = (BYTE) data[0]; + ul_ReloadValue = (ULONG) data[1]; + b_InputClockSelection =(BYTE) data[2]; + b_InputClockLevel =(BYTE) data[3]; + b_OutputLevel =(BYTE) data[4]; + b_HardwareGateLevel =(BYTE) data[5]; ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer mode selection is wrong | +| -6: Input timer clock selection is wrong | +| -7: Selection from input clock level is wrong | +| -8: Selection from output clock level is wrong | +| -9: Selection from hardware gate level is wrong | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnConfigInitTimer(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + + INT i_ReturnValue = 0; + BYTE b_ModulNbr; + BYTE b_TimerNbr; + BYTE b_TimerMode; + ULONG ul_ReloadValue; + BYTE b_InputClockSelection; + BYTE b_InputClockLevel; + BYTE b_OutputLevel; + BYTE b_HardwareGateLevel; + + 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 >= 0) && (b_TimerNbr <= 2)) + { + /***********************/ + /* Test the timer mode */ + /***********************/ + + if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) + { + /*********************************/ + /* Test te imput clock selection */ + /*********************************/ + + if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) || + ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1)))) + { + /****************************************/ + /* 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)) + { + /*********************/ + /* 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 */ + /****************************************************/ + 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)); + + + 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)); + + } // 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; + } + } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) + else + { + /*********************************/ + /* Timer mode selection is wrong */ + /*********************************/ + DPRINTK("Timer mode selection is wrong\n"); + i_ReturnValue = -5; + } // if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + else + { + /*************************/ + /* Timer selection wrong */ + /*************************/ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } + else + { + /************************************/ + /* The module is not a TIMER module */ + /************************************/ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableTimer | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| BYTE_ b_InterruptEnable) +INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Enable OR Disable the Timer (b_TimerNbr) from selected module | +| (b_ModulNbr). You must calling the | +| "i_APCI1710_InitTimer" function be for you call this | +| function. If you enable the timer interrupt, the timer | +| generate a interrupt after the timer value reach | +| the zero. See function "i_APCI1710_SetBoardIntRoutineX"| ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to enable | +| (0 to 2) | +| BYTE_ b_InterruptEnable : Enable or disable the | +| timer interrupt. | +| APCI1710_ENABLE : | +| Enable the timer interrupt | +| APCI1710_DISABLE : | +| Disable the timer interrupt| +i_ReturnValue=insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec); + b_ActionType = (BYTE) data[0]; // enable disable ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | +| -6: Interrupt parameter is wrong | +| -7: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_DummyRead; + BYTE b_ModulNbr; + BYTE b_TimerNbr; + BYTE b_ActionType; + BYTE b_InterruptEnable; + + i_ReturnValue=insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_TimerNbr = (BYTE) CR_CHAN(insn->chanspec); + b_ActionType = (BYTE) data[0]; // enable disable + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) + { + /*************************/ + /* Test the timer number */ + /*************************/ + + if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + { + /*****************************/ + /* Test if timer initialised */ + /*****************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + b_82X54Init == 1) + { + + switch(b_ActionType) + { + case APCI1710_ENABLE: + + b_InterruptEnable = (BYTE) data[1]; + /********************************/ + /* Test the interrupt selection */ + /********************************/ + + if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) + { + if (b_InterruptEnable == APCI1710_ENABLE) + { + + dw_DummyRead=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /************************/ + /* Enable the interrupt */ + /************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord = devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord | 0x8; + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord,devpriv->s_BoardInfos. + ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + devpriv->tsk_Current=current; // Save the current process task structure + + + } // if (b_InterruptEnable == APCI1710_ENABLE) + else + { + /*************************/ + /* Disable the interrupt */ + /*************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord = devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord & 0xF7; + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord,devpriv->s_BoardInfos. + ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /***************************/ + /* Save the interrupt flag */ + /***************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + b_InterruptMask = devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + b_InterruptMask & (0xFF - (1 << b_TimerNbr)); + } // if (b_InterruptEnable == APCI1710_ENABLE) + + /***********************/ + /* Test if error occur */ + /***********************/ + + if (i_ReturnValue >= 0) + { + /***************************/ + /* Save the interrupt flag */ + /***************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + b_InterruptMask = devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + b_InterruptMask | ((1 & b_InterruptEnable) << b_TimerNbr); + + + /********************/ + /* Enable the timer */ + /********************/ + + + outl(1,devpriv->s_BoardInfos. + ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + } + } + else + { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + DPRINTK("\n"); + i_ReturnValue = -6; + } + break; + case APCI1710_DISABLE: + /***************************/ + /* Test the interrupt flag */ + /***************************/ + + if (((devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + b_InterruptMask >> b_TimerNbr) & 1) == 1) + { + /*************************/ + /* Disable the interrupt */ + /*************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord = devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord & 0xF7; + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + dw_ConfigurationWord,devpriv->s_BoardInfos. + ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + /***************************/ + /* Save the interrupt flag */ + /***************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + b_InterruptMask = devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr)); + } + + /*********************/ + /* Disable the timer */ + /*********************/ + + + outl(0,devpriv->s_BoardInfos. + ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + break; + }// Switch end + } + else + { + /**************************************/ + /* Timer not initialised see function */ + /**************************************/ + DPRINTK("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } + else + { + /*************************/ + /* Timer selection wrong */ + /*************************/ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } + else + { + /************************************/ + /* The module is not a TIMER module */ + /************************************/ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadAllTimerValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PULONG_ pul_TimerValueArray) +INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the all timer values from selected timer | +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_TimerValueArray : Timer value array. | +| Element 0 contain the timer 0 value. | +| Element 1 contain the timer 1 value. | +| Element 2 contain the timer 2 value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a TIMER module | +| -4: Timer 0 not initialised see function | +| "i_APCI1710_InitTimer" | +| -5: Timer 1 not initialised see function | +| "i_APCI1710_InitTimer" | +| -6: Timer 2 not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + BYTE b_ModulNbr,b_ReadType; + PULONG pul_TimerValueArray; + + b_ModulNbr=CR_AREF(insn->chanspec); + b_ReadType=CR_CHAN(insn->chanspec); + pul_TimerValueArray=(PULONG) data; + i_ReturnValue=insn->n; + + switch(b_ReadType) + { + case APCI1710_TIMER_READINTERRUPT: + + + data[0]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].b_OldModuleMask; + data[1]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldInterruptMask; + data[2]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldCounterLatchValue; + + + /**************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv-> + s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters. + ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + break; + + case APCI1710_TIMER_READALLTIMER: + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) + { + /********************************/ + /* Test if timer 0 iniutialised */ + /********************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [0]. + b_82X54Init == 1) + { + /********************************/ + /* Test if timer 1 iniutialised */ + /********************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [1]. + b_82X54Init == 1) + { + /********************************/ + /* Test if timer 2 iniutialised */ + /********************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [2]. + b_82X54Init == 1) + { + /*********************/ + /* Latch all counter */ + /*********************/ + + + outl(0x17,devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + /**************************/ + /* Read the timer 0 value */ + /**************************/ + + + pul_TimerValueArray [0]=inl(devpriv->s_BoardInfos. + ui_Address + 0 + (64 * b_ModulNbr)); + + /**************************/ + /* Read the timer 1 value */ + /**************************/ + + + pul_TimerValueArray [1]=inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + + /**************************/ + /* Read the timer 2 value */ + /**************************/ + + + pul_TimerValueArray [2]=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (64 * b_ModulNbr)); + } + else + { + /****************************************/ + /* Timer 2 not initialised see function */ + /****************************************/ + DPRINTK("Timer 2 not initialised see function\n"); + i_ReturnValue = -6; + } + } + else + { + /****************************************/ + /* Timer 1 not initialised see function */ + /****************************************/ + DPRINTK("Timer 1 not initialised see function\n"); + i_ReturnValue = -5; + } + } + else + { + /****************************************/ + /* Timer 0 not initialised see function */ + /****************************************/ + DPRINTK("Timer 0 not initialised see function\n"); + i_ReturnValue = -4; + } + } + else + { + /************************************/ + /* The module is not a TIMER module */ + /************************************/ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + }// End of Switch + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnBitsTimer(comedi_device *dev, +comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read write functions for Timer | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsTimer(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + BYTE b_BitsType; + INT i_ReturnValue=0; + b_BitsType=data[0]; + + switch(b_BitsType) + { + case APCI1710_TIMER_READVALUE: + i_ReturnValue=i_APCI1710_ReadTimerValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_CHAN(insn->chanspec), + (PULONG) &data[0]); + break; + + case APCI1710_TIMER_GETOUTPUTLEVEL: + i_ReturnValue=i_APCI1710_GetTimerOutputLevel (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_CHAN(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_TIMER_GETPROGRESSSTATUS: + i_ReturnValue=i_APCI1710_GetTimerProgressStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_CHAN(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_TIMER_WRITEVALUE: + i_ReturnValue=i_APCI1710_WriteTimerValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_CHAN(insn->chanspec), + (ULONG) data[1]); + + break; + + default: + printk("Bits Config Parameter Wrong\n"); + i_ReturnValue=-1; + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadTimerValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| PULONG_ pul_TimerValue) | ++----------------------------------------------------------------------------+ +| Task : Return the timer value from selected digital timer | +| (b_TimerNbr) from selected timer module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to read | +| (0 to 2) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_TimerValue : Timer value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadTimerValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + PULONG pul_TimerValue) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) + { + /*************************/ + /* Test the timer number */ + /*************************/ + + if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + { + /*****************************/ + /* Test if timer initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + b_82X54Init == 1) + { + /*************************/ + /* Latch the timer value */ + /*************************/ + + + outl((2 << b_TimerNbr) | 0xD0,devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + /**************************/ + /* Read the counter value */ + /**************************/ + + + *pul_TimerValue=inl(devpriv->s_BoardInfos. + ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + } + else + { + /**************************************/ + /* Timer not initialised see function */ + /**************************************/ + DPRINTK("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } + else + { + /*************************/ + /* Timer selection wrong */ + /*************************/ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } + else + { + /************************************/ + /* The module is not a TIMER module */ + /************************************/ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + /* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetTimerOutputLevel | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| PBYTE_ pb_OutputLevel) | ++----------------------------------------------------------------------------+ +| Task : Return the output signal level (pb_OutputLevel) from | +| selected digital timer (b_TimerNbr) from selected timer| +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to test | +| (0 to 2) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_OutputLevel : Output signal level | +| 0 : The output is low | +| 1 : The output is high | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetTimerOutputLevel (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + PBYTE pb_OutputLevel) + { + INT i_ReturnValue = 0; + DWORD dw_TimerStatus; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) + { + /*************************/ + /* Test the timer number */ + /*************************/ + + if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + { + /*****************************/ + /* Test if timer initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + b_82X54Init == 1) + { + /*************************/ + /* Latch the timer value */ + /*************************/ + + outl((2 << b_TimerNbr) | 0xE0,devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + /*************************/ + /* Read the timer status */ + /*************************/ + + + dw_TimerStatus=inl(devpriv->s_BoardInfos. + ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + *pb_OutputLevel = (BYTE) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + b_OutputLevel); + } + else + { + /**************************************/ + /* Timer not initialised see function */ + /**************************************/ + DPRINTK("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } + else + { + /*************************/ + /* Timer selection wrong */ + /*************************/ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } + else + { + /************************************/ + /* The module is not a TIMER module */ + /************************************/ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetTimerProgressStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| PBYTE_ pb_TimerStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the progress status (pb_TimerStatus) from | +| selected digital timer (b_TimerNbr) from selected timer| +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to test | +| (0 to 2) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TimerStatus : Output signal level | +| 0 : Timer not in progress | +| 1 : Timer in progress | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetTimerProgressStatus (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + PBYTE pb_TimerStatus) + { + INT i_ReturnValue = 0; + DWORD dw_TimerStatus; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) + { + /*************************/ + /* Test the timer number */ + /*************************/ + + if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + { + /*****************************/ + /* Test if timer initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + b_82X54Init == 1) + { + /*************************/ + /* Latch the timer value */ + /*************************/ + + + outl((2 << b_TimerNbr) | 0xE0,devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + /*************************/ + /* Read the timer status */ + /*************************/ + + + dw_TimerStatus=inl(devpriv->s_BoardInfos. + ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + + *pb_TimerStatus = (BYTE) ((dw_TimerStatus) >> 8) & 1; + printk("ProgressStatus : %d",*pb_TimerStatus); + } + else + { + /**************************************/ + /* Timer not initialised see function */ + /**************************************/ + + i_ReturnValue = -5; + } + } + else + { + /*************************/ + /* Timer selection wrong */ + /*************************/ + + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } + else + { + /************************************/ + /* The module is not a TIMER module */ + /************************************/ + + i_ReturnValue = -4; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_WriteTimerValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TimerNbr, | +| ULONG_ ul_WriteValue) | ++----------------------------------------------------------------------------+ +| Task : Write the value (ul_WriteValue) into the selected timer| +| (b_TimerNbr) from selected timer module (b_ModulNbr). | +| The action in depend of the time mode selection. | +| See timer mode description table. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board | +| APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_TimerNbr : Timer number to write | +| (0 to 2) | +| ULONG_ ul_WriteValue : Value to write | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: Timer selection wrong | +| -4: The module is not a TIMER module | +| -5: Timer not initialised see function | +| "i_APCI1710_InitTimer" | ++----------------------------------------------------------------------------+ +*/ + + INT i_APCI1710_WriteTimerValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + ULONG ul_WriteValue) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) + { + /*************************/ + /* Test the timer number */ + /*************************/ + + if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + { + /*****************************/ + /* Test if timer initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_82X54ModuleInfo. + s_82X54TimerInfo [b_TimerNbr]. + b_82X54Init == 1) + { + /*******************/ + /* Write the value */ + /*******************/ + + + outl(ul_WriteValue,devpriv->s_BoardInfos. + ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr)); + } + else + { + /**************************************/ + /* Timer not initialised see function */ + /**************************************/ + DPRINTK("Timer not initialised see function\n"); + i_ReturnValue = -5; + } + } + else + { + /*************************/ + /* Timer selection wrong */ + /*************************/ + DPRINTK("Timer selection wrong\n"); + i_ReturnValue = -3; + } // if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) + } + else + { + /************************************/ + /* The module is not a TIMER module */ + /************************************/ + DPRINTK("The module is not a TIMER module\n"); + i_ReturnValue = -4; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + + diff --git a/comedi/drivers/addi-data/APCI1710_82x54.h b/comedi/drivers/addi-data/APCI1710_82x54.h new file mode 100644 index 00000000..4e958a5a --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_82x54.h @@ -0,0 +1,69 @@ + + +#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 + +/* ++----------------------------------------------------------------------------+ +| 82X54 TIMER INISIALISATION FUNCTION | ++----------------------------------------------------------------------------+ +*/ + + + +INT i_APCI1710_InsnConfigInitTimer(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + + +INT i_APCI1710_InsnWriteEnableDisableTimer(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); +/* ++----------------------------------------------------------------------------+ +| 82X54 READ FUNCTION | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadAllTimerValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + +INT i_APCI1710_InsnBitsTimer(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + +/* ++----------------------------------------------------------------------------+ +| 82X54 READ & WRITE FUNCTION | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_ReadTimerValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + PULONG pul_TimerValue); + +INT i_APCI1710_GetTimerOutputLevel (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + PBYTE pb_OutputLevel); + +INT i_APCI1710_GetTimerProgressStatus (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + PBYTE pb_TimerStatus); + +/* ++----------------------------------------------------------------------------+ +| 82X54 WRITE FUNCTION | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_WriteTimerValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_TimerNbr, + ULONG ul_WriteValue); \ No newline at end of file diff --git a/comedi/drivers/addi-data/APCI1710_Chrono.c b/comedi/drivers/addi-data/APCI1710_Chrono.c new file mode 100644 index 00000000..998f86a7 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Chrono.c @@ -0,0 +1,1828 @@ +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : CHRONO.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 06.07.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 chronometer module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 29/06/98 | S. Weber | Digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | | | | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "APCI1710_Chrono.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitChrono | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ChronoMode, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_TimingInterval, | +| PULONG_ pul_RealTimingInterval) + ++----------------------------------------------------------------------------+ +| Task : Configure the chronometer operating mode (b_ChronoMode)| +| from selected module (b_ModulNbr). | +| The ul_TimingInterval and ul_TimingUnit determine the | +| timing base for the measurement. | +| The pul_RealTimingInterval return the real timing | +| value. You must calling this function be for you call | +| any other function witch access of the chronometer. | +| | +| Witch this functionality from the APCI-1710 you have | +| the possibility to measure the timing witch two event. | +| | +| The mode 0 and 1 is appropriate for period measurement.| +| The mode 2 and 3 is appropriate for frequent | +| measurement. | +| The mode 4 to 7 is appropriate for measuring the timing| +| between two event. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr CR_AREF(insn->chanspec) : Module number to configure | +| (0 to 3) | +| BYTE_ b_ChronoMode data[0] : Chronometer action mode | +| (0 to 7). | +| BYTE_ b_PCIInputClock data[1] : Selection from PCI bus clock| +| - APCI1710_30MHZ : | +| The PC have a PCI bus | +| clock from 30 MHz | +| - APCI1710_33MHZ : | +| The PC have a PCI bus | +| clock from 33 MHz | +| - APCI1710_40MHZ | +| The APCI-1710 have a | +| integrated 40Mhz | +| quartz. | +| BYTE_ b_TimingUnit data[2] : Base timing unity (0 to 4) | +| 0 : ns | +| 1 : µs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_TimingInterval : data[3] Base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing | +| value. +| data[0] ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer mode selection is wrong | +| -5: The selected PCI input clock is wrong | +| -6: Timing unity selection is wrong | +| -7: Base timing selection is wrong | +| -8: You can not used the 40MHz clock selection wich | +| this board | +| -9: You can not used the 40MHz clock selection wich | +| this CHRONOS version | ++----------------------------------------------------------------------------+ +*/ + + + +INT i_APCI1710_InsnConfigInitChrono(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + ULONG ul_TimerValue,ul_TimingInterval,ul_RealTimingInterval; + double d_RealTimingInterval; + DWORD dw_ModeArray [8] = {0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06}; + BYTE b_ModulNbr,b_ChronoMode,b_PCIInputClock,b_TimingUnit; + PULONG pul_RealTimingInterval; + + 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 >= 0 && 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 >= 0) && (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)) + { + /****************************************/ + /* 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) *pul_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) *pul_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) *pul_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) *pul_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) *pul_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; + } + + /****************************/ + /* Save the PCI input clock */ + /****************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_PCIInputClock = b_PCIInputClock; + + /*************************/ + /* Save the timing unity */ + /*************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_TimingUnit = b_TimingUnit; + + /************************/ + /* Save the base timing */ + /************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + d_TimingInterval = d_RealTimingInterval; + + /****************************/ + /* Set the chronometer mode */ + /****************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg = dw_ModeArray [b_ChronoMode]; + + /***********************/ + /* Test if 40 MHz used */ + /***********************/ + + if (b_PCIInputClock == APCI1710_40MHZ) + { + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg = devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg | 0x80; + } + + outl(devpriv->s_ModuleInfo [b_ModulNbr].s_ChronoModuleInfo. + dw_ConfigReg,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + /***********************/ + /* Write timer 0 value */ + /***********************/ + + + outl(ul_TimerValue,devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + /*********************/ + /* Chronometer init. */ + /*********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_ChronoInit = 1; + } + else + { + /***********************************************/ + /* TOR version error for 40MHz clock selection */ + /***********************************************/ + DPRINTK("TOR version error for 40MHz clock selection\n"); + i_ReturnValue = -9; + } + } + else + { + /**************************************************************/ + /* You can not used the 40MHz clock selection wich this board */ + /**************************************************************/ + DPRINTK("You can not used the 40MHz clock selection wich this board\n"); + i_ReturnValue = -8; + } + } + else + { + /**********************************/ + /* Base timing selection is wrong */ + /**********************************/ + DPRINTK("Base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else + { + /***********************************/ + /* Timing unity selection is wrong */ + /***********************************/ + DPRINTK("Timing unity selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) + else + { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = -5; + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) + } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7) + else + { + /***************************************/ + /* Chronometer mode selection is wrong */ + /***************************************/ + DPRINTK("Chronometer mode selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_ChronoMode >= 0 && b_ChronoMode <= 7) + } + else + { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + data[0] = ul_RealTimingInterval; + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableChrono | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_CycleMode, | +| BYTE_ b_InterruptEnable) +INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev, +comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Enable the chronometer from selected module | +| (b_ModulNbr). You must calling the | +| "i_APCI1710_InitChrono" function be for you call this | +| function. | +| If you enable the chronometer interrupt, the | +| chronometer generate a interrupt after the stop signal.| +| See function "i_APCI1710_SetBoardIntRoutineX" and the | +| Interrupt mask description chapter from this manual. | +| The b_CycleMode parameter determine if you will | +| measured a single or more cycle. + +| Disable the chronometer from selected module | +| (b_ModulNbr). If you disable the chronometer after a | +| start signal occur and you restart the chronometer | +| witch the " i_APCI1710_EnableChrono" function, if no | +| stop signal occur this start signal is ignored. ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr CR_AREF(chanspec) : Selected module number (0 to 3) | + data[0] ENABle/Disable chrono +| BYTE_ b_CycleMode : Selected the chronometer | +| data[1] acquisition mode | +| BYTE_ b_InterruptEnable : Enable or disable the | +| data[2] chronometer interrupt. | +| APCI1710_ENABLE: | +| Enable the chronometer | +| interrupt | +| APCI1710_DISABLE: | +| Disable the chronometer | +| interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | +| -5: Chronometer acquisition mode cycle is wrong | +| -6: Interrupt parameter is wrong | +| -7: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" + -8: data[0] wrong input | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + BYTE b_ModulNbr,b_CycleMode,b_InterruptEnable,b_Action; + b_ModulNbr = CR_AREF(insn->chanspec); + b_Action =(BYTE) data[0]; + b_CycleMode =(BYTE) data[1]; + b_InterruptEnable =(BYTE) data[2]; + i_ReturnValue = insn->n; + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER) + { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_ChronoInit == 1) + { + + + switch(b_Action) + { + + case APCI1710_ENABLE : + + /*********************************/ + /* Test the cycle mode parameter */ + /*********************************/ + + if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) + { + /***************************/ + /* Test the interrupt flag */ + /***************************/ + + if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) + { + + + /***************************/ + /* Save the interrupt flag */ + /***************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_InterruptMask = b_InterruptEnable; + + /***********************/ + /* Save the cycle mode */ + /***********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_CycleMode = b_CycleMode; + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg = (devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg & 0x8F) | + ((1 & b_InterruptEnable) << 5) | + ((1 & b_CycleMode) << 6) | + 0x10 ; + + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if (b_InterruptEnable == APCI1710_ENABLE) + { + /****************************/ + /* Clear the interrupt flag */ + /****************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos. + ui_Address + 32 + (64 * b_ModulNbr)); + devpriv->tsk_Current=current; // Save the current process task structure + } + + /***********************************/ + /* Enable or disable the interrupt */ + /* Enable the chronometer */ + /***********************************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo.dw_ConfigReg,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + /*************************/ + /* Clear status register */ + /*************************/ + + + outl(0,devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr)); + + } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) + else + { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue = -6; + } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) + } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) + else + { + /***********************************************/ + /* Chronometer acquisition mode cycle is wrong */ + /***********************************************/ + DPRINTK("Chronometer acquisition mode cycle is wrong\n"); + i_ReturnValue = -5; + } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) + break; + + case APCI1710_DISABLE : + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_InterruptMask = 0; + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg = devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + dw_ConfigReg & 0x2F; + + /***************************/ + /* Disable the interrupt */ + /* Disable the chronometer */ + /***************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + /***************************/ + /* Test if continuous mode */ + /***************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo.b_CycleMode == APCI1710_CONTINUOUS) + { + /*************************/ + /* Clear status register */ + /*************************/ + + + outl(0,devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr)); + } + break; + + default: + DPRINTK("Inputs wrong! Enable or Disable chrono\n"); + i_ReturnValue = -8; + } // switch ENABLE/DISABLE + } + else + { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnReadChrono(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read functions for Timer | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadChrono(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + BYTE b_ReadType; + INT i_ReturnValue=insn->n; + + b_ReadType=CR_CHAN(insn->chanspec); + + switch(b_ReadType) + { + case APCI1710_CHRONO_PROGRESS_STATUS: + i_ReturnValue=i_APCI1710_GetChronoProgressStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_CHRONO_READVALUE: + i_ReturnValue=i_APCI1710_ReadChronoValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (UINT) insn->unused[0], + (PBYTE) &data[0], + (PULONG) &data[1]); + break; + + case APCI1710_CHRONO_CONVERTVALUE: + i_ReturnValue=i_APCI1710_ConvertChronoValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (ULONG) insn->unused[0], + (PULONG) &data[0], + (PBYTE) &data[1], + (PBYTE) &data[2], + (PUINT) &data[3], + (PUINT) &data[4], + (PUINT) &data[5]); + break; + + case APCI1710_CHRONO_READINTERRUPT: + printk("In Chrono Read Interrupt\n"); + + data[0]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].b_OldModuleMask; + data[1]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldInterruptMask; + data[2]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldCounterLatchValue; + + + /**************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv-> + s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters. + ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + break; + + default: + printk("ReadType Parameter wrong\n"); + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); + +} + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetChronoProgressStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_ChronoStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the chronometer status (pb_ChronoStatus) from | +| selected chronometer module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer | +| status. | +| 0 : Measurement not started.| +| No start signal occur. | +| 1 : Measurement started. | +| A start signal occur. | +| 2 : Measurement stopped. | +| A stop signal occur. | +| The measurement is | +| terminate. | +| 3: A overflow occur. You | +| must change the base | +| timing witch the | +| function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetChronoProgressStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_ChronoStatus) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER) + { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_ChronoInit == 1) + { + + dw_Status=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (64 * b_ModulNbr)); + + /********************/ + /* Test if overflow */ + /********************/ + + if ((dw_Status & 8) == 8) + { + /******************/ + /* Overflow occur */ + /******************/ + + *pb_ChronoStatus = 3; + } // if ((dw_Status & 8) == 8) + else + { + /*******************************/ + /* Test if measurement stopped */ + /*******************************/ + + if ((dw_Status & 2) == 2) + { + /***********************/ + /* A stop signal occur */ + /***********************/ + + *pb_ChronoStatus = 2; + } // if ((dw_Status & 2) == 2) + else + { + /*******************************/ + /* Test if measurement started */ + /*******************************/ + + if ((dw_Status & 1) == 1) + { + /************************/ + /* A start signal occur */ + /************************/ + + *pb_ChronoStatus = 1; + } // if ((dw_Status & 1) == 1) + else + { + /***************************/ + /* Measurement not started */ + /***************************/ + + *pb_ChronoStatus = 0; + } // if ((dw_Status & 1) == 1) + } // if ((dw_Status & 2) == 2) + } // if ((dw_Status & 8) == 8) + } + else + { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadChronoValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| UINT_ ui_TimeOut, | +| PBYTE_ pb_ChronoStatus, | +| PULONG_ pul_ChronoValue) | ++----------------------------------------------------------------------------+ +| Task : Return the chronometer status (pb_ChronoStatus) and the| +| timing value (pul_ChronoValue) after a stop signal | +| occur from selected chronometer module (b_ModulNbr). | +| This function are only avaible if you have disabled | +| the interrupt functionality. See function | +| "i_APCI1710_EnableChrono" and the Interrupt mask | +| description chapter. | +| You can test the chronometer status witch the | +| "i_APCI1710_GetChronoProgressStatus" function. | +| | +| The returned value from pul_ChronoValue parameter is | +| not real measured timing. | +| You must used the "i_APCI1710_ConvertChronoValue" | +| function or make this operation for calculate the | +| timing: | +| | +| Timing = pul_ChronoValue * pul_RealTimingInterval. | +| | +| pul_RealTimingInterval is the returned parameter from | +| "i_APCI1710_InitChrono" function and the time unity is | +| the b_TimingUnit from "i_APCI1710_InitChrono" function| ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer | +| status. | +| 0 : Measurement not started.| +| No start signal occur. | +| 1 : Measurement started. | +| A start signal occur. | +| 2 : Measurement stopped. | +| A stop signal occur. | +| The measurement is | +| terminate. | +| 3: A overflow occur. You | +| must change the base | +| timing witch the | +| function | +| "i_APCI1710_InitChrono" | +| PULONG pul_ChronoValue : Chronometer timing value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | +| -5: Timeout parameter is wrong (0 to 65535) | +| -6: Interrupt routine installed. You can not read | +| directly the chronometer measured timing. | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadChronoValue (comedi_device *dev, + BYTE b_ModulNbr, + UINT ui_TimeOut, + PBYTE pb_ChronoStatus, + PULONG pul_ChronoValue) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_TimeOut = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER) + { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_ChronoInit == 1) + { + /*****************************/ + /* Test the timout parameter */ + /*****************************/ + + if ((ui_TimeOut >= 0) && (ui_TimeOut <= 65535UL)) + { + + for (;;) + { + /*******************/ + /* Read the status */ + /*******************/ + + + dw_Status=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (64 * b_ModulNbr)); + + + /********************/ + /* Test if overflow */ + /********************/ + + if ((dw_Status & 8) == 8) + { + /******************/ + /* Overflow occur */ + /******************/ + + *pb_ChronoStatus = 3; + + /***************************/ + /* Test if continuous mode */ + /***************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_CycleMode == APCI1710_CONTINUOUS) + { + /*************************/ + /* Clear status register */ + /*************************/ + + + outl(0,devpriv->s_BoardInfos. + ui_Address + 36 + (64 * b_ModulNbr)); + } + + break; + } // if ((dw_Status & 8) == 8) + else + { + /*******************************/ + /* Test if measurement stopped */ + /*******************************/ + + if ((dw_Status & 2) == 2) + { + /***********************/ + /* A stop signal occur */ + /***********************/ + + *pb_ChronoStatus = 2; + + /***************************/ + /* Test if continnous mode */ + /***************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_CycleMode == APCI1710_CONTINUOUS) + { + /*************************/ + /* Clear status register */ + /*************************/ + + + outl(0,devpriv->s_BoardInfos. + ui_Address + 36 + (64 * b_ModulNbr)); + } + break; + } // if ((dw_Status & 2) == 2) + else + { + /*******************************/ + /* Test if measurement started */ + /*******************************/ + + if ((dw_Status & 1) == 1) + { + /************************/ + /* A start signal occur */ + /************************/ + + *pb_ChronoStatus = 1; + } // if ((dw_Status & 1) == 1) + else + { + /***************************/ + /* Measurement not started */ + /***************************/ + + *pb_ChronoStatus = 0; + } // if ((dw_Status & 1) == 1) + } // if ((dw_Status & 2) == 2) + } // if ((dw_Status & 8) == 8) + + if (dw_TimeOut == ui_TimeOut) + { + /*****************/ + /* Timeout occur */ + /*****************/ + + break; + } + else + { + /*************************/ + /* Increment the timeout */ + /*************************/ + + dw_TimeOut = dw_TimeOut + 1; + mdelay(1000); + + } + } // for (;;) + + /*****************************/ + /* Test if stop signal occur */ + /*****************************/ + + if (*pb_ChronoStatus == 2) + { + /**********************************/ + /* Read the measured timing value */ + /**********************************/ + + + *pul_ChronoValue= inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + + if (*pul_ChronoValue != 0) + { + *pul_ChronoValue = *pul_ChronoValue - 1; + } + } + else + { + /*************************/ + /* Test if timeout occur */ + /*************************/ + + if ((*pb_ChronoStatus != 3) && (dw_TimeOut == ui_TimeOut) && (ui_TimeOut != 0)) + { + /*****************/ + /* Timeout occur */ + /*****************/ + + *pb_ChronoStatus = 4; + } + } + + } + else + { + /******************************/ + /* Timeout parameter is wrong */ + /******************************/ + DPRINTK("Timeout parameter is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ConvertChronoValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| ULONG_ ul_ChronoValue, | +| PULONG_ pul_Hour, | +| PBYTE_ pb_Minute, | +| PBYTE_ pb_Second, | +| PUINT_ pui_MilliSecond, | +| PUINT_ pui_MicroSecond, | +| PUINT_ pui_NanoSecond) | ++----------------------------------------------------------------------------+ +| Task : Convert the chronometer measured timing | +| (ul_ChronoValue) in to h, mn, s, ms, µs, ns. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| +| ULONG_ ul_ChronoValue : Measured chronometer timing | +| value. | +| See"i_APCI1710_ReadChronoValue"| ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_Hour : Chronometer timing hour | +| PBYTE_ pb_Minute : Chronometer timing minute | +| PBYTE_ pb_Second : Chronometer timing second | +| PUINT_ pui_MilliSecond : Chronometer timing mini | +| second | +| PUINT_ pui_MicroSecond : Chronometer timing micro | +| second | +| PUINT_ pui_NanoSecond : Chronometer timing nano | +| second | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ConvertChronoValue (comedi_device *dev, + BYTE b_ModulNbr, + ULONG ul_ChronoValue, + PULONG pul_Hour, + PBYTE pb_Minute, + PBYTE pb_Second, + PUINT pui_MilliSecond, + PUINT pui_MicroSecond, + PUINT pui_NanoSecond) + { + INT i_ReturnValue = 0; + double d_Hour; + double d_Minute; + double d_Second; + double d_MilliSecond; + double d_MicroSecond; + double d_NanoSecond; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER) + { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_ChronoInit == 1) + { + + d_Hour = (double) ul_ChronoValue * (double) devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + d_TimingInterval; + + switch (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_TimingUnit) + { + case 0: + d_Hour = d_Hour / (double) 1000.0; + + case 1: + d_Hour = d_Hour / (double) 1000.0; + + case 2: + d_Hour = d_Hour / (double) 1000.0; + + case 3: + d_Hour = d_Hour / (double) 60.0; + + case 4: + /**********************/ + /* Calculate the hour */ + /**********************/ + + d_Hour = d_Hour / (double) 60.0; + *pul_Hour = (ULONG) d_Hour; + + /************************/ + /* Calculate the minute */ + /************************/ + + d_Minute = d_Hour - *pul_Hour; + d_Minute = d_Minute * 60; + *pb_Minute = (BYTE) d_Minute; + + /************************/ + /* Calculate the second */ + /************************/ + + d_Second = d_Minute - *pb_Minute; + d_Second = d_Second * 60; + *pb_Second = (BYTE) d_Second; + + /*****************************/ + /* Calculate the mini second */ + /*****************************/ + + d_MilliSecond = d_Second - *pb_Second; + d_MilliSecond = d_MilliSecond * 1000; + *pui_MilliSecond = (UINT) d_MilliSecond; + + /******************************/ + /* Calculate the micro second */ + /******************************/ + + d_MicroSecond = d_MilliSecond - *pui_MilliSecond; + d_MicroSecond = d_MicroSecond * 1000; + *pui_MicroSecond = (UINT) d_MicroSecond; + + /******************************/ + /* Calculate the micro second */ + /******************************/ + + d_NanoSecond = d_MicroSecond - *pui_MicroSecond; + d_NanoSecond = d_NanoSecond * 1000; + *pui_NanoSecond = (UINT) d_NanoSecond; + break; + } + + } + else + { + /*******************************/ + /* Chronometer not initialised */ + /*******************************/ + DPRINTK("Chronometer not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /******************************************/ + /* The module is not a Chronometer module */ + /******************************************/ + DPRINTK("The module is not a Chronometer module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Sets the output witch has been passed with the | +| parameter b_Channel. Setting an output means setting an| +| output high. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel : Selection from digital output | +| CR_CHAN() channel (0 to 2) | +| 0 : Channel H | +| 1 : Channel A | +| 2 : Channel B | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: The selected digital output is wrong | +| -5: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetChronoChlOff | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_OutputChannel) | ++----------------------------------------------------------------------------+ +| Task : Resets the output witch has been passed with the | +| parameter b_Channel. Resetting an output means setting | +| an output low. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 + data[0] : Chl ON, Chl OFF , Chl Read , Port Read + +| BYTE_ b_ModulNbr CR_AREF : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel CR_CHAN : Selection from digital output | +| channel (0 to 2) | +| 0 : Channel H | +| 1 : Channel A | +| 2 : Channel B | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: The selected digital output is wrong | +| -5: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadChronoChlValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_InputChannel, | +| PBYTE_ pb_ChannelStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the status from selected digital input | +| (b_InputChannel) from selected chronometer | +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| +| BYTE_ b_InputChannel : Selection from digital input | +| channel (0 to 2) | +| CR_CHAN() 0 : Channel E | +| 1 : Channel F | +| 2 : Channel G | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel status.| +| data[0] 0 : Channel is not active | +| 1 : Channel is active | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: The selected digital input is wrong | +| -5: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadChronoPortValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_PortValue) | ++----------------------------------------------------------------------------+ +| Task : Return the status from digital inputs port from | +| selected (b_ModulNbr) chronometer module. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_PortValue : Digital inputs port status. +| data[0] ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a Chronometer module | +| -4: Chronometer not initialised see function | +| "i_APCI1710_InitChrono" | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + BYTE b_ModulNbr,b_OutputChannel,b_InputChannel,b_IOType; + DWORD dw_Status; + PBYTE pb_ChannelStatus; + PBYTE pb_PortValue; + + b_ModulNbr = CR_AREF(insn->chanspec); + i_ReturnValue = insn->n; + b_IOType = (BYTE) data[0]; + + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_CHRONOMETER) + { + /***********************************/ + /* Test if chronometer initialised */ + /***********************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_ChronoModuleInfo. + b_ChronoInit == 1) + { + /***********************************/ + /* Test the digital output channel */ + /***********************************/ + switch(b_IOType) + { + + case APCI1710_CHRONO_SET_CHANNELOFF: + + b_OutputChannel = (BYTE) CR_CHAN(insn->chanspec); + if ((b_OutputChannel >= 0) && (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 >= 0) && (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 >= 0) && (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/comedi/drivers/addi-data/APCI1710_Chrono.h b/comedi/drivers/addi-data/APCI1710_Chrono.h new file mode 100644 index 00000000..7d8833be --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Chrono.h @@ -0,0 +1,78 @@ + + + +#define APCI1710_30MHZ 30 +#define APCI1710_33MHZ 33 +#define APCI1710_40MHZ 40 + + +#define APCI1710_SINGLE 0 +#define APCI1710_CONTINUOUS 1 + + +#define APCI1710_CHRONO_PROGRESS_STATUS 0 +#define APCI1710_CHRONO_READVALUE 1 +#define APCI1710_CHRONO_CONVERTVALUE 2 +#define APCI1710_CHRONO_READINTERRUPT 3 + +#define APCI1710_CHRONO_SET_CHANNELON 0 +#define APCI1710_CHRONO_SET_CHANNELOFF 1 +#define APCI1710_CHRONO_READ_CHANNEL 2 +#define APCI1710_CHRONO_READ_PORT 3 + +/* ++----------------------------------------------------------------------------+ +| CHRONOMETER INISIALISATION FUNCTION | ++----------------------------------------------------------------------------+ */ + +INT i_APCI1710_InsnConfigInitChrono(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InsnWriteEnableDisableChrono(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + +/* ++----------------------------------------------------------------------------+ +| CHRONOMETER READ FUNCTION | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadChrono(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + + +INT i_APCI1710_GetChronoProgressStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_ChronoStatus); + +INT i_APCI1710_ReadChronoValue (comedi_device *dev, + BYTE b_ModulNbr, + UINT ui_TimeOut, + PBYTE pb_ChronoStatus, + PULONG pul_ChronoValue); + +INT i_APCI1710_ConvertChronoValue (comedi_device *dev, + BYTE b_ModulNbr, + ULONG ul_ChronoValue, + PULONG pul_Hour, + PBYTE pb_Minute, + PBYTE pb_Second, + PUINT pui_MilliSecond, + PUINT pui_MicroSecond, + PUINT pui_NanoSecond); + + + + + +/* ++----------------------------------------------------------------------------+ +| CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsChronoDigitalIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + diff --git a/comedi/drivers/addi-data/APCI1710_Dig_io.c b/comedi/drivers/addi-data/APCI1710_Dig_io.c new file mode 100644 index 00000000..c39d304b --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Dig_io.c @@ -0,0 +1,988 @@ +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : DIG_IO.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 16.06.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 digital I/O module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 16/06/98 | S. Weber | Digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | | | | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "APCI1710_Dig_io.h" + + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev, | +| comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)| ++----------------------------------------------------------------------------+ +| Task : Configure the digital I/O operating mode from selected | +| module (b_ModulNbr). You must calling this function be| +| for you call any other function witch access of digital| +| I/O. | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| BYTE_ b_ModulNbr data[0]: Module number to | +| configure (0 to 3) | +| BYTE_ b_ChannelAMode data[1] : Channel A mode selection | +| 0 : Channel used for digital | +| input | +| 1 : Channel used for digital | +| output | +| BYTE_ b_ChannelBMode data[2] : Channel B mode selection | +| 0 : Channel used for digital | +| input | +| 1 : Channel used for digital | +| output | + data[0] memory on/off +Activates and deactivates the digital output memory. + After having | +| called up this function with memory on,the output you have previously| +| activated with the function are not reset ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a digital I/O module | +| -4: Bi-directional channel A configuration error | +| -5: Bi-directional channel B configuration error | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + BYTE b_ModulNbr,b_ChannelAMode,b_ChannelBMode ; + BYTE b_MemoryOnOff,b_ConfigType; + INT i_ReturnValue = 0; + DWORD dw_WriteConfig = 0; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_ConfigType = (BYTE) data[0];// Memory or Init + b_ChannelAMode = (BYTE) data[1]; + b_ChannelBMode = (BYTE) data[2]; + b_MemoryOnOff = (BYTE) data[1]; // if memory operation + i_ReturnValue = insn->n; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr >= 4) + { + DPRINTK("Module Number invalid\n"); + i_ReturnValue = -2; + return i_ReturnValue; + } + switch(b_ConfigType) + { + case APCI1710_DIGIO_MEMORYONOFF: + + if(b_MemoryOnOff) // If Memory ON + { + /****************************/ + /* Set the output memory on */ + /****************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled = 1; + + /***************************/ + /* Clear the output memory */ + /***************************/ + devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory = 0; + } + else // If memory off + { + /*****************************/ + /* Set the output memory off */ + /*****************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled = 0; + } + break; + + case APCI1710_DIGIO_INIT: + + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if((devpriv->s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO) + { + + /***************************************************/ + /* Test the bi-directional channel A configuration */ + /***************************************************/ + + if ((b_ChannelAMode == 0) || (b_ChannelAMode == 1)) + { + /***************************************************/ + /* Test the bi-directional channel B configuration */ + /***************************************************/ + + if ((b_ChannelBMode == 0) || (b_ChannelBMode == 1)) + { + devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_DigitalInit = 1; + + /********************************/ + /* Save channel A configuration */ + /********************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelAMode = b_ChannelAMode; + + /********************************/ + /* Save channel B configuration */ + /********************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelBMode = b_ChannelBMode; + + /*****************************************/ + /* Set the channel A and B configuration */ + /*****************************************/ + + + dw_WriteConfig = (DWORD) (b_ChannelAMode | (b_ChannelBMode * 2)); + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(dw_WriteConfig,devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); + + } + else + { + /************************************************/ + /* Bi-directional channel B configuration error */ + /************************************************/ + DPRINTK("Bi-directional channel B configuration error\n"); + i_ReturnValue = -5; + } + + } + else + { + /************************************************/ + /* Bi-directional channel A configuration error */ + /************************************************/ + DPRINTK("Bi-directional channel A configuration error\n"); + i_ReturnValue = -4; + + } + + } + else + { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + DPRINTK("The module is not a digital I/O module\n"); + i_ReturnValue = -3; + } + } // end of Switch + printk("Return Value %d\n",i_ReturnValue); + return i_ReturnValue; +} + +/* ++----------------------------------------------------------------------------+ +| INPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ + +|INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice +*s, comedi_insn *insn,lsampl_t *data) + ++----------------------------------------------------------------------------+ +| Task : Read the status from selected digital I/O digital input| +| (b_InputChannel) | ++----------------------------------------------------------------------------| + + +| +| BYTE_ b_ModulNbr CR_AREF(chanspec) : Selected module number | +| (0 to 3) | +| BYTE_ b_InputChannel CR_CHAN(chanspec) : Selection from digital | +| input ( 0 to 6) | +| 0 : Channel C | +| 1 : Channel D | +| 2 : Channel E | +| 3 : Channel F | +| 4 : Channel G | +| 5 : Channel A | +| 6 : Channel B + + + | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : Digital input channel | +| status | +| 0 : Channle is not active| +| 1 : Channle is active | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a digital I/O module | +| -4: The selected digital I/O digital input is wrong | +| -5: Digital I/O not initialised | +| -6: The digital channel A is used for output | +| -7: The digital channel B is used for output | ++----------------------------------------------------------------------------+ +*/ + +//_INT_ i_APCI1710_ReadDigitalIOChlValue (BYTE_ b_BoardHandle, +// BYTE_ b_ModulNbr, +// BYTE_ b_InputChannel, +// +// PBYTE_ pb_ChannelStatus) +INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg; + BYTE b_ModulNbr,b_InputChannel; + PBYTE pb_ChannelStatus; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_InputChannel = (BYTE) CR_CHAN(insn->chanspec); + data[0]=0; + pb_ChannelStatus= (PBYTE) &data[0]; + i_ReturnValue = insn->n; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO) + { + /******************************************/ + /* Test the digital imnput channel number */ + /******************************************/ + + if ((b_InputChannel >= 0) && (b_InputChannel <= 6)) + { + /**********************************************/ + /* Test if the digital I/O module initialised */ + /**********************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr].s_DigitalIOInfo.b_DigitalInit == 1) + { + /**********************************/ + /* Test if channel A or channel B */ + /**********************************/ + + if (b_InputChannel > 4) + { + /*********************/ + /* Test if channel A */ + /*********************/ + + if (b_InputChannel == 5) + { + /***************************/ + /* Test the channel A mode */ + /***************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr].s_DigitalIOInfo.b_ChannelAMode != 0) + { + /********************************************/ + /* The digital channel A is used for output */ + /********************************************/ + + i_ReturnValue = -6; + } + } // if (b_InputChannel == 5) + else + { + /***************************/ + /* Test the channel B mode */ + /***************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr].s_DigitalIOInfo.b_ChannelBMode != 0) + { + /********************************************/ + /* The digital channel B is used for output */ + /********************************************/ + + i_ReturnValue = -7; + } + } // if (b_InputChannel == 5) + } // if (b_InputChannel > 4) + + /***********************/ + /* Test if error occur */ + /***********************/ + + if (i_ReturnValue >= 0) + { + /**************************/ + /* Read all digital input */ + /**************************/ + + //INPDW (ps_APCI1710Variable-> + // s_Board [b_BoardHandle]. + // s_BoardInfos. + // ui_Address + (64 * b_ModulNbr), + // &dw_StatusReg); + + dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + + *pb_ChannelStatus = (BYTE) ((dw_StatusReg ^ 0x1C) >> b_InputChannel) & 1; + + } // if (i_ReturnValue == 0) + } + else + { + /*******************************/ + /* Digital I/O not initialised */ + /*******************************/ + DPRINTK("Digital I/O not initialised\n"); + i_ReturnValue = -5; + } + } + else + { + /********************************/ + /* Selected digital input error */ + /********************************/ + DPRINTK("Selected digital input error\n"); + i_ReturnValue = -4; + } + } + else + { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + DPRINTK("The module is not a digital I/O module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device +|*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) + ++----------------------------------------------------------------------------+ +| Task : Sets or resets the output witch has been passed with the | +| parameter b_Channel. Setting an output means setting | +| an ouput high. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr (aref ) : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel (CR_CHAN) : Selection from digital output | +| channel (0 to 2) | +| 0 : Channel H | +| 1 : Channel A | +| 2 : Channel B | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a digital I/O module | +| -4: The selected digital output is wrong | +| -5: digital I/O not initialised see function | +| " i_APCI1710_InitDigitalIO" | +| -6: The digital channel A is used for input | +| -7: The digital channel B is used for input + -8: Digital Output Memory OFF. | +| Use previously the function | +| "i_APCI1710_SetDigitalIOMemoryOn". | ++----------------------------------------------------------------------------+ +*/ + +//_INT_ i_APCI1710_SetDigitalIOChlOn (BYTE_ b_BoardHandle, +// BYTE_ b_ModulNbr, +// BYTE_ b_OutputChannel) +INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_WriteValue; + BYTE b_ModulNbr,b_OutputChannel; + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_OutputChannel = CR_CHAN(insn->chanspec); + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if digital I/O counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_DIGITAL_IO) + { + /**********************************************/ + /* Test if the digital I/O module initialised */ + /**********************************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_DigitalInit == 1) + { + /******************************************/ + /* Test the digital output channel number */ + /******************************************/ + + switch (b_OutputChannel) + { + /*************/ + /* Channel H */ + /*************/ + + case 0: + break; + + /*************/ + /* Channel A */ + /*************/ + + case 1: + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelAMode != 1) + { + /*******************************************/ + /* The digital channel A is used for input */ + /*******************************************/ + + i_ReturnValue = -6; + } + break; + + /*************/ + /* Channel B */ + /*************/ + + case 2: + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_ChannelBMode != 1) + { + /*******************************************/ + /* The digital channel B is used for input */ + /*******************************************/ + + i_ReturnValue = -7; + } + break; + + default : + /****************************************/ + /* The selected digital output is wrong */ + /****************************************/ + + i_ReturnValue = -4; + break; + } + + /***********************/ + /* Test if error occur */ + /***********************/ + + if (i_ReturnValue >= 0) + { + + + /*********************************/ + /* Test if set channel ON */ + /*********************************/ + if(data[0]) + { + /*********************************/ + /* Test if output memory enabled */ + /*********************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled == 1) + { + dw_WriteValue = devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory | (1 << b_OutputChannel); + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory = dw_WriteValue; + } + else + { + dw_WriteValue = 1 << b_OutputChannel; + } + } // set channel off + else + { + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + b_OutputMemoryEnabled == 1) + { + dw_WriteValue = devpriv->s_ModuleInfo [b_ModulNbr]. + s_DigitalIOInfo. + dw_OutputMemory & (0xFFFFFFFFUL - (1 << b_OutputChannel)); + + devpriv->s_ModuleInfo [b_ModulNbr].s_DigitalIOInfo.dw_OutputMemory = dw_WriteValue; + } + else + { + /*****************************/ + /* Digital Output Memory OFF */ + /*****************************/ + // +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn" + i_ReturnValue = -8; + } + + } + /*******************/ + /* Write the value */ + /*******************/ + + //OUTPDW (ps_APCI1710Variable-> + // s_Board [b_BoardHandle]. + // s_BoardInfos. + // ui_Address + (64 * b_ModulNbr), + // dw_WriteValue); + outl(dw_WriteValue,devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + } + } + else + { + /*******************************/ + /* Digital I/O not initialised */ + /*******************************/ + + i_ReturnValue = -5; + } + } + else + { + /******************************************/ + /* The module is not a digital I/O module */ + /******************************************/ + + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ + +|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice + *s, comedi_insn *insn,lsampl_t *data) ++----------------------------------------------------------------------------+ +| Task : write: + Sets or resets one or several outputs from port. | +| Setting an output means setting an output high. | +| If you have switched OFF the digital output memory | +| (OFF), all the other output are set to "0". + +| read: + Read the status from digital input port | +| from selected digital I/O module (b_ModulNbr) ++----------------------------------------------------------------------------+ +| Input Parameters : + BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr CR_AREF(aref) : Selected module number (0 to 3)| +| BYTE_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 ) +| data[0] read or write port + data[1] if write then indicate ON or OFF + + if read : data[1] will return port status. ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : + + INPUT : + + 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a digital I/O module | +| -4: Digital I/O not initialised + + OUTPUT: 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a digital I/O module | +| -4: Output value wrong | +| -5: digital I/O not initialised see function | +| " i_APCI1710_InitDigitalIO" | +| -6: The digital channel A is used for input | +| -7: The digital channel B is used for input + -8: Digital Output Memory OFF. | +| Use previously the function | +| "i_APCI1710_SetDigitalIOMemoryOn". | ++----------------------------------------------------------------------------+ +*/ + +//_INT_ i_APCI1710_SetDigitalIOPortOn (BYTE_ b_BoardHandle, +// BYTE_ b_ModulNbr, +// BYTE_ b_PortValue) +INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_WriteValue,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 >= 0) && (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/comedi/drivers/addi-data/APCI1710_Dig_io.h b/comedi/drivers/addi-data/APCI1710_Dig_io.h new file mode 100644 index 00000000..59c79b54 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Dig_io.h @@ -0,0 +1,38 @@ + + + +#define APCI1710_ON 1 // Digital Output ON or OFF +#define APCI1710_OFF 0 + + +#define APCI1710_INPUT 0 // Digital I/O +#define APCI1710_OUTPUT 1 + +#define APCI1710_DIGIO_MEMORYONOFF 0x10 // +#define APCI1710_DIGIO_INIT 0x11 + + +/* ++----------------------------------------------------------------------------+ +| DIGITAL I/O INISIALISATION FUNCTION | ++----------------------------------------------------------------------------+ +*/ + + + INT i_APCI1710_InsnConfigDigitalIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + +/* ++----------------------------------------------------------------------------+ +| INPUT OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_InsnReadDigitalIOChlValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InsnBitsDigitalIOPortOnOff(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + diff --git a/comedi/drivers/addi-data/APCI1710_INCCPT.c b/comedi/drivers/addi-data/APCI1710_INCCPT.c new file mode 100644 index 00000000..5751bca5 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_INCCPT.c @@ -0,0 +1,5376 @@ +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : INC_CPT.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 08.01.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 incremental counter module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | 29/06/01 | Guinot C. | - 1100/0231 -> 0701/0232 | + | | | See i_APCI1710_DisableFrequencyMeasurement | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + + +#include "APCI1710_INCCPT.h" + +/* ++----------------------------------------------------------------------------+ +| INT i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) + ++----------------------------------------------------------------------------+ +| Task : Configuration function for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : *data ++----------------------------------------------------------------------------+ +| Return Value : | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + UINT ui_ConfigType; + INT i_ReturnValue = 0; + ui_ConfigType=CR_CHAN(insn->chanspec); + devpriv->tsk_Current=current; // Save the current process task structure + switch(ui_ConfigType) + { + case APCI1710_INCCPT_INITCOUNTER : + i_ReturnValue =i_APCI1710_InitCounter (dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (BYTE) data[2], + (BYTE) data[3], + (BYTE) data[4]); + break; + + case APCI1710_INCCPT_COUNTERAUTOTEST: + i_ReturnValue =i_APCI1710_CounterAutoTest (dev, + (PBYTE) &data[0]); + break; + + case APCI1710_INCCPT_INITINDEX: + i_ReturnValue =i_APCI1710_InitIndex (dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (BYTE) data[2], + (BYTE) data[3]); + break; + + case APCI1710_INCCPT_INITREFERENCE: + i_ReturnValue =i_APCI1710_InitReference (dev, + CR_AREF(insn->chanspec), + (BYTE) data[0]); + break; + + case APCI1710_INCCPT_INITEXTERNALSTROBE: + i_ReturnValue =i_APCI1710_InitExternalStrobe (dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1]); + break; + + case APCI1710_INCCPT_INITCOMPARELOGIC: + i_ReturnValue =i_APCI1710_InitCompareLogic (dev, + CR_AREF(insn->chanspec), + (UINT) data[0]); + break; + + case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT: + i_ReturnValue =i_APCI1710_InitFrequencyMeasurement (dev, + CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (ULONG) data[2], + (PULONG) &data[0]); + break; + + default: + printk("Insn Config : Config Parameter Wrong\n"); + + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_CounterRange, | +| BYTE_ b_FirstCounterModus, | +| BYTE_ b_FirstCounterOption, | +| BYTE_ b_SecondCounterModus, | +| BYTE_ b_SecondCounterOption) | ++----------------------------------------------------------------------------+ +| Task : Configure the counter operating mode from selected | +| module (b_ModulNbr). You must calling this function be | +| for you call any other function witch access of | +| counters. | +| | +| Counter range | +| ------------- | +| +------------------------------------+-----------------------------------+ | +| | Parameter Passed value | Description | | +| |------------------------------------+-----------------------------------| | +| |b_ModulNbr APCI1710_16BIT_COUNTER | The module is configured for | | +| | | two 16-bit counter. | | +| | | - b_FirstCounterModus and | | +| | | b_FirstCounterOption | | +| | | configure the first 16 bit | | +| | | counter. | | +| | | - b_SecondCounterModus and | | +| | | b_SecondCounterOption | | +| | | configure the second 16 bit | | +| | | counter. | | +| |------------------------------------+-----------------------------------| | +| |b_ModulNbr APCI1710_32BIT_COUNTER | The module is configured for one | | +| | | 32-bit counter. | | +| | | - b_FirstCounterModus and | | +| | | b_FirstCounterOption | | +| | | configure the 32 bit counter. | | +| | | - b_SecondCounterModus and | | +| | | b_SecondCounterOption | | +| | | are not used and have no | | +| | | importance. | | +| +------------------------------------+-----------------------------------+ | +| | +| Counter operating mode | +| ---------------------- | +| | +| +--------------------+-------------------------+-------------------------+ | +| | Parameter | Passed value | Description | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_QUADRUPLE_MODE | In the quadruple mode, | | +| | or | | the edge analysis | | +| |b_SecondCounterModus| | circuit generates a | | +| | | | counting pulse from | | +| | | | each edge of 2 signals | | +| | | | which are phase shifted | | +| | | | in relation to each | | +| | | | other. | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_DOUBLE_MODE | Functions in the same | | +| | or | | way as the quadruple | | +| |b_SecondCounterModus| | mode, except that only | | +| | | | two of the four edges | | +| | | | are analysed per | | +| | | | period | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_SIMPLE_MODE | Functions in the same | | +| | or | | way as the quadruple | | +| |b_SecondCounterModus| | mode, except that only | | +| | | | one of the four edges | | +| | | | is analysed per | | +| | | | period. | | +| |--------------------+-------------------------+-------------------------| | +| |b_FirstCounterModus | APCI1710_DIRECT_MODE | In the direct mode the | | +| | or | | both edge analysis | | +| |b_SecondCounterModus| | circuits are inactive. | | +| | | | The inputs A, B in the | | +| | | | 32-bit mode or A, B and | | +| | | | C, D in the 16-bit mode | | +| | | | represent, each, one | | +| | | | clock pulse gate circuit| | +| | | | There by frequency and | | +| | | | pulse duration | | +| | | | measurements can be | | +| | | | performed. | | +| +--------------------+-------------------------+-------------------------+ | +| | +| | +| IMPORTANT! | +| If you have configured the module for two 16-bit counter, a mixed | +| mode with a counter in quadruple/double/single mode | +| and the other counter in direct mode is not possible! | +| | +| | +| Counter operating option for quadruple/double/simple mode | +| --------------------------------------------------------- | +| | +| +----------------------+-------------------------+------------------------+| +| | Parameter | Passed value | Description || +| |----------------------+-------------------------+------------------------|| +| |b_FirstCounterOption | APCI1710_HYSTERESIS_ON | In both edge analysis || +| | or | | circuits is available || +| |b_SecondCounterOption | | one hysteresis circuit.|| +| | | | It suppresses each || +| | | | time the first counting|| +| | | | pulse after a change || +| | | | of rotation. || +| |----------------------+-------------------------+------------------------|| +| |b_FirstCounterOption | APCI1710_HYSTERESIS_OFF | The first counting || +| | or | | pulse is not suppress || +| |b_SecondCounterOption | | after a change of || +| | | | rotation. || +| +----------------------+-------------------------+------------------------+| +| | +| | +| IMPORTANT! | +| This option are only avaible if you have selected the direct mode. | +| | +| | +| Counter operating option for direct mode | +| ---------------------------------------- | +| | +| +----------------------+--------------------+----------------------------+ | +| | Parameter | Passed value | Description | | +| |----------------------+--------------------+----------------------------| | +| |b_FirstCounterOption | APCI1710_INCREMENT | The counter increment for | | +| | or | | each counting pulse | | +| |b_SecondCounterOption | | | | +| |----------------------+--------------------+----------------------------| | +| |b_FirstCounterOption | APCI1710_DECREMENT | The counter decrement for | | +| | or | | each counting pulse | | +| |b_SecondCounterOption | | | | +| +----------------------+--------------------+----------------------------+ | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_CounterRange : Selection form counter | +| range. | +| BYTE_ b_FirstCounterModus : First counter operating | +| mode. | +| BYTE_ b_FirstCounterOption : First counter option. | +| BYTE_ b_SecondCounterModus : Second counter operating | +| mode. | +| BYTE_ b_SecondCounterOption : Second counter option. | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module is not a counter module | +| -3: The selected counter range is wrong. | +| -4: The selected first counter operating mode is wrong. | +| -5: The selected first counter operating option is wrong| +| -6: The selected second counter operating mode is wrong.| +| -7: The selected second counter operating option is | +| wrong. | ++----------------------------------------------------------------------------+ +*/ + + + + + +INT i_APCI1710_InitCounter (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_CounterRange, + BYTE b_FirstCounterModus, + BYTE b_FirstCounterOption, + BYTE b_SecondCounterModus, + BYTE b_SecondCounterOption) + { + INT i_ReturnValue = 0; + + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + /**************************/ + /* Test the counter range */ + /**************************/ + + if (b_CounterRange == APCI1710_16BIT_COUNTER || b_CounterRange == APCI1710_32BIT_COUNTER) + { + /********************************/ + /* Test the first counter modus */ + /********************************/ + + if (b_FirstCounterModus == APCI1710_QUADRUPLE_MODE || + b_FirstCounterModus == APCI1710_DOUBLE_MODE || + b_FirstCounterModus == APCI1710_SIMPLE_MODE || + b_FirstCounterModus == APCI1710_DIRECT_MODE) + { + /*********************************/ + /* Test the first counter option */ + /*********************************/ + + if ((b_FirstCounterModus == APCI1710_DIRECT_MODE && + (b_FirstCounterOption == APCI1710_INCREMENT || + b_FirstCounterOption == APCI1710_DECREMENT)) || + (b_FirstCounterModus != APCI1710_DIRECT_MODE && + (b_FirstCounterOption == APCI1710_HYSTERESIS_ON || + b_FirstCounterOption == APCI1710_HYSTERESIS_OFF))) + { + /**************************/ + /* Test if 16-bit counter */ + /**************************/ + + if (b_CounterRange == APCI1710_16BIT_COUNTER) + { + /*********************************/ + /* Test the second counter modus */ + /*********************************/ + + if ((b_FirstCounterModus != APCI1710_DIRECT_MODE && + (b_SecondCounterModus == APCI1710_QUADRUPLE_MODE || + b_SecondCounterModus == APCI1710_DOUBLE_MODE || + b_SecondCounterModus == APCI1710_SIMPLE_MODE)) || + (b_FirstCounterModus == APCI1710_DIRECT_MODE && + b_SecondCounterModus == APCI1710_DIRECT_MODE)) + { + /**********************************/ + /* Test the second counter option */ + /**********************************/ + + if ((b_SecondCounterModus == APCI1710_DIRECT_MODE && + (b_SecondCounterOption == APCI1710_INCREMENT || + b_SecondCounterOption == APCI1710_DECREMENT)) || + (b_SecondCounterModus != APCI1710_DIRECT_MODE && + (b_SecondCounterOption == APCI1710_HYSTERESIS_ON || + b_SecondCounterOption == APCI1710_HYSTERESIS_OFF))) + { + i_ReturnValue = 0; + } + else + { + /*********************************************************/ + /* The selected second counter operating option is wrong */ + /*********************************************************/ + DPRINTK("The selected second counter operating option is wrong\n"); + i_ReturnValue = -7; + } + } + else + { + /*******************************************************/ + /* The selected second counter operating mode is wrong */ + /*******************************************************/ + DPRINTK("The selected second counter operating mode is wrong\n"); + i_ReturnValue = -6; + } + } + } + else + { + /********************************************************/ + /* The selected first counter operating option is wrong */ + /********************************************************/ + DPRINTK("The selected first counter operating option is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /******************************************************/ + /* The selected first counter operating mode is wrong */ + /******************************************************/ + DPRINTK("The selected first counter operating mode is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /***************************************/ + /* The selected counter range is wrong */ + /***************************************/ + DPRINTK("The selected counter range is wrong\n"); + i_ReturnValue = -3; + } + + /*************************/ + /* Test if a error occur */ + /*************************/ + + if (i_ReturnValue == 0) + { + /**************************/ + /* Test if 16-Bit counter */ + /**************************/ + + if (b_CounterRange == APCI1710_32BIT_COUNTER) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 = b_CounterRange | + b_FirstCounterModus | + b_FirstCounterOption; + } + else + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 = b_CounterRange | + (b_FirstCounterModus & 0x5) | + (b_FirstCounterOption & 0x20) | + (b_SecondCounterModus & 0xA) | + (b_SecondCounterOption & 0x40); + + /***********************/ + /* Test if direct mode */ + /***********************/ + + if (b_FirstCounterModus == APCI1710_DIRECT_MODE) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 | APCI1710_DIRECT_MODE; + } + } + + /***************************/ + /* Write the configuration */ + /***************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit = 1; + } + } + else + { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_CounterAutoTest | +| (BYTE_ b_BoardHandle, | +| PBYTE_ pb_TestStatus) | ++----------------------------------------------------------------------------+ +| Task : A test mode is intended for testing the component and | +| the connected periphery. All the 8-bit counter chains | +| are operated internally as down counters. | +| Independently from the external signals, | +| all the four 8-bit counter chains are decremented in | +| parallel by each negative clock pulse edge of CLKX. | +| | +| Counter auto test conclusion | +| ---------------------------- | +| +-----------------+-----------------------------+ | +| | pb_TestStatus | Error description | | +| | mask | | | +| |-----------------+-----------------------------| | +| | 0000 | No error detected | | +| |-----------------|-----------------------------| | +| | 0001 | Error detected of counter 0 | | +| |-----------------|-----------------------------| | +| | 0010 | Error detected of counter 1 | | +| |-----------------|-----------------------------| | +| | 0100 | Error detected of counter 2 | | +| |-----------------|-----------------------------| | +| | 1000 | Error detected of counter 3 | | +| +-----------------+-----------------------------+ | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TestStatus : Auto test conclusion. See table| ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_CounterAutoTest (comedi_device *dev,PBYTE pb_TestStatus) + { + BYTE b_ModulCpt = 0; + INT i_ReturnValue = 0; + DWORD dw_LathchValue; + + + *pb_TestStatus = 0; + + /********************************/ + /* Test if counter module found */ + /********************************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [0] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER || + (devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [1] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER || + (devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [2] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER|| + (devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [3] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + for (b_ModulCpt = 0; b_ModulCpt < 4 ; b_ModulCpt ++) + { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulCpt] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + /******************/ + /* Start the test */ + /******************/ + + + outl(3,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulCpt)); + + /*********************/ + /* Tatch the counter */ + /*********************/ + + + outl(1,devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulCpt)); + + /************************/ + /* Read the latch value */ + /************************/ + + + dw_LathchValue=inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulCpt)); + + if ((dw_LathchValue & 0xFF) != ((dw_LathchValue >> 8) & 0xFF) && + (dw_LathchValue & 0xFF) != ((dw_LathchValue >> 16) & 0xFF) && + (dw_LathchValue & 0xFF) != ((dw_LathchValue >> 24) & 0xFF)) + { + *pb_TestStatus = *pb_TestStatus | (1 << b_ModulCpt); + } + + /*****************/ + /* Stop the test */ + /*****************/ + + + outl(0,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulCpt)); + } + } + } + else + { + /***************************/ + /* No counter module found */ + /***************************/ + DPRINTK("No counter module found\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitIndex (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ReferenceAction, | +| BYTE_ b_IndexOperation, | +| BYTE_ b_AutoMode, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Initialise the index corresponding to the selected | +| module (b_ModulNbr). If a INDEX flag occur, you have | +| the possibility to clear the 32-Bit counter or to latch| +| the current 32-Bit value in to the first latch | +| register. The b_IndexOperation parameter give the | +| possibility to choice the INDEX action. | +| If you have enabled the automatic mode, each INDEX | +| action is cleared automatically, else you must read | +| the index status ("i_APCI1710_ReadIndexStatus") | +| after each INDEX action. | +| | +| | +| Index action | +| ------------ | +| | +| +------------------------+------------------------------------+ | +| | b_IndexOperation | Operation | | +| |------------------------+------------------------------------| | +| |APCI1710_LATCH_COUNTER | After a index signal, the counter | | +| | | value (32-Bit) is latched in to | | +| | | the first latch register | | +| |------------------------|------------------------------------| | +| |APCI1710_CLEAR_COUNTER | After a index signal, the counter | | +| | | value is cleared (32-Bit) | | +| +------------------------+------------------------------------+ | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_ReferenceAction : Determine if the reference | +| must set or no for the | +| acceptance from index | +| APCI1710_ENABLE : | +| Reference must be set for | +| accepted the index | +| APCI1710_DISABLE : | +| Reference have not | +| importance | +| BYTE_ b_IndexOperation : Index operating mode. | +| See table. | +| BYTE_ b_AutoMode : Enable or disable the | +| automatic index reset. | +| APCI1710_ENABLE : | +| Enable the automatic mode | +| APCI1710_DISABLE : | +| Disable the automatic mode | +| BYTE_ b_InterruptEnable : Enable or disable the | +| interrupt. | +| APCI1710_ENABLE : | +| Enable the interrupt | +| APCI1710_DISABLE : | +| Disable the interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4 The reference action parameter is wrong | +| -5: The index operating mode parameter is wrong | +| -6: The auto mode parameter is wrong | +| -7: Interrupt parameter is wrong | +| -8: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitIndex (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_ReferenceAction, + BYTE b_IndexOperation, + BYTE b_AutoMode, + BYTE b_InterruptEnable) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /********************************/ + /* Test the reference parameter */ + /********************************/ + + if (b_ReferenceAction == APCI1710_ENABLE || + b_ReferenceAction == APCI1710_DISABLE) + { + /****************************/ + /* Test the index parameter */ + /****************************/ + + if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER || + b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER || + b_IndexOperation == APCI1710_HIGH_EDGE_CLEAR_COUNTER || + b_IndexOperation == APCI1710_LOW_EDGE_CLEAR_COUNTER || + b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || + b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + { + /********************************/ + /* Test the auto mode parameter */ + /********************************/ + + if (b_AutoMode == APCI1710_ENABLE || + b_AutoMode == APCI1710_DISABLE) + { + /***************************/ + /* Test the interrupt mode */ + /***************************/ + + if (b_InterruptEnable == APCI1710_ENABLE || + b_InterruptEnable == APCI1710_DISABLE) + { + + /************************************/ + /* Makte the configuration commando */ + /************************************/ + + if (b_ReferenceAction == APCI1710_ENABLE) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_ENABLE_INDEX_ACTION; + } + else + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & APCI1710_DISABLE_INDEX_ACTION; + } + + /****************************************/ + /* Test if low level latch or/and clear */ + /****************************************/ + + if (b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER || + b_IndexOperation == APCI1710_LOW_EDGE_CLEAR_COUNTER || + b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + { + /*************************************/ + /* Set the index level to low (DQ26) */ + /*************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 | APCI1710_SET_LOW_INDEX_LEVEL; + } + else + { + /**************************************/ + /* Set the index level to high (DQ26) */ + /**************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & APCI1710_SET_HIGH_INDEX_LEVEL; + } + + /***********************************/ + /* Test if latch and clear counter */ + /***********************************/ + + if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || + b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + { + /***************************************/ + /* Set the latch and clear flag (DQ27) */ + /***************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 | APCI1710_ENABLE_LATCH_AND_CLEAR; + } // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + else + { + /*****************************************/ + /* Clear the latch and clear flag (DQ27) */ + /*****************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & APCI1710_DISABLE_LATCH_AND_CLEAR; + + /*************************/ + /* Test if latch counter */ + /*************************/ + + if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER || + b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER) + { + /*********************************/ + /* Enable the latch from counter */ + /*********************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_INDEX_LATCH_COUNTER; + } + else + { + /*********************************/ + /* Enable the clear from counter */ + /*********************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & (~APCI1710_INDEX_LATCH_COUNTER); + } + } // // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + + + if (b_AutoMode == APCI1710_DISABLE) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_INDEX_AUTO_MODE; + } + else + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & (~APCI1710_INDEX_AUTO_MODE); + } + + if (b_InterruptEnable == APCI1710_ENABLE) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 | APCI1710_ENABLE_INDEX_INT; + } + else + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & APCI1710_DISABLE_INDEX_INT; + } + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInit = 1; + + } + else + { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue = -7; + } + } + else + { + /************************************/ + /* The auto mode parameter is wrong */ + /************************************/ + DPRINTK("The auto mode parameter is wrong\n"); + i_ReturnValue = -6; + } + } + else + { + /***********************************************/ + /* The index operating mode parameter is wrong */ + /***********************************************/ + DPRINTK("The index operating mode parameter is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /*******************************************/ + /* The reference action parameter is wrong */ + /*******************************************/ + DPRINTK("The reference action parameter is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitReference | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ReferenceLevel) | ++----------------------------------------------------------------------------+ +| Task : Initialise the reference corresponding to the selected | +| module (b_ModulNbr). | +| | +| Reference level | +| --------------- | +| +--------------------+-------------------------+ | +| | b_ReferenceLevel | Operation | | +| +--------------------+-------------------------+ | +| | APCI1710_LOW | Reference occur if "0" | | +| |--------------------|-------------------------| | +| | APCI1710_HIGH | Reference occur if "1" | | +| +--------------------+-------------------------+ | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_ReferenceLevel : Reference level. | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number parameter is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Reference level parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitReference (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_ReferenceLevel) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /**************************************/ + /* Test the reference level parameter */ + /**************************************/ + + if (b_ReferenceLevel == 0 || + b_ReferenceLevel == 1) + { + if (b_ReferenceLevel == 1) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_REFERENCE_HIGH; + } + else + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & APCI1710_REFERENCE_LOW; + } + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_ReferenceInit = 1; + } + else + { + /**************************************/ + /* Reference level parameter is wrong */ + /**************************************/ + DPRINTK("Reference level parameter is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitExternalStrobe | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ExternalStrobe, | +| BYTE_ b_ExternalStrobeLevel) | ++----------------------------------------------------------------------------+ +| Task : Initialises the external strobe level corresponding to | +| the selected module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_ExternalStrobe : External strobe selection | +| 0 : External strobe A | +| 1 : External strobe B | +| BYTE_ b_ExternalStrobeLevel : External strobe level | +| APCI1710_LOW : | +| External latch occurs if "0" | +| APCI1710_HIGH : | +| External latch occurs if "1" | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised. | +| See function "i_APCI1710_InitCounter" | +| -4: External strobe selection is wrong | +| -5: External strobe level parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitExternalStrobe (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_ExternalStrobe, + BYTE b_ExternalStrobeLevel) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /**************************************/ + /* Test the external strobe selection */ + /**************************************/ + + if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) + { + /******************/ + /* Test the level */ + /******************/ + + if ((b_ExternalStrobeLevel == APCI1710_HIGH) || + ((b_ExternalStrobeLevel == APCI1710_LOW && (devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3135))) + { + /*****************/ + /* Set the level */ + /*****************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & (0xFF - (0x10 << b_ExternalStrobe))) | + ((b_ExternalStrobeLevel^1) << (4 + b_ExternalStrobe)); + } + else + { + /********************************************/ + /* External strobe level parameter is wrong */ + /********************************************/ + DPRINTK("External strobe level parameter is wrong\n"); + i_ReturnValue = -5; + } + } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) + else + { + /**************************************/ + /* External strobe selection is wrong */ + /**************************************/ + DPRINTK("External strobe selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + /* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitCompareLogic | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| UINT_ ui_CompareValue) | ++----------------------------------------------------------------------------+ +| Task : Set the 32-Bit compare value. At that moment that the | +| incremental counter arrive to the compare value | +| (ui_CompareValue) a interrupt is generated. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| UINT_ ui_CompareValue : 32-Bit compare value | ++----------------------------------------------------------------------------+ +| Output Parameters : - ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitCompareLogic (comedi_device *dev, + BYTE b_ModulNbr, + UINT ui_CompareValue) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + + outl(ui_CompareValue,devpriv->s_BoardInfos. + ui_Address + 28 + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CompareLogicInit = 1; + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitFrequencyMeasurement | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_TimingUnity, | +| ULONG_ ul_TimingInterval, | +| PULONG_ pul_RealTimingInterval) | ++----------------------------------------------------------------------------+ +| Task : Sets the time for the frequency measurement. | +| Configures the selected TOR incremental counter of the | +| selected module (b_ModulNbr). The ul_TimingInterval and| +| ul_TimingUnity determine the time base for the | +| measurement. The pul_RealTimingInterval returns the | +| real time value. You must call up this function before | +| you call up any other function which gives access to | +| the frequency measurement. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | +| BYTE_ b_PCIInputClock : Selection of the PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC has a PCI bus clock | +| of 30 MHz | +| - APCI1710_33MHZ : | +| The PC has a PCI bus clock | +| of 33 MHz | +| BYTE_ b_TimingUnity : Base time unit (0 to 2) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| ULONG_ ul_TimingInterval: Base time value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealTimingInterval : Real base time value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected PCI input clock is wrong | +| -5: Timing unity selection is wrong | +| -6: Base timing selection is wrong | +| -7: 40MHz quartz not on board | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PCIInputClock, + BYTE b_TimingUnity, + ULONG ul_TimingInterval, + PULONG pul_RealTimingInterval) + { + INT i_ReturnValue = 0; + ULONG ul_TimerValue; + 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 >= 0) && (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 */ + /********************************/ + + 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; + } + + /*************************/ + /* Write the timer value */ + /*************************/ + + + outl(ul_TimerValue,devpriv->s_BoardInfos. + ui_Address + 32 + (64 * b_ModulNbr)); + + /*******************************/ + /* Set the initialisation flag */ + /*******************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementInit = 1; + } + else + { + /***************************/ + /* Counter not initialised */ + /***************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } // if (i_ReturnValue == 0) + } + else + { + /**********************************/ + /* Base timing selection is wrong */ + /**********************************/ + DPRINTK("Base timing selection is wrong\n"); + i_ReturnValue = -6; + } + } + else + { + /***********************************/ + /* Timing unity selection is wrong */ + /***********************************/ + DPRINTK("Timing unity selection is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/*########################################################################### */ + + //INSN BITS +/*########################################################################### */ + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Set & Clear Functions for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + UINT ui_BitsType; + INT i_ReturnValue=0; + ui_BitsType=CR_CHAN(insn->chanspec); + devpriv->tsk_Current=current; // Save the current process task structure + + switch(ui_BitsType) + { + case APCI1710_INCCPT_CLEARCOUNTERVALUE: + i_ReturnValue=i_APCI1710_ClearCounterValue (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_CLEARALLCOUNTERVALUE: + i_ReturnValue=i_APCI1710_ClearAllCounterValue (dev); + break; + + case APCI1710_INCCPT_SETINPUTFILTER: + i_ReturnValue=i_APCI1710_SetInputFilter (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1]); + break; + + case APCI1710_INCCPT_LATCHCOUNTER: + i_ReturnValue=i_APCI1710_LatchCounter (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0]); + break; + + case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE: + i_ReturnValue=i_APCI1710_SetIndexAndReferenceSource (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0]); + break; + + case APCI1710_INCCPT_SETDIGITALCHLON: + i_ReturnValue=i_APCI1710_SetDigitalChlOn (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_SETDIGITALCHLOFF: + i_ReturnValue=i_APCI1710_SetDigitalChlOff (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + default: + printk("Bits Config Parameter Wrong\n"); + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ClearCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Clear the counter value from selected module | +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number parameter is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ClearCounterValue (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*********************/ + /* Clear the counter */ + /*********************/ + + + outl(1,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ClearAllCounterValue | +| (BYTE_ b_BoardHandle) | ++----------------------------------------------------------------------------+ +| Task : Clear all counter value. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ClearAllCounterValue (comedi_device *dev) + { + BYTE b_ModulCpt = 0; + INT i_ReturnValue = 0; + + + /********************************/ + /* Test if counter module found */ + /********************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [0] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER || + (devpriv->s_BoardInfos. + dw_MolduleConfiguration [1] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER || + (devpriv->s_BoardInfos. + dw_MolduleConfiguration [2] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER || + (devpriv->s_BoardInfos. + dw_MolduleConfiguration [3] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + for (b_ModulCpt = 0; b_ModulCpt < 4 ; b_ModulCpt ++) + { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulCpt] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + /*********************/ + /* Clear the counter */ + /*********************/ + + + outl(1,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulCpt)); + } + } + } + else + { + /***************************/ + /* No counter module found */ + /***************************/ + DPRINTK("No counter module found\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetInputFilter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_Module, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_Filter) | ++----------------------------------------------------------------------------+ +| Task : Disable or enable the software filter from selected | +| module (b_ModulNbr). b_Filter determine the filter time| ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | +| BYTE_ b_PCIInputClock : Selection of the PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC has a PCI bus clock | +| of 30 MHz | +| - APCI1710_33MHZ : | +| The PC has a PCI bus clock | +| of 33 MHz | +| - APCI1710_40MHZ : | +| The APCI1710 has a 40MHz | +| quartz | +| BYTE_ b_Filter : Filter selection | +| | +| 30 MHz | +| ------ | +| 0: Software filter not used | +| 1: Filter from 266ns (3.750000MHz) | +| 2: Filter from 400ns (2.500000MHz) | +| 3: Filter from 533ns (1.876170MHz) | +| 4: Filter from 666ns (1.501501MHz) | +| 5: Filter from 800ns (1.250000MHz) | +| 6: Filter from 933ns (1.071800MHz) | +| 7: Filter from 1066ns (0.938080MHz) | +| 8: Filter from 1200ns (0.833333MHz) | +| 9: Filter from 1333ns (0.750000MHz) | +| 10: Filter from 1466ns (0.682100MHz) | +| 11: Filter from 1600ns (0.625000MHz) | +| 12: Filter from 1733ns (0.577777MHz) | +| 13: Filter from 1866ns (0.535900MHz) | +| 14: Filter from 2000ns (0.500000MHz) | +| 15: Filter from 2133ns (0.468800MHz) | +| | +| 33 MHz | +| ------ | +| 0: Software filter not used | +| 1: Filter from 242ns (4.125000MHz) | +| 2: Filter from 363ns (2.754820MHz) | +| 3: Filter from 484ns (2.066115MHz) | +| 4: Filter from 605ns (1.652892MHz) | +| 5: Filter from 726ns (1.357741MHz) | +| 6: Filter from 847ns (1.180637MHz) | +| 7: Filter from 968ns (1.033055MHz) | +| 8: Filter from 1089ns (0.918273MHz) | +| 9: Filter from 1210ns (0.826446MHz) | +| 10: Filter from 1331ns (0.751314MHz) | +| 11: Filter from 1452ns (0.688705MHz) | +| 12: Filter from 1573ns (0.635727MHz) | +| 13: Filter from 1694ns (0.590318MHz) | +| 14: Filter from 1815ns (0.550964MHz) | +| 15: Filter from 1936ns (0.516528MHz) | +| | +| 40 MHz | +| ------ | +| 0: Software filter not used | +| 1: Filter from 200ns (5.000000MHz) | +| 2: Filter from 300ns (3.333333MHz) | +| 3: Filter from 400ns (2.500000MHz) | +| 4: Filter from 500ns (2.000000MHz) | +| 5: Filter from 600ns (1.666666MHz) | +| 6: Filter from 700ns (1.428500MHz) | +| 7: Filter from 800ns (1.250000MHz) | +| 8: Filter from 900ns (1.111111MHz) | +| 9: Filter from 1000ns (1.000000MHz) | +| 10: Filter from 1100ns (0.909090MHz) | +| 11: Filter from 1200ns (0.833333MHz) | +| 12: Filter from 1300ns (0.769200MHz) | +| 13: Filter from 1400ns (0.714200MHz) | +| 14: Filter from 1500ns (0.666666MHz) | +| 15: Filter from 1600ns (0.625000MHz) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: The module is not a counter module | +| -4: The selected PCI input clock is wrong | +| -5: The selected filter value is wrong | +| -6: 40MHz quartz not on board | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetInputFilter (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PCIInputClock, + BYTE b_Filter) + { + INT i_ReturnValue = 0; + DWORD dw_Status = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + /******************************/ + /* Test if firmware >= Rev1.5 */ + /******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3135) + { + /**************************/ + /* Test the PCI bus clock */ + /**************************/ + + if ((b_PCIInputClock == APCI1710_30MHZ) || + (b_PCIInputClock == APCI1710_33MHZ) || + (b_PCIInputClock == APCI1710_40MHZ)) + { + /*************************/ + /* Test the filter value */ + /*************************/ + + if (b_Filter < 16) + { + /**********************/ + /* Test if 40MHz used */ + /**********************/ + + if (b_PCIInputClock == APCI1710_40MHZ) + { + /*********************************/ + /* Test if 40MHz quartz on board */ + /*********************************/ + + + dw_Status= inl(devpriv->s_BoardInfos. + ui_Address + 36 + (64 * b_ModulNbr)); + + /******************************/ + /* Test the quartz flag (DQ0) */ + /******************************/ + + if ((dw_Status & 1) != 1) + { + /*****************************/ + /* 40MHz quartz not on board */ + /*****************************/ + DPRINTK("40MHz quartz not on board\n"); + i_ReturnValue = -6; + } + } // if (b_PCIInputClock == APCI1710_40MHZ) + + /***************************/ + /* Test if error not occur */ + /***************************/ + + if (i_ReturnValue == 0) + { + /**********************/ + /* Test if 40MHz used */ + /**********************/ + + if (b_PCIInputClock == APCI1710_40MHZ) + { + /*********************************/ + /* Enable the 40MHz quarz (DQ31) */ + /*********************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 | APCI1710_ENABLE_40MHZ_FILTER; + + } // if (b_PCIInputClock == APCI1710_40MHZ) + else + { + /**********************************/ + /* Disable the 40MHz quarz (DQ31) */ + /**********************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & APCI1710_DISABLE_40MHZ_FILTER; + + } // if (b_PCIInputClock == APCI1710_40MHZ) + + /************************/ + /* Set the filter value */ + /************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = (devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & 0x1F) | ((b_Filter & 0x7) << 5); + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & 0xFE) | ((b_Filter & 0x8) >> 3); + + /***************************/ + /* Write the configuration */ + /***************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } // if (i_ReturnValue == 0) + } // if (b_Filter < 16) + else + { + /**************************************/ + /* The selected filter value is wrong */ + /**************************************/ + DPRINTK("The selected filter value is wrong\n"); + i_ReturnValue = -5; + } // if (b_Filter < 16) + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) + else + { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = 4; + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) + } + else + { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } + else + { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_LatchCounter (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_LatchReg) | ++----------------------------------------------------------------------------+ +| Task : Latch the courant value from selected module | +| (b_ModulNbr) in to the selected latch register | +| (b_LatchReg). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_LatchReg : Selected latch register | +| 0 : for the first latch register | +| 1 : for the second latch register | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected latch register parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_LatchCounter (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_LatchReg) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*************************************/ + /* Test the latch register parameter */ + /*************************************/ + + if (b_LatchReg < 2) + { + /*********************/ + /* Tatch the counter */ + /*********************/ + + outl(1 << (b_LatchReg * 4),devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + } + else + { + /**************************************************/ + /* The selected latch register parameter is wrong */ + /**************************************************/ + DPRINTK("The selected latch register parameter is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetIndexAndReferenceSource | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SourceSelection) | ++----------------------------------------------------------------------------+ +| Task : Determine the hardware source for the index and the | +| reference logic. Per default the index logic is | +| connected to the difference input C and the reference | +| logic is connected to the 24V input E | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_SourceSelection : APCI1710_SOURCE_0 : | +| The index logic is connected | +| to the difference input C and| +| the reference logic is | +| connected to the 24V input E.| +| This is the default | +| configuration. | +| APCI1710_SOURCE_1 : | +| The reference logic is | +| connected to the difference | +| input C and the index logic | +| is connected to the 24V | +| input E | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: The module is not a counter module. | +| -4: The source selection is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetIndexAndReferenceSource (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_SourceSelection) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + /******************************/ + /* Test if firmware >= Rev1.5 */ + /******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3135) + { + /*****************************/ + /* Test the source selection */ + /*****************************/ + + if (b_SourceSelection == APCI1710_SOURCE_0 || + b_SourceSelection == APCI1710_SOURCE_1) + { + /******************************************/ + /* Test if invert the index and reference */ + /******************************************/ + + if (b_SourceSelection == APCI1710_SOURCE_1) + { + /********************************************/ + /* Invert index and reference source (DQ25) */ + /********************************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 | APCI1710_INVERT_INDEX_RFERENCE; + } + else + { + /****************************************/ + /* Set the default configuration (DQ25) */ + /****************************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & APCI1710_DEFAULT_INDEX_RFERENCE; + } + } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) + else + { + /*********************************/ + /* The source selection is wrong */ + /*********************************/ + DPRINTK("The source selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) + } + else + { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } + else + { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } + else + { + /***************************************/ + /* The selected module number is wrong */ + /***************************************/ + DPRINTK("The selected module number is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetDigitalChlOn | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Sets the digital output H Setting an output means | +| setting an ouput high. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetDigitalChlOn (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 | 0x10; + + /*********************/ + /* Set the output On */ + /*********************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetDigitalChlOff | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Resets the digital output H. Resetting an output means | +| setting an ouput low. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetDigitalChlOff (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & 0xEF; + + /**********************/ + /* Set the output Off */ + /**********************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/*########################################################################### */ + + // INSN WRITE +/*########################################################################### */ + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Enable Disable functions for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + UINT ui_WriteType; + INT i_ReturnValue=0; + + ui_WriteType=CR_CHAN(insn->chanspec); + devpriv->tsk_Current=current; // Save the current process task structure + + switch(ui_WriteType) + { + case APCI1710_INCCPT_ENABLELATCHINTERRUPT: + i_ReturnValue = i_APCI1710_EnableLatchInterrupt (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_DISABLELATCHINTERRUPT: + i_ReturnValue = i_APCI1710_DisableLatchInterrupt (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE: + i_ReturnValue = i_APCI1710_Write16BitCounterValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (UINT) data[1]); + break; + + case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE: + i_ReturnValue = i_APCI1710_Write32BitCounterValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (ULONG) data[0]); + + break; + + case APCI1710_INCCPT_ENABLEINDEX: + i_APCI1710_EnableIndex (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_DISABLEINDEX: + i_ReturnValue = i_APCI1710_DisableIndex (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_ENABLECOMPARELOGIC: + i_ReturnValue = i_APCI1710_EnableCompareLogic (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_DISABLECOMPARELOGIC: + i_ReturnValue = i_APCI1710_DisableCompareLogic (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT: + i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0]); + break; + + case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT: + i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement (dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + default: + printk("Write Config Parameter Wrong\n"); + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableLatchInterrupt | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Enable the latch interrupt from selected module | +| (b_ModulNbr). Each software or hardware latch occur a | +| interrupt. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Interrupt routine not installed see function | +| "i_APCI1710_SetBoardIntRoutine" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnableLatchInterrupt (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + + /********************/ + /* Enable interrupt */ + /********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_ENABLE_LATCH_INT; + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableLatchInterrupt | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Disable the latch interrupt from selected module | +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Interrupt routine not installed see function | +| "i_APCI1710_SetBoardIntRoutine" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisableLatchInterrupt (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4 & ((APCI1710_DISABLE_LATCH_INT << 8) | 0xFF),devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + mdelay(1000); + + /*********************/ + /* Disable interrupt */ + /*********************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & APCI1710_DISABLE_LATCH_INT; + + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Write16BitCounterValue | +| (BYTE_ b_BoardHandle | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedCounter, | +| UINT_ ui_WriteValue) | ++----------------------------------------------------------------------------+ +| Task : Write a 16-Bit value (ui_WriteValue) in to the selected| +| 16-Bit counter (b_SelectedCounter) from selected module| +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_SelectedCounter : Selected 16-Bit counter | +| (0 or 1) | +| UINT_ ui_WriteValue : 16-Bit write value | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected 16-Bit counter parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Write16BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_SelectedCounter, + UINT ui_WriteValue) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /******************************/ + /* Test the counter selection */ + /******************************/ + + if (b_SelectedCounter < 2) + { + /*******************/ + /* Write the value */ + /*******************/ + + outl((ULONG) ((ULONG) (ui_WriteValue) << (16 * b_SelectedCounter)),devpriv->s_BoardInfos. + ui_Address + 8 + (b_SelectedCounter * 4) + (64 * b_ModulNbr)); + } + else + { + /**************************************************/ + /* The selected 16-Bit counter parameter is wrong */ + /**************************************************/ + DPRINTK("The selected 16-Bit counter parameter is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Write32BitCounterValue | +| (BYTE_ b_BoardHandle | +| BYTE_ b_ModulNbr, | +| ULONG_ ul_WriteValue) | ++----------------------------------------------------------------------------+ +| Task : Write a 32-Bit value (ui_WriteValue) in to the selected| +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| ULONG_ ul_WriteValue : 32-Bit write value | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Write32BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + ULONG ul_WriteValue) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*******************/ + /* Write the value */ + /*******************/ + + outl(ul_WriteValue,devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableIndex (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Enable the INDEX actions | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Index not initialised see function | +| "i_APCI1710_InitIndex" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnableIndex (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + ULONG ul_InterruptLatchReg; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*****************************/ + /* Test if index initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInit) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_ENABLE_INDEX; + + ul_InterruptLatchReg=inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModulNbr)); + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /*************************************************************/ + /* Index not initialised see function "i_APCI1710_InitIndex" */ + /*************************************************************/ + DPRINTK("Index not initialised \n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableIndex (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Disable the INDEX actions | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Index not initialised see function | +| "i_APCI1710_InitIndex" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisableIndex (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*****************************/ + /* Test if index initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInit) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & APCI1710_DISABLE_INDEX; + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /*************************************************************/ + /* Index not initialised see function "i_APCI1710_InitIndex" */ + /*************************************************************/ + DPRINTK("Index not initialised \n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableCompareLogic | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Enable the 32-Bit compare logic. At that moment that | +| the incremental counter arrive to the compare value a | +| interrupt is generated. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Compare logic not initialised. | +| See function "i_APCI1710_InitCompareLogic" | +| -5: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnableCompareLogic (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*************************************/ + /* Test if compare logic initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CompareLogicInit == 1) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 | APCI1710_ENABLE_COMPARE_INT; + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /*********************************/ + /* Compare logic not initialised */ + /*********************************/ + DPRINTK("Compare logic not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableCompareLogic | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Disable the 32-Bit compare logic. ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Compare logic not initialised. | +| See function "i_APCI1710_InitCompareLogic" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisableCompareLogic (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*************************************/ + /* Test if compare logic initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CompareLogicInit == 1) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & APCI1710_DISABLE_COMPARE_INT; + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /*********************************/ + /* Compare logic not initialised */ + /*********************************/ + DPRINTK("Compare logic not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + /* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableFrequencyMeasurement | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Enables the frequency measurement function | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | +| BYTE_ b_InterruptEnable: Enable or disable the | +| interrupt. | +| APCI1710_ENABLE: | +| Enable the interrupt | +| APCI1710_DISABLE: | +| Disable the interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Frequency measurement logic not initialised. | +| See function "i_APCI1710_InitFrequencyMeasurement" | +| -5: Interrupt parameter is wrong | +| -6: Interrupt function not initialised. | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnableFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_InterruptEnable) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /********************************************/ + /* Test if frequency mesurement initialised */ + /********************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementInit == 1) + { + /***************************/ + /* Test the interrupt mode */ + /***************************/ + + if ((b_InterruptEnable == APCI1710_DISABLE) || + (b_InterruptEnable == APCI1710_ENABLE)) + { + + /************************************/ + /* Enable the frequency measurement */ + /************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 | APCI1710_ENABLE_FREQUENCY; + + /*********************************************/ + /* Disable or enable the frequency interrupt */ + /*********************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & APCI1710_DISABLE_FREQUENCY_INT) | (b_InterruptEnable << 3); + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementEnable = 1; + } + else + { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /***********************************************/ + /* Frequency measurement logic not initialised */ + /***********************************************/ + DPRINTK("Frequency measurement logic not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + /* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableFrequencyMeasurement | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Disables the frequency measurement function | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Frequency measurement logic not initialised. | +| See function "i_APCI1710_InitFrequencyMeasurement" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisableFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /********************************************/ + /* Test if frequency mesurement initialised */ + /********************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementInit == 1) + { + /*************************************/ + /* Disable the frequency measurement */ + /*************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & APCI1710_DISABLE_FREQUENCY + // Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared + & APCI1710_DISABLE_FREQUENCY_INT; + // End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + /*************************************/ + /* Disable the frequency measurement */ + /*************************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementEnable = 0; + } + else + { + /***********************************************/ + /* Frequency measurement logic not initialised */ + /***********************************************/ + DPRINTK("Frequency measurement logic not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/*########################################################################### */ + + // INSN READ + +/*########################################################################### */ + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read and Get functions for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_InsnReadINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + UINT ui_ReadType; + INT i_ReturnValue=0; + + ui_ReadType=CR_CHAN(insn->chanspec); + devpriv->tsk_Current=current; // Save the current process task structure + switch(ui_ReadType) + { + case APCI1710_INCCPT_READLATCHREGISTERSTATUS: + i_ReturnValue=i_APCI1710_ReadLatchRegisterStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_RANGE(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_INCCPT_READLATCHREGISTERVALUE: + i_ReturnValue=i_APCI1710_ReadLatchRegisterValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_RANGE(insn->chanspec), + (PULONG) &data[0]); + printk("Latch Register Value %d\n",data[0]); + break; + + case APCI1710_INCCPT_READ16BITCOUNTERVALUE: + i_ReturnValue=i_APCI1710_Read16BitCounterValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_RANGE(insn->chanspec), + (PUINT) &data[0]); + break; + + case APCI1710_INCCPT_READ32BITCOUNTERVALUE: + i_ReturnValue=i_APCI1710_Read32BitCounterValue (dev, + (BYTE) CR_AREF(insn->chanspec), + (PULONG) &data[0]); + break; + + case APCI1710_INCCPT_GETINDEXSTATUS: + i_ReturnValue=i_APCI1710_GetIndexStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_INCCPT_GETREFERENCESTATUS: + i_ReturnValue=i_APCI1710_GetReferenceStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_INCCPT_GETUASSTATUS: + i_ReturnValue=i_APCI1710_GetUASStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_INCCPT_GETCBSTATUS: + i_ReturnValue=i_APCI1710_GetCBStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_INCCPT_GET16BITCBSTATUS: + i_ReturnValue=i_APCI1710_Get16BitCBStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0], + (PBYTE) &data[1]); + break; + + case APCI1710_INCCPT_GETUDSTATUS: + i_ReturnValue=i_APCI1710_GetUDStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0]); + + break; + + case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS: + i_ReturnValue=i_APCI1710_GetInterruptUDLatchedStatus (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0]); + break; + + case APCI1710_INCCPT_READFREQUENCYMEASUREMENT: + i_ReturnValue=i_APCI1710_ReadFrequencyMeasurement (dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) &data[0], + (PBYTE) &data[1], + (PULONG) &data[2]); + break; + + case APCI1710_INCCPT_READINTERRUPT: + data[0]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].b_OldModuleMask; + data[1]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldInterruptMask; + data[2]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldCounterLatchValue; + + + /**************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv-> + s_InterruptParameters. + ui_Read = (devpriv->s_InterruptParameters. + ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + + break; + + default: + printk("ReadType Parameter wrong\n"); + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); + +} + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadLatchRegisterStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_LatchReg, | +| PBYTE_ pb_LatchStatus) | ++----------------------------------------------------------------------------+ +| Task : Read the latch register status from selected module | +| (b_ModulNbr) and selected latch register (b_LatchReg). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_LatchReg : Selected latch register | +| 0 : for the first latch register | +| 1 : for the second latch register | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_LatchStatus : Latch register status. | +| 0 : No latch occur | +| 1 : A software latch occur | +| 2 : A hardware latch occur | +| 3 : A software and hardware | +| latch occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected latch register parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadLatchRegisterStatus (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_LatchReg, + PBYTE pb_LatchStatus) + { + INT i_ReturnValue = 0; + DWORD dw_LatchReg; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*************************************/ + /* Test the latch register parameter */ + /*************************************/ + + if (b_LatchReg < 2) + { + dw_LatchReg=inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + *pb_LatchStatus = (BYTE) ((dw_LatchReg >> (b_LatchReg * 4)) & 0x3); + } + else + { + /**************************************************/ + /* The selected latch register parameter is wrong */ + /**************************************************/ + DPRINTK("The selected latch register parameter is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadLatchRegisterValue | +| (BYTE_ b_BoardHandle,| +| BYTE_ b_ModulNbr, | +| BYTE_ b_LatchReg, | +| PULONG_ pul_LatchValue) | ++----------------------------------------------------------------------------+ +| Task : Read the latch register value from selected module | +| (b_ModulNbr) and selected latch register (b_LatchReg). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_LatchReg : Selected latch register | +| 0 : for the first latch register | +| 1 : for the second latch register | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_LatchValue : Latch register value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected latch register parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadLatchRegisterValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_LatchReg, + PULONG pul_LatchValue) + { + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*************************************/ + /* Test the latch register parameter */ + /*************************************/ + + if (b_LatchReg < 2) + { + *pul_LatchValue=inl(devpriv->s_BoardInfos. + ui_Address + ((b_LatchReg + 1) * 4) + (64 * b_ModulNbr)); + + } + else + { + /**************************************************/ + /* The selected latch register parameter is wrong */ + /**************************************************/ + DPRINTK("The selected latch register parameter is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Read16BitCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedCounter, | +| PUINT_ pui_CounterValue) | ++----------------------------------------------------------------------------+ +| Task : Latch the selected 16-Bit counter (b_SelectedCounter) | +| from selected module (b_ModulNbr) in to the first | +| latch register and return the latched value. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_SelectedCounter : Selected 16-Bit counter | +| (0 or 1) | ++----------------------------------------------------------------------------+ +| Output Parameters : PUINT_ pui_CounterValue : 16-Bit counter value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected 16-Bit counter parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Read16BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_SelectedCounter, + PUINT pui_CounterValue) + { + INT i_ReturnValue = 0; + DWORD dw_LathchValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /******************************/ + /* Test the counter selection */ + /******************************/ + + if (b_SelectedCounter < 2) + { + /*********************/ + /* Latch the counter */ + /*********************/ + + outl(1,devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + /************************/ + /* Read the latch value */ + /************************/ + + dw_LathchValue=inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + + *pui_CounterValue = (UINT) ((dw_LathchValue >> (16 * b_SelectedCounter)) & 0xFFFFU); + } + else + { + /**************************************************/ + /* The selected 16-Bit counter parameter is wrong */ + /**************************************************/ + DPRINTK("The selected 16-Bit counter parameter is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Read32BitCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PULONG_ pul_CounterValue) | ++----------------------------------------------------------------------------+ +| Task : Latch the 32-Bit counter from selected module | +| (b_ModulNbr) in to the first latch register and return | +| the latched value. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_CounterValue : 32-Bit counter value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Read32BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + PULONG pul_CounterValue) + { + INT i_ReturnValue = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*********************/ + /* Tatch the counter */ + /*********************/ + + outl(1,devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + /************************/ + /* Read the latch value */ + /************************/ + + *pul_CounterValue=inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetIndexStatus (BYTE_ b_BoardHandle,| +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_IndexStatus)| ++----------------------------------------------------------------------------+ +| Task : Return the index status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_IndexStatus : 0 : No INDEX occur | +| 1 : A INDEX occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Index not initialised see function | +| "i_APCI1710_InitIndex" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetIndexStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_IndexStatus) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*****************************/ + /* Test if index initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInit) + { + dw_StatusReg= inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + *pb_IndexStatus = (BYTE) (dw_StatusReg & 1); + } + else + { + /*************************************************************/ + /* Index not initialised see function "i_APCI1710_InitIndex" */ + /*************************************************************/ + DPRINTK("Index not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetReferenceStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_ReferenceStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the reference status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_ReferenceStatus : 0 : No REFERENCE occur | +| 1 : A REFERENCE occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Reference not initialised see function | +| "i_APCI1710_InitReference" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetReferenceStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_ReferenceStatus) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*********************************/ + /* Test if reference initialised */ + /*********************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_ReferenceInit) + { + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModulNbr)); + + *pb_ReferenceStatus = (BYTE) (~dw_StatusReg & 1); + } + else + { + /*********************************************************************/ + /* Reference not initialised see function "i_APCI1710_InitReference" */ + /*********************************************************************/ + DPRINTK("Reference not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetUASStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_UASStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the error signal (UAS) status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_UASStatus : 0 : UAS is low "0" | +| 1 : UAS is high "1" | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetUASStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_UASStatus) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModulNbr)); + + *pb_UASStatus = (BYTE) ((dw_StatusReg >> 1) & 1); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetCBStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_CBStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the counter overflow status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_CBStatus : 0 : Counter no overflow | +| 1 : Counter overflow | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetCBStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_CBStatus) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + *pb_CBStatus = (BYTE) (dw_StatusReg & 1); + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Get16BitCBStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_CBStatusCounter0, | +| PBYTE_ pb_CBStatusCounter1) | ++----------------------------------------------------------------------------+ +| Task : Returns the counter overflow (counter initialised to | +| 2*16-bit) status from selected incremental counter | +| module | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_CBStatusCounter0 : 0 : No overflow occur for | +| the first 16-bit | +| counter | +| 1 : Overflow occur for the| +| first 16-bit counter | +| PBYTE_ pb_CBStatusCounter1 : 0 : No overflow occur for | +| the second 16-bit | +| counter | +| 1 : Overflow occur for the| +| second 16-bit counter | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Counter not initialised to 2*16-bit mode. | +| See function "i_APCI1710_InitCounter" | +| -5: Firmware revision error | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Get16BitCBStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_CBStatusCounter0, + PBYTE pb_CBStatusCounter1) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*************************/ + /* Test if 2*16-Bit mode */ + /*************************/ + + if ((devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 & 0x10) == 0x10) + { + /*****************************/ + /* Test the Firmware version */ + /*****************************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) + { + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + *pb_CBStatusCounter1 = (BYTE) ((dw_StatusReg >> 0) & 1); + *pb_CBStatusCounter0 = (BYTE) ((dw_StatusReg >> 1) & 1); + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) + else + { + /****************************/ + /* Firmware revision error */ + /****************************/ + + i_ReturnValue = -5; + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) + else + { + /********************************************/ + /* Counter not initialised to 2*16-bit mode */ + /* "i_APCI1710_InitCounter" */ + /********************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -4; + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) + } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) + } // if (b_ModulNbr < 4) + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } // if (b_ModulNbr < 4) + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetUDStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_UDStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the counter progress status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_UDStatus : 0 : Counter progress in the | +| selected mode down | +| 1 : Counter progress in the | +| selected mode up | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetUDStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_UDStatus) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModulNbr)); + + *pb_UDStatus = (BYTE) ((dw_StatusReg >> 2) & 1); + + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetInterruptUDLatchedStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_UDStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the counter progress latched status after a | +| index interrupt occur. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_UDStatus : 0 : Counter progress in the | +| selected mode down | +| 1 : Counter progress in the | +| selected mode up | +| 2 : No index interrupt occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetInterruptUDLatchedStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_UDStatus) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /*********************************/ + /* Test if index interrupt occur */ + /*********************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInterruptOccur == 1) + { + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInterruptOccur = 0; + + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + *pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 1); + } + else + { + /****************************/ + /* No index interrupt occur */ + /****************************/ + + *pb_UDStatus = 2; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + /* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadFrequencyMeasurement | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_Status, | +| PULONG_ pul_ReadValue) | ++----------------------------------------------------------------------------+ +| Task : Returns the status (pb_Status) and the number of | +| increments in the set time. | +| See function " i_APCI1710_InitFrequencyMeasurement " | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_Status : Returns the frequency | +| measurement status | +| 0 : Counting cycle not | +| started. | +| 1 : Counting cycle started. | +| 2 : Counting cycle stopped. | +| The measurement cycle is | +| completed. | +| PBYTE_ pb_UDStatus : 0 : Counter progress in the | +| selected mode down | +| 1 : Counter progress in the | +| selected mode up | +| PULONG_ pul_ReadValue : Return the number of | +| increments in the defined | +| time base. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Frequency measurement logic not initialised. | +| See function "i_APCI1710_InitFrequencyMeasurement" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_Status, + PBYTE pb_UDStatus, + PULONG pul_ReadValue) + { + INT i_ReturnValue = 0; + UINT ui_16BitValue; + DWORD dw_StatusReg; + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_CounterInit == 1) + { + /********************************************/ + /* Test if frequency mesurement initialised */ + /********************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementInit == 1) + { + /******************/ + /* Test if enable */ + /******************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementEnable == 1) + { + /*******************/ + /* Read the status */ + /*******************/ + + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + 32 + (64 * b_ModulNbr)); + + /**************************/ + /* Test if frequency stop */ + /**************************/ + + if (dw_StatusReg & 1) + { + *pb_Status = 2; + *pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 3); + + /******************/ + /* Read the value */ + /******************/ + + *pul_ReadValue=inl(devpriv->s_BoardInfos. + ui_Address + 28 + (64 * b_ModulNbr)); + + if (*pb_UDStatus == 0) + { + /*************************/ + /* Test the counter mode */ + /*************************/ + + if ((devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER) + { + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFFU) != 0) + { + ui_16BitValue = (UINT) *pul_ReadValue & 0xFFFFU; + *pul_ReadValue = (*pul_ReadValue & 0xFFFF0000UL) | (0xFFFFU - ui_16BitValue); + } + + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFF0000UL) != 0) + { + ui_16BitValue = (UINT) ((*pul_ReadValue >> 16) & 0xFFFFU); + *pul_ReadValue = (*pul_ReadValue & 0xFFFFUL) | ((0xFFFFU - ui_16BitValue) << 16); + } + } + else + { + if (*pul_ReadValue != 0) + { + *pul_ReadValue = 0xFFFFFFFFUL - *pul_ReadValue; + } + } + } + else + { + if (*pb_UDStatus == 1) + { + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFF0000UL) != 0) + { + ui_16BitValue = (UINT) ((*pul_ReadValue >> 16) & 0xFFFFU); + *pul_ReadValue = (*pul_ReadValue & 0xFFFFUL) | ((0xFFFFU - ui_16BitValue) << 16); + } + } + else + { + if (*pb_UDStatus == 2) + { + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFFU) != 0) + { + ui_16BitValue = (UINT) *pul_ReadValue & 0xFFFFU; + *pul_ReadValue = (*pul_ReadValue & 0xFFFF0000UL) | (0xFFFFU - ui_16BitValue); + } + } + } + } + } + else + { + *pb_Status = 1; + *pb_UDStatus = 0; + } + } + else + { + *pb_Status = 0; + *pb_UDStatus = 0; + } + } + else + { + /***********************************************/ + /* Frequency measurement logic not initialised */ + /***********************************************/ + DPRINTK("Frequency measurement logic not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } + else + { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } diff --git a/comedi/drivers/addi-data/APCI1710_INCCPT.h b/comedi/drivers/addi-data/APCI1710_INCCPT.h new file mode 100644 index 00000000..5f3bb095 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_INCCPT.h @@ -0,0 +1,308 @@ + + + +#define APCI1710_16BIT_COUNTER 0x10 +#define APCI1710_32BIT_COUNTER 0x0 +#define APCI1710_QUADRUPLE_MODE 0x0 +#define APCI1710_DOUBLE_MODE 0x3 +#define APCI1710_SIMPLE_MODE 0xF +#define APCI1710_DIRECT_MODE 0x80 +#define APCI1710_HYSTERESIS_ON 0x60 +#define APCI1710_HYSTERESIS_OFF 0x0 +#define APCI1710_INCREMENT 0x60 +#define APCI1710_DECREMENT 0x0 +#define APCI1710_LATCH_COUNTER 0x1 +#define APCI1710_CLEAR_COUNTER 0x0 +#define APCI1710_LOW 0x0 +#define APCI1710_HIGH 0x1 + +/*********************/ +/* Version 0600-0229 */ +/*********************/ + +#define APCI1710_HIGH_EDGE_CLEAR_COUNTER 0x0 +#define APCI1710_HIGH_EDGE_LATCH_COUNTER 0x1 +#define APCI1710_LOW_EDGE_CLEAR_COUNTER 0x2 +#define APCI1710_LOW_EDGE_LATCH_COUNTER 0x3 +#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER 0x4 +#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER 0x5 +#define APCI1710_SOURCE_0 0x0 +#define APCI1710_SOURCE_1 0x1 + + + +#define APCI1710_30MHZ 30 +#define APCI1710_33MHZ 33 +#define APCI1710_40MHZ 40 + + +#define APCI1710_ENABLE_LATCH_INT 0x80 +#define APCI1710_DISABLE_LATCH_INT (~APCI1710_ENABLE_LATCH_INT) + +#define APCI1710_INDEX_LATCH_COUNTER 0x10 +#define APCI1710_INDEX_AUTO_MODE 0x8 +#define APCI1710_ENABLE_INDEX 0x4 +#define APCI1710_DISABLE_INDEX (~APCI1710_ENABLE_INDEX) +#define APCI1710_ENABLE_LATCH_AND_CLEAR 0x8 +#define APCI1710_DISABLE_LATCH_AND_CLEAR (~APCI1710_ENABLE_LATCH_AND_CLEAR) +#define APCI1710_SET_LOW_INDEX_LEVEL 0x4 +#define APCI1710_SET_HIGH_INDEX_LEVEL (~APCI1710_SET_LOW_INDEX_LEVEL) +#define APCI1710_INVERT_INDEX_RFERENCE 0x2 +#define APCI1710_DEFAULT_INDEX_RFERENCE (~APCI1710_INVERT_INDEX_RFERENCE) + +#define APCI1710_ENABLE_INDEX_INT 0x1 +#define APCI1710_DISABLE_INDEX_INT (~APCI1710_ENABLE_INDEX_INT) + +#define APCI1710_ENABLE_FREQUENCY 0x4 +#define APCI1710_DISABLE_FREQUENCY (~APCI1710_ENABLE_FREQUENCY) + +#define APCI1710_ENABLE_FREQUENCY_INT 0x8 +#define APCI1710_DISABLE_FREQUENCY_INT (~APCI1710_ENABLE_FREQUENCY_INT) + +#define APCI1710_ENABLE_40MHZ_FREQUENCY 0x40 +#define APCI1710_DISABLE_40MHZ_FREQUENCY (~APCI1710_ENABLE_40MHZ_FREQUENCY) + +#define APCI1710_ENABLE_40MHZ_FILTER 0x80 +#define APCI1710_DISABLE_40MHZ_FILTER (~APCI1710_ENABLE_40MHZ_FILTER) + +#define APCI1710_ENABLE_COMPARE_INT 0x2 +#define APCI1710_DISABLE_COMPARE_INT (~APCI1710_ENABLE_COMPARE_INT) + +#define APCI1710_ENABLE_INDEX_ACTION 0x20 +#define APCI1710_DISABLE_INDEX_ACTION (~APCI1710_ENABLE_INDEX_ACTION) +#define APCI1710_REFERENCE_HIGH 0x40 +#define APCI1710_REFERENCE_LOW (~APCI1710_REFERENCE_HIGH) + + + #define APCI1710_TOR_GATE_LOW 0x40 + #define APCI1710_TOR_GATE_HIGH (~APCI1710_TOR_GATE_LOW) + + +// INSN CONFIG +#define APCI1710_INCCPT_INITCOUNTER 100 +#define APCI1710_INCCPT_COUNTERAUTOTEST 101 +#define APCI1710_INCCPT_INITINDEX 102 +#define APCI1710_INCCPT_INITREFERENCE 103 +#define APCI1710_INCCPT_INITEXTERNALSTROBE 104 +#define APCI1710_INCCPT_INITCOMPARELOGIC 105 +#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT 106 + +// INSN READ +#define APCI1710_INCCPT_READLATCHREGISTERSTATUS 200 +#define APCI1710_INCCPT_READLATCHREGISTERVALUE 201 +#define APCI1710_INCCPT_READ16BITCOUNTERVALUE 202 +#define APCI1710_INCCPT_READ32BITCOUNTERVALUE 203 +#define APCI1710_INCCPT_GETINDEXSTATUS 204 +#define APCI1710_INCCPT_GETREFERENCESTATUS 205 +#define APCI1710_INCCPT_GETUASSTATUS 206 +#define APCI1710_INCCPT_GETCBSTATUS 207 +#define APCI1710_INCCPT_GET16BITCBSTATUS 208 +#define APCI1710_INCCPT_GETUDSTATUS 209 +#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS 210 +#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT 211 +#define APCI1710_INCCPT_READINTERRUPT 212 + +//INSN BITS +#define APCI1710_INCCPT_CLEARCOUNTERVALUE 300 +#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE 301 +#define APCI1710_INCCPT_SETINPUTFILTER 302 +#define APCI1710_INCCPT_LATCHCOUNTER 303 +#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE 304 +#define APCI1710_INCCPT_SETDIGITALCHLON 305 +#define APCI1710_INCCPT_SETDIGITALCHLOFF 306 + +// INSN WRITE +#define APCI1710_INCCPT_ENABLELATCHINTERRUPT 400 +#define APCI1710_INCCPT_DISABLELATCHINTERRUPT 401 +#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE 402 +#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE 403 +#define APCI1710_INCCPT_ENABLEINDEX 404 +#define APCI1710_INCCPT_DISABLEINDEX 405 +#define APCI1710_INCCPT_ENABLECOMPARELOGIC 406 +#define APCI1710_INCCPT_DISABLECOMPARELOGIC 407 +#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT 408 +#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT 409 + + +/************ Main Functions *************/ +INT i_APCI1710_InsnConfigINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InsnBitsINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InsnWriteINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InsnReadINCCPT(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + +/*********** Supplementary Functions********/ + + +// INSN CONFIG + +INT i_APCI1710_InitCounter (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_CounterRange, + BYTE b_FirstCounterModus, + BYTE b_FirstCounterOption, + BYTE b_SecondCounterModus, + BYTE b_SecondCounterOption); + +INT i_APCI1710_CounterAutoTest (comedi_device *dev,PBYTE pb_TestStatus); + +INT i_APCI1710_InitIndex (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_ReferenceAction, + BYTE b_IndexOperation, + BYTE b_AutoMode, + BYTE b_InterruptEnable); + +INT i_APCI1710_InitReference (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_ReferenceLevel); + +INT i_APCI1710_InitExternalStrobe (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_ExternalStrobe, + BYTE b_ExternalStrobeLevel); + +INT i_APCI1710_InitCompareLogic (comedi_device *dev, + BYTE b_ModulNbr, + UINT ui_CompareValue); + +INT i_APCI1710_InitFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PCIInputClock, + BYTE b_TimingUnity, + ULONG ul_TimingInterval, + PULONG pul_RealTimingInterval); + + +//INSN BITS + +INT i_APCI1710_ClearCounterValue (comedi_device *dev, + BYTE b_ModulNbr); + +INT i_APCI1710_ClearAllCounterValue (comedi_device *dev); + +INT i_APCI1710_SetInputFilter (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PCIInputClock, + BYTE b_Filter); + +INT i_APCI1710_LatchCounter (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_LatchReg); + +INT i_APCI1710_SetIndexAndReferenceSource (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_SourceSelection); + +INT i_APCI1710_SetDigitalChlOn (comedi_device *dev, + BYTE b_ModulNbr); + +INT i_APCI1710_SetDigitalChlOff (comedi_device *dev, + BYTE b_ModulNbr); + + +// INSN WRITE +INT i_APCI1710_EnableLatchInterrupt (comedi_device *dev, + BYTE b_ModulNbr); + + +INT i_APCI1710_DisableLatchInterrupt (comedi_device *dev, + BYTE b_ModulNbr); + +INT i_APCI1710_Write16BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_SelectedCounter, + UINT ui_WriteValue); + +INT i_APCI1710_Write32BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + ULONG ul_WriteValue); + +INT i_APCI1710_EnableIndex (comedi_device *dev, + BYTE b_ModulNbr); + +INT i_APCI1710_DisableIndex (comedi_device *dev, + BYTE b_ModulNbr); + +INT i_APCI1710_EnableCompareLogic (comedi_device *dev, + BYTE b_ModulNbr); + +INT i_APCI1710_DisableCompareLogic (comedi_device *dev, + BYTE b_ModulNbr); + +INT i_APCI1710_EnableFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_InterruptEnable); + +INT i_APCI1710_DisableFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr); + + +// INSN READ + +INT i_APCI1710_ReadLatchRegisterStatus (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_LatchReg, + PBYTE pb_LatchStatus); + +INT i_APCI1710_ReadLatchRegisterValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_LatchReg, + PULONG pul_LatchValue); + +INT i_APCI1710_Read16BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_SelectedCounter, + PUINT pui_CounterValue); + +INT i_APCI1710_Read32BitCounterValue (comedi_device *dev, + BYTE b_ModulNbr, + PULONG pul_CounterValue); + +INT i_APCI1710_GetIndexStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_IndexStatus); + +INT i_APCI1710_GetReferenceStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_ReferenceStatus); + +INT i_APCI1710_GetUASStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_UASStatus); + +INT i_APCI1710_GetCBStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_CBStatus); + +INT i_APCI1710_Get16BitCBStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_CBStatusCounter0, + PBYTE pb_CBStatusCounter1); + +INT i_APCI1710_GetUDStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_UDStatus); + +INT i_APCI1710_GetInterruptUDLatchedStatus (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_UDStatus); + +INT i_APCI1710_ReadFrequencyMeasurement (comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_Status, + PBYTE pb_UDStatus, + PULONG pul_ReadValue); + + + + + + + diff --git a/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/comedi/drivers/addi-data/APCI1710_Inp_cpt.c new file mode 100644 index 00000000..bd27ada5 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Inp_cpt.c @@ -0,0 +1,760 @@ +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : INP_CPT.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 27.08.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 pulse encoder module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Inp_cpt.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitPulseEncoder | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PulseEncoderNbr, | +| BYTE_ b_InputLevelSelection, | +| BYTE_ b_TriggerOutputAction, | +| ULONG_ ul_StartValue) | ++----------------------------------------------------------------------------+ +| Task : Configure the pulse encoder operating mode selected via| +| b_ModulNbr and b_PulseEncoderNbr. The pulse encoder | +| after each pulse decrement the counter value from 1. | +| | +| You must calling this function be for you call any | +| other function witch access of pulse encoders. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_PulseEncoderNbr : Pulse encoder selection | +| (0 to 3) | +| BYTE_ b_InputLevelSelection : Input level selection | +| (0 or 1) | +| 0 : Set pulse encoder| +| count the the low| +| level pulse. | +| 1 : Set pulse encoder| +| count the the | +| high level pulse.| +| BYTE_ b_TriggerOutputAction : Digital TRIGGER output | +| action | +| 0 : No action | +| 1 : Set the trigger | +| output to "1" | +| (high) after the | +| passage from 1 to| +| 0 from pulse | +| encoder. | +| 2 : Set the trigger | +| output to "0" | +| (low) after the | +| passage from 1 to| +| 0 from pulse | +| encoder | +| ULONG_ ul_StartValue : Pulse encoder start value| +| (1 to 4294967295) + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_PulseEncoderNbr =(BYTE) data[0]; + b_InputLevelSelection =(BYTE) data[1]; + b_TriggerOutputAction =(BYTE) data[2]; + ul_StartValue =(ULONG) data[3]; + | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module is not a pulse encoder module | +| -3: Pulse encoder selection is wrong | +| -4: Input level selection is wrong | +| -5: Digital TRIGGER output action selection is wrong | +| -6: Pulse encoder start value is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_IntRegister; + + BYTE b_ModulNbr; + BYTE b_PulseEncoderNbr; + BYTE b_InputLevelSelection; + BYTE b_TriggerOutputAction; + ULONG ul_StartValue; + + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_PulseEncoderNbr =(BYTE) data[0]; + b_InputLevelSelection =(BYTE) data[1]; + b_TriggerOutputAction =(BYTE) data[2]; + ul_StartValue =(ULONG) data[3]; + i_ReturnValue =insn->n; + + + /***********************************/ + /* Test the selected module number */ + /***********************************/ + + if (b_ModulNbr >= 0 && 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 >= 0 && b_PulseEncoderNbr <= 3) + { + /************************/ + /* Test the input level */ + /************************/ + + if ((b_InputLevelSelection == 0) || (b_InputLevelSelection == 1)) + { + /*******************************************/ + /* Test the ouput TRIGGER action selection */ + /*******************************************/ + + if ((b_TriggerOutputAction >= 0 && b_TriggerOutputAction <= 2) || (b_PulseEncoderNbr > 0)) + { + if (ul_StartValue > 1) + { + + dw_IntRegister= inl(devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr)); + + /***********************/ + /* Set the start value */ + /***********************/ + + + outl(ul_StartValue,devpriv->s_BoardInfos.ui_Address + (b_PulseEncoderNbr * 4) + (64 * b_ModulNbr)); + + /***********************/ + /* Set the input level */ + /***********************/ + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister = (devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister & (0xFFFFFFFFUL - (1UL << (8 + b_PulseEncoderNbr)))) | + ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr)); + + /*******************************/ + /* Test if output trigger used */ + /*******************************/ + + if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1)) + { + /****************************/ + /* Enable the output action */ + /****************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister | + (1UL << (4 + b_PulseEncoderNbr)); + + /*********************************/ + /* Set the output TRIGGER action */ + /*********************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister = (devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister & (0xFFFFFFFFUL - (1UL << (12 + b_PulseEncoderNbr)))) | + ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr)); + } + else + { + /*****************************/ + /* Disable the output action */ + /*****************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister & (0xFFFFFFFFUL - (1UL << (4 + b_PulseEncoderNbr))); + } + + /*************************/ + /* Set the configuration */ + /*************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo.dw_SetRegister,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo [b_PulseEncoderNbr]. + b_PulseEncoderInit = 1; + } + else + { + /**************************************/ + /* Pulse encoder start value is wrong */ + /**************************************/ + DPRINTK("Pulse encoder start value is wrong\n"); + i_ReturnValue = -6; + } + } + else + { + /****************************************************/ + /* Digital TRIGGER output action selection is wrong */ + /****************************************************/ + DPRINTK("Digital TRIGGER output action selection is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /**********************************/ + /* Input level selection is wrong */ + /**********************************/ + DPRINTK("Input level selection is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /************************************/ + /* Pulse encoder selection is wrong */ + /************************************/ + DPRINTK("Pulse encoder selection is wrong\n"); + i_ReturnValue = -3; + } + } + else + { + /********************************************/ + /* The module is not a pulse encoder module */ + /********************************************/ + DPRINTK("The module is not a pulse encoder module\n"); + i_ReturnValue = -2; + } + } + else + { + /********************************************/ + /* The module is not a pulse encoder module */ + /********************************************/ + DPRINTK("The module is not a pulse encoder module\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnablePulseEncoder | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PulseEncoderNbr, | +| BYTE_ b_CycleSelection, | +| BYTE_ b_InterruptHandling) | ++----------------------------------------------------------------------------+ +| Task : Enableor disable the selected pulse encoder (b_PulseEncoderNbr) | +| from selected module (b_ModulNbr). Each input pulse | +| decrement the pulse encoder counter value from 1. | +| If you enabled the interrupt (b_InterruptHandling), a | +| interrupt is generated when the pulse encoder has run | +| down. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_PulseEncoderNbr : Pulse encoder selection | +| (0 to 3) | +| BYTE_ b_CycleSelection : APCI1710_CONTINUOUS: | +| Each time the | +| counting value is set| +| on "0", the pulse | +| encoder load the | +| start value after | +| the next pulse. | +| APCI1710_SINGLE: | +| If the counter is set| +| on "0", the pulse | +| encoder is stopped. | +| BYTE_ b_InterruptHandling : Interrupts can be | +| generated, when the pulse| +| encoder has run down. | +| With this parameter the | +| user decides if | +| interrupts are used or | +| not. | +| APCI1710_ENABLE: | +| Interrupts are enabled | +| APCI1710_DISABLE: | +| Interrupts are disabled + + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_Action =(BYTE) data[0]; + b_PulseEncoderNbr =(BYTE) data[1]; + b_CycleSelection =(BYTE) data[2]; + b_InterruptHandling =(BYTE) data[3];| ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection is wrong | +| -3: Pulse encoder selection is wrong | +| -4: Pulse encoder not initialised. | +| See function "i_APCI1710_InitPulseEncoder" | +| -5: Cycle selection mode is wrong | +| -6: Interrupt handling mode is wrong | +| -7: Interrupt routine not installed. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + + + INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + BYTE b_ModulNbr; + BYTE b_PulseEncoderNbr ; + BYTE b_CycleSelection ; + BYTE b_InterruptHandling; + BYTE b_Action; + + i_ReturnValue =insn->n; + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_Action =(BYTE) data[0]; + b_PulseEncoderNbr =(BYTE) data[1]; + b_CycleSelection =(BYTE) data[2]; + b_InterruptHandling =(BYTE) data[3]; + + + /***********************************/ + /* Test the selected module number */ + /***********************************/ + + if (b_ModulNbr >= 0 && b_ModulNbr <= 3) + { + /******************************************/ + /* Test the selected pulse encoder number */ + /******************************************/ + + if (b_PulseEncoderNbr >= 0 && b_PulseEncoderNbr <= 3) + { + /*************************************/ + /* Test if pulse encoder initialised */ + /*************************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo [b_PulseEncoderNbr]. + b_PulseEncoderInit == 1) + { + switch(b_Action) + { + + case APCI1710_ENABLE: + /****************************/ + /* Test the cycle selection */ + /****************************/ + + if (b_CycleSelection == APCI1710_CONTINUOUS || b_CycleSelection == APCI1710_SINGLE) + { + /*******************************/ + /* Test the interrupt handling */ + /*******************************/ + + if (b_InterruptHandling == APCI1710_ENABLE || b_InterruptHandling == APCI1710_DISABLE) + { + /******************************/ + /* Test if interrupt not used */ + /******************************/ + + if (b_InterruptHandling == APCI1710_DISABLE) + { + /*************************/ + /* Disable the interrupt */ + /*************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister & (0xFFFFFFFFUL - (1UL << b_PulseEncoderNbr)); + } + else + { + + /************************/ + /* Enable the interrupt */ + /************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister = devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister | (1UL << b_PulseEncoderNbr); + devpriv->tsk_Current=current; // Save the current process task structure + + + } + + if (i_ReturnValue>=0) + { + /***********************************/ + /* Enable or disable the interrupt */ + /***********************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister,devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + /****************************/ + /* Enable the pulse encoder */ + /****************************/ + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister = devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister | (1UL << b_PulseEncoderNbr); + + /**********************/ + /* Set the cycle mode */ + /**********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister = (devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister & (0xFFFFFFFFUL - (1 << (b_PulseEncoderNbr + 4)))) | + ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr)); + + /****************************/ + /* Enable the pulse encoder */ + /****************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + } + } + else + { + /************************************/ + /* Interrupt handling mode is wrong */ + /************************************/ + DPRINTK("Interrupt handling mode is wrong\n"); + i_ReturnValue = -6; + } + } + else + { + /*********************************/ + /* Cycle selection mode is wrong */ + /*********************************/ + DPRINTK("Cycle selection mode is wrong\n"); + i_ReturnValue = -5; + } + break; + + case APCI1710_DISABLE: + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister = devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister & (0xFFFFFFFFUL - (1UL << b_PulseEncoderNbr)); + + /*****************************/ + /* Disable the pulse encoder */ + /*****************************/ + + + outl(devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister,devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + break; + }// switch End + + } + else + { + /*********************************/ + /* Pulse encoder not initialised */ + /*********************************/ + DPRINTK("Pulse encoder not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /************************************/ + /* Pulse encoder selection is wrong */ + /************************************/ + DPRINTK("Pulse encoder selection is wrong\n"); + i_ReturnValue = -3; + } + } + else + { + /*****************************/ + /* Module selection is wrong */ + /*****************************/ + DPRINTK("Module selection is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadPulseEncoderStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PulseEncoderNbr, | +| PBYTE_ pb_Status) | ++----------------------------------------------------------------------------+ +| Task APCI1710_PULSEENCODER_READ : Reads the pulse encoder status + and valuefrom selected pulse | +| encoder (b_PulseEncoderNbr) from selected module | +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ + BYTE b_Type; data[0] + APCI1710_PULSEENCODER_WRITE + Writes a 32-bit value (ul_WriteValue) into the selected| +| pulse encoder (b_PulseEncoderNbr) from selected module | +| (b_ModulNbr). This operation set the new start pulse | +| encoder value. + APCI1710_PULSEENCODER_READ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| CRAREF() BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| data[1] BYTE_ b_PulseEncoderNbr : Pulse encoder selection | +| (0 to 3) + APCI1710_PULSEENCODER_WRITE + data[2] ULONG_ ul_WriteValue : 32-bit value to be | +| written | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_Status : Pulse encoder status. | +| 0 : No overflow occur| +| 1 : Overflow occur + PULONG_ pul_ReadValue : Pulse encoder value | | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection is wrong | +| -3: Pulse encoder selection is wrong | +| -4: Pulse encoder not initialised. | +| See function "i_APCI1710_InitPulseEncoder" | ++----------------------------------------------------------------------------+ +*/ + + +/*_INT_ i_APCI1710_ReadPulseEncoderStatus (BYTE_ b_BoardHandle, + BYTE_ b_ModulNbr, + BYTE_ b_PulseEncoderNbr, + + PBYTE_ pb_Status) + */ +INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_StatusRegister; + BYTE b_ModulNbr; + BYTE b_PulseEncoderNbr; + PBYTE pb_Status; + BYTE b_Type; + PULONG pul_ReadValue; + ULONG ul_WriteValue ; + + i_ReturnValue=insn->n; + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_Type =(BYTE) data[0] ; + b_PulseEncoderNbr=(BYTE) data[1]; + pb_Status =(PBYTE) &data[0]; + pul_ReadValue =(PULONG) &data[1]; + + /***********************************/ + /* Test the selected module number */ + /***********************************/ + + if (b_ModulNbr >= 0 && b_ModulNbr <= 3) + { + /******************************************/ + /* Test the selected pulse encoder number */ + /******************************************/ + + if (b_PulseEncoderNbr >= 0 && b_PulseEncoderNbr <= 3) + { + /*************************************/ + /* Test if pulse encoder initialised */ + /*************************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo [b_PulseEncoderNbr]. + b_PulseEncoderInit == 1) + { + + switch(b_Type) + { + case APCI1710_PULSEENCODER_READ: + /****************************/ + /* Read the status register */ + /****************************/ + + + dw_StatusRegister=inl(devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister | dw_StatusRegister; + + *pb_Status = (BYTE) (devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister >> (1 + b_PulseEncoderNbr)) & 1; + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister = devpriv->s_ModuleInfo [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister & (0xFFFFFFFFUL - (1 << (1 + b_PulseEncoderNbr))); + + /******************/ + /* Read the value */ + /******************/ + + + *pul_ReadValue=inl(devpriv->s_BoardInfos. + ui_Address + (4 * b_PulseEncoderNbr) + (64 * b_ModulNbr)); + break; + + case APCI1710_PULSEENCODER_WRITE: + ul_WriteValue = (ULONG) data[2]; + /*******************/ + /* Write the value */ + /*******************/ + + + outl(ul_WriteValue,devpriv->s_BoardInfos. + ui_Address + (4 * b_PulseEncoderNbr) + (64 * b_ModulNbr)); + + }//end of switch + } + else + { + /*********************************/ + /* Pulse encoder not initialised */ + /*********************************/ + DPRINTK("Pulse encoder not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /************************************/ + /* Pulse encoder selection is wrong */ + /************************************/ + DPRINTK("Pulse encoder selection is wrong\n"); + i_ReturnValue = -3; + } + } + else + { + /*****************************/ + /* Module selection is wrong */ + /*****************************/ + DPRINTK("Module selection is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +{ + + data[0] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].b_OldModuleMask; + data[1] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldInterruptMask; + data[2] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldCounterLatchValue; + + + /***************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv->s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + return insn->n; + + +} + + diff --git a/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/comedi/drivers/addi-data/APCI1710_Inp_cpt.h new file mode 100644 index 00000000..7265a724 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Inp_cpt.h @@ -0,0 +1,38 @@ + + + + #define APCI1710_SINGLE 0 + #define APCI1710_CONTINUOUS 1 + + +#define APCI1710_PULSEENCODER_READ 0 +#define APCI1710_PULSEENCODER_WRITE 1 + + +INT i_APCI1710_InsnConfigInitPulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + + + +INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); +/* ++----------------------------------------------------------------------------+ +| READ PULSE ENCODER FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadInterruptPulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + +/* ++----------------------------------------------------------------------------+ +| WRITE PULSE ENCODER FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + + INT i_APCI1710_InsnBitsReadWritePulseEncoder(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + diff --git a/comedi/drivers/addi-data/APCI1710_Pwm.c b/comedi/drivers/addi-data/APCI1710_Pwm.c new file mode 100644 index 00000000..588dc35f --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Pwm.c @@ -0,0 +1,2517 @@ + + + + +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : PWM.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 22.01.99 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 Wulse wide modulation module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +-----------------------------------------------------------------------+ + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + + +#include "APCI1710_Pwm.h" + + + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnConfigPWM(comedi_device *dev, +comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Pwm Init and Get Pwm Initialisation | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigPWM(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + BYTE b_ConfigType; + INT i_ReturnValue=0; + b_ConfigType=CR_CHAN(insn->chanspec); + + switch(b_ConfigType) + { + case APCI1710_PWM_INIT : + i_ReturnValue=i_APCI1710_InitPWM (dev, + (BYTE)CR_AREF(insn->chanspec), // b_ModulNbr + (BYTE) data[0], //b_PWM + (BYTE) data[1], // b_ClockSelection + (BYTE) data[2], // b_TimingUnit + (ULONG)data[3], //ul_LowTiming + (ULONG)data[4], //ul_HighTiming + (PULONG)&data[0], //pul_RealLowTiming + (PULONG)&data[1] //pul_RealHighTiming + ); + break; + + case APCI1710_PWM_GETINITDATA : + i_ReturnValue=i_APCI1710_GetPWMInitialisation (dev, + (BYTE)CR_AREF(insn->chanspec), // b_ModulNbr + (BYTE) data[0], //b_PWM + (PBYTE)&data[0], //pb_TimingUnit + (PULONG)&data[1], //pul_LowTiming + (PULONG)&data[2], //pul_HighTiming + (PBYTE) &data[3], // pb_StartLevel + (PBYTE) &data[4], // pb_StopMode + (PBYTE) &data[5], // pb_StopLevel + (PBYTE) &data[6], // pb_ExternGate + (PBYTE) &data[7], // pb_InterruptEnable + (PBYTE) &data[8] // pb_Enable + ); + break; + + default: + printk(" Config Parameter Wrong\n"); + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); +} + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitPWM | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_ClockSelection, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_LowTiming, | +| ULONG_ ul_HighTiming, | +| PULONG_ pul_RealLowTiming, | +| PULONG_ pul_RealHighTiming) | ++----------------------------------------------------------------------------+ +| Task : Configure the selected PWM (b_PWM) from selected module| +| (b_ModulNbr). The ul_LowTiming, ul_HighTiming and | +| ul_TimingUnit determine the low/high timing base for | +| the period. pul_RealLowTiming, pul_RealHighTiming | +| return the real timing value. | +| You must calling this function be for you call any | +| other function witch access of the PWM. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure| +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1). | +| BYTE_ b_ClockSelection : Selection from PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC have a 30 MHz | +| PCI bus clock | +| - APCI1710_33MHZ : | +| The PC have a 33 MHz | +| PCI bus clock | +| - APCI1710_40MHZ | +| The APCI-1710 have a | +| integrated 40Mhz | +| quartz. | +| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_LowTiming : Low base timing value. | +| ULONG_ ul_HighTiming : High base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealLowTiming : Real low base timing | +| value. | +| PULONG_ pul_RealHighTiming : Real high base timing | +| value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: The selected input clock is wrong | +| -6: Timing Unit selection is wrong | +| -7: Low base timing selection is wrong | +| -8: High base timing selection is wrong | +| -9: You can not used the 40MHz clock selection with | +| this board | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitPWM (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_ClockSelection, + BYTE b_TimingUnit, + ULONG ul_LowTiming, + ULONG ul_HighTiming, + PULONG pul_RealLowTiming, + PULONG pul_RealHighTiming) + { + INT i_ReturnValue = 0; + ULONG ul_LowTimerValue; + ULONG ul_HighTimerValue; + DWORD dw_Command; + double d_RealLowTiming; + double d_RealHighTiming; + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_PWM) + { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM >= 0 && b_PWM <= 1) + { + /******************/ + /* Test the clock */ + /******************/ + + if ((b_ClockSelection == APCI1710_30MHZ) || + (b_ClockSelection == APCI1710_33MHZ) || + (b_ClockSelection == APCI1710_40MHZ)) + { + /************************/ + /* Test the timing unit */ + /************************/ + + if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + { + /*********************************/ + /* Test the low timing selection */ + /*********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_LowTiming >= 266) && (ul_LowTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_LowTiming >= 1) && (ul_LowTiming <= 571230650UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_LowTiming >= 1) && (ul_LowTiming <= 571230UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_LowTiming >= 1) && (ul_LowTiming <= 571UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_LowTiming >= 1) && (ul_LowTiming <= 9UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_LowTiming >= 242) && (ul_LowTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_LowTiming >= 1) && (ul_LowTiming <= 519691043UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_LowTiming >= 1) && (ul_LowTiming <= 519691UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_LowTiming >= 1) && (ul_LowTiming <= 520UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_LowTiming >= 1) && (ul_LowTiming <= 8UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_LowTiming >= 200) && (ul_LowTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_LowTiming >= 1) && (ul_LowTiming <= 429496729UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_LowTiming >= 1) && (ul_LowTiming <= 429496UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_LowTiming >= 1) && (ul_LowTiming <= 429UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_LowTiming >= 1) && (ul_LowTiming <= 7UL))) + { + /**********************************/ + /* Test the High timing selection */ + /**********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) + { + /**************************/ + /* Test the board version */ + /**************************/ + + if ((b_ClockSelection == APCI1710_40MHZ) && (devpriv-> + s_BoardInfos. + b_BoardVersion > 0) || + (b_ClockSelection != APCI1710_40MHZ)) + { + + /************************************/ + /* Calculate the low division fator */ + /************************************/ + + switch (b_TimingUnit) + { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) (ul_LowTiming * (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (0.00025 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming = (ULONG) (ul_LowTimerValue / (0.00025 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / (0.00025 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (0.00025 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealLowTiming + 0.5)) + { + *pul_RealLowTiming = *pul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) (ul_LowTiming * (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (0.25 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming = (ULONG) (ul_LowTimerValue / (0.25 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / ((double) 0.25 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (0.25 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealLowTiming + 0.5)) + { + *pul_RealLowTiming = *pul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = ul_LowTiming * (250.0 * b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (250.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming = (ULONG) (ul_LowTimerValue / (250.0 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / (250.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (250.0 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealLowTiming + 0.5)) + { + *pul_RealLowTiming = *pul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) (ul_LowTiming * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming = (ULONG) (ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealLowTiming + 0.5)) + { + *pul_RealLowTiming = *pul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) ((ul_LowTiming * 60) * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) (ul_LowTiming * 60.0) * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming = (ULONG) (ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) / 60; + d_RealLowTiming = ((double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0; + + if ((double) (((double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0) >= (double) ((double) *pul_RealLowTiming + 0.5)) + { + *pul_RealLowTiming = *pul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + break; + } + + /*************************************/ + /* Calculate the high division fator */ + /*************************************/ + + switch (b_TimingUnit) + { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) (ul_HighTiming * (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (0.00025 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming = (ULONG) (ul_HighTimerValue / (0.00025 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / (0.00025 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (0.00025 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealHighTiming + 0.5)) + { + *pul_RealHighTiming = *pul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) (ul_HighTiming * (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (0.25 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming = (ULONG) (ul_HighTimerValue / (0.25 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / ((double) 0.25 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (0.25 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealHighTiming + 0.5)) + { + *pul_RealHighTiming = *pul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = ul_HighTiming * (250.0 * b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (250.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming = (ULONG) (ul_HighTimerValue / (250.0 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / (250.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (250.0 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealHighTiming + 0.5)) + { + *pul_RealHighTiming = *pul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) (ul_HighTiming * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming = (ULONG) (ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) >= (double) ((double) *pul_RealHighTiming + 0.5)) + { + *pul_RealHighTiming = *pul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) ((ul_HighTiming * 60) * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) (ul_HighTiming * 60.0) * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming = (ULONG) (ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) / 60; + d_RealHighTiming = ((double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0; + + if ((double) (((double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0) >= (double) ((double) *pul_RealHighTiming + 0.5)) + { + *pul_RealHighTiming = *pul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + break; + } + + /****************************/ + /* Save the clock selection */ + /****************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + b_ClockSelection = b_ClockSelection; + + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + b_TimingUnit = b_TimingUnit; + + /****************************/ + /* Save the low base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + d_LowTiming = d_RealLowTiming; + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + ul_RealLowTiming = *pul_RealLowTiming; + + /****************************/ + /* Save the high base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + d_HighTiming = d_RealHighTiming; + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + ul_RealHighTiming = *pul_RealHighTiming; + + /************************/ + /* Write the low timing */ + /************************/ + + outl(ul_LowTimerValue,devpriv->s_BoardInfos. + ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************************/ + /* Write the high timing */ + /*************************/ + + outl(ul_HighTimerValue,devpriv->s_BoardInfos. + ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /***************************/ + /* Set the clock selection */ + /***************************/ + + dw_Command=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command = dw_Command & 0x7F; + + if (b_ClockSelection == APCI1710_40MHZ) + { + dw_Command = dw_Command | 0x80; + } + + /***************************/ + /* Set the clock selection */ + /***************************/ + + outl(dw_Command,devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************/ + /* PWM init. */ + /*************/ + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + b_PWMInit = 1; + } + else + { + /***************************************************/ + /* You can not used the 40MHz clock selection with */ + /* this board */ + /***************************************************/ + DPRINTK("You can not used the 40MHz clock selection with this board\n"); + i_ReturnValue = -9; + } + } + else + { + /***************************************/ + /* High base timing selection is wrong */ + /***************************************/ + DPRINTK("High base timing selection is wrong\n"); + i_ReturnValue = -8; + } + } + else + { + /**************************************/ + /* Low base timing selection is wrong */ + /**************************************/ + DPRINTK("Low base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else + { + /**********************************/ + /* Timing unit selection is wrong */ + /**********************************/ + DPRINTK("Timing unit selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) + else + { + /*******************************/ + /* The selected clock is wrong */ + /*******************************/ + DPRINTK("The selected clock is wrong\n"); + i_ReturnValue = -5; + } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) + } // if (b_PWM >= 0 && b_PWM <= 1) + else + { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } + else + { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetPWMInitialisation | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| PBYTE_ pb_TimingUnit, | +| PULONG_ pul_LowTiming, | +| PULONG_ pul_HighTiming, | +| PBYTE_ pb_StartLevel, | +| PBYTE_ pb_StopMode, | +| PBYTE_ pb_StopLevel, | +| PBYTE_ pb_ExternGate, | +| PBYTE_ pb_InterruptEnable, | +| PBYTE_ pb_Enable) | ++----------------------------------------------------------------------------+ +| Task : Return the PWM (b_PWM) initialisation from selected | +| module (b_ModulNbr). You must calling the | +| "i_APCI1710_InitPWM" function be for you call this | +| function. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| PULONG_ pul_LowTiming : Low base timing value. | +| PULONG_ pul_HighTiming : High base timing value. | +| PBYTE_ pb_StartLevel : Start period level | +| selection | +| 0 : The period start | +| with a low level | +| 1 : The period start | +| with a high level| +| PBYTE_ pb_StopMode : Stop mode selection | +| 0 : The PWM is stopped | +| directly after the | +| "i_APCI1710_DisablePWM"| +| function and break the| +| last period | +| 1 : After the | +| "i_APCI1710_DisablePWM"| +| function the PWM is | +| stopped at the end | +| from last period cycle| +| PBYTE_ pb_StopLevel : Stop PWM level selection | +| 0 : The output signal | +| keep the level after| +| the | +| "i_APCI1710_DisablePWM"| +| function | +| 1 : The output signal is| +| set to low after the| +| "i_APCI1710_DisablePWM"| +| function | +| 2 : The output signal is| +| set to high after | +| the | +| "i_APCI1710_DisablePWM"| +| function | +| PBYTE_ pb_ExternGate : Extern gate action | +| selection | +| 0 : Extern gate signal | +| not used. | +| 1 : Extern gate signal | +| used. | +| PBYTE_ pb_InterruptEnable : Enable or disable the PWM | +| interrupt. | +| - APCI1710_ENABLE : | +| Enable the PWM interrupt| +| A interrupt occur after | +| each period | +| - APCI1710_DISABLE : | +| Disable the PWM | +| interrupt | +| PBYTE_ pb_Enable : Indicate if the PWM is | +| enabled or no | +| 0 : PWM not enabled | +| 1 : PWM enabled | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetPWMInitialisation (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + PBYTE pb_TimingUnit, + PULONG pul_LowTiming, + PULONG pul_HighTiming, + PBYTE pb_StartLevel, + PBYTE pb_StopMode, + PBYTE pb_StopLevel, + PBYTE pb_ExternGate, + PBYTE pb_InterruptEnable, + PBYTE pb_Enable) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_Command; + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_PWM) + { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM >= 0 && b_PWM <= 1) + { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) + { + /***********************/ + /* Read the low timing */ + /***********************/ + + *pul_LowTiming = inl(devpriv->s_BoardInfos. + ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /************************/ + /* Read the high timing */ + /************************/ + + *pul_HighTiming= inl(devpriv->s_BoardInfos. + ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /********************/ + /* Read the command */ + /********************/ + + dw_Command = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + *pb_StartLevel = (BYTE) ((dw_Command >> 5) & 1); + *pb_StopMode = (BYTE) ((dw_Command >> 0) & 1); + *pb_StopLevel = (BYTE) ((dw_Command >> 1) & 1); + *pb_ExternGate = (BYTE) ((dw_Command >> 4) & 1); + *pb_InterruptEnable = (BYTE) ((dw_Command >> 3) & 1); + + if (*pb_StopLevel) + { + *pb_StopLevel = *pb_StopLevel + (BYTE) ((dw_Command >> 2) & 1); + } + + /********************/ + /* Read the command */ + /********************/ + + dw_Command=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + *pb_Enable = (BYTE) ((dw_Command >> 0) & 1); + + *pb_TimingUnit = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + b_TimingUnit; + } // if (dw_Status & 0x10) + else + { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else + { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } + else + { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnWritePWM(comedi_device *dev, +comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Pwm Enable Disable and Set New Timing | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWritePWM(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) +{ + BYTE b_WriteType; + INT i_ReturnValue=0; + b_WriteType=CR_CHAN(insn->chanspec); + + switch(b_WriteType) + { + case APCI1710_PWM_ENABLE : + i_ReturnValue=i_APCI1710_EnablePWM (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (BYTE) data[2], + (BYTE) data[3], + (BYTE) data[4], + (BYTE) data[5]); + break; + + case APCI1710_PWM_DISABLE : + i_ReturnValue=i_APCI1710_DisablePWM (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0]); + break; + + case APCI1710_PWM_NEWTIMING: + i_ReturnValue=i_APCI1710_SetNewPWMTiming (dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (ULONG) data[2], + (ULONG) data[3]); + break; + + + default: + printk("Write Config Parameter Wrong\n"); + } + + if(i_ReturnValue>=0) i_ReturnValue =insn->n; + return (i_ReturnValue); +} + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnablePWM | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_StartLevel, | +| BYTE_ b_StopMode, | +| BYTE_ b_StopLevel, | +| BYTE_ b_ExternGate, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Enable the selected PWM (b_PWM) from selected module | +| (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"| +| function be for you call this function. | +| If you enable the PWM interrupt, the PWM generate a | +| interrupt after each period. | +| See function "i_APCI1710_SetBoardIntRoutineX" and the | +| Interrupt mask description chapter. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | +| BYTE_ b_StartLevel : Start period level selection | +| 0 : The period start with a | +| low level | +| 1 : The period start with a | +| high level | +| BYTE_ b_StopMode : Stop mode selection | +| 0 : The PWM is stopped | +| directly after the | +| "i_APCI1710_DisablePWM" | +| function and break the | +| last period | +| 1 : After the | +| "i_APCI1710_DisablePWM" | +| function the PWM is | +| stopped at the end from| +| last period cycle. | +| BYTE_ b_StopLevel : Stop PWM level selection | +| 0 : The output signal keep | +| the level after the | +| "i_APCI1710_DisablePWM" | +| function | +| 1 : The output signal is set| +| to low after the | +| "i_APCI1710_DisablePWM" | +| function | +| 2 : The output signal is set| +| to high after the | +| "i_APCI1710_DisablePWM" | +| function | +| BYTE_ b_ExternGate : Extern gate action selection | +| 0 : Extern gate signal not | +| used. | +| 1 : Extern gate signal used.| +| BYTE_ b_InterruptEnable : Enable or disable the PWM | +| interrupt. | +| - APCI1710_ENABLE : | +| Enable the PWM interrupt | +| A interrupt occur after | +| each period | +| - APCI1710_DISABLE : | +| Disable the PWM interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM start level selection is wrong | +| -7: PWM stop mode selection is wrong | +| -8: PWM stop level selection is wrong | +| -9: Extern gate signal selection is wrong | +| -10: Interrupt parameter is wrong | +| -11: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnablePWM (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_StartLevel, + BYTE b_StopMode, + BYTE b_StopLevel, + BYTE b_ExternGate, + BYTE b_InterruptEnable) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_Command; + + devpriv->tsk_Current=current; // Save the current process task structure + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_PWM) + { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM >= 0 && b_PWM <= 1) + { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status= inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) + { + /**********************************/ + /* Test the start level selection */ + /**********************************/ + + if (b_StartLevel >= 0 && b_StartLevel <= 1) + { + /**********************/ + /* Test the stop mode */ + /**********************/ + + if (b_StopMode >= 0 && b_StopMode <= 1) + { + /***********************/ + /* Test the stop level */ + /***********************/ + + if (b_StopLevel >= 0 && b_StopLevel <= 2) + { + /*****************************/ + /* Test the extern gate mode */ + /*****************************/ + + if (b_ExternGate >= 0 && b_ExternGate <= 1) + { + /*****************************/ + /* Test the interrupt action */ + /*****************************/ + + if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) + { + /******************************************/ + /* Test if interrupt function initialised */ + /******************************************/ + + /********************/ + /* Read the command */ + /********************/ + + dw_Command=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command = dw_Command & 0x80; + + /********************/ + /* Make the command */ + /********************/ + + dw_Command = dw_Command | b_StopMode | (b_InterruptEnable << 3) | (b_ExternGate << 4) | (b_StartLevel << 5); + + if (b_StopLevel & 3) + { + dw_Command = dw_Command | 2; + + if (b_StopLevel & 2) + { + dw_Command = dw_Command | 4; + } + } + + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + b_InterruptEnable = b_InterruptEnable; + + /*******************/ + /* Set the command */ + /*******************/ + + outl(dw_Command,devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /******************/ + /* Enable the PWM */ + /******************/ + outl(1,devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + } // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) + else + { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue = -10; + } // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + else + { + /*****************************************/ + /* Extern gate signal selection is wrong */ + /*****************************************/ + DPRINTK("Extern gate signal selection is wrong\n"); + i_ReturnValue = -9; + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + } // if (b_StopLevel >= 0 && b_StopLevel <= 2) + else + { + /*************************************/ + /* PWM stop level selection is wrong */ + /*************************************/ + DPRINTK("PWM stop level selection is wrong\n"); + i_ReturnValue = -8; + } // if (b_StopLevel >= 0 && b_StopLevel <= 2) + } // if (b_StopMode >= 0 && b_StopMode <= 1) + else + { + /************************************/ + /* PWM stop mode selection is wrong */ + /************************************/ + DPRINTK("PWM stop mode selection is wrong\n"); + i_ReturnValue = -7; + } // if (b_StopMode >= 0 && b_StopMode <= 1) + } // if (b_StartLevel >= 0 && b_StartLevel <= 1) + else + { + /**************************************/ + /* PWM start level selection is wrong */ + /**************************************/ + DPRINTK("PWM start level selection is wrong\n"); + i_ReturnValue = -6; + } // if (b_StartLevel >= 0 && b_StartLevel <= 1) + } // if (dw_Status & 0x10) + else + { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else + { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } + else + { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisablePWM (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM) | ++----------------------------------------------------------------------------+ +| Task : Disable the selected PWM (b_PWM) from selected module | +| (b_ModulNbr). The output signal level depend of the | +| initialisation by the "i_APCI1710_EnablePWM". | +| See the b_StartLevel, b_StopMode and b_StopLevel | +| parameters from this function. | ++----------------------------------------------------------------------------+ +| Input Parameters :BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM not enabled see function | +| "i_APCI1710_EnablePWM" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisablePWM (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_PWM) + { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM >= 0 && b_PWM <= 1) + { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) + { + /***********************/ + /* Test if PWM enabled */ + /***********************/ + + if (dw_Status & 0x1) + { + /*******************/ + /* Disable the PWM */ + /*******************/ + outl(0,devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + } // if (dw_Status & 0x1) + else + { + /*******************/ + /* PWM not enabled */ + /*******************/ + DPRINTK("PWM not enabled\n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } // if (dw_Status & 0x10) + else + { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK(" PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else + { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } + else + { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetNewPWMTiming | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_ClockSelection, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_LowTiming, | +| ULONG_ ul_HighTiming) | ++----------------------------------------------------------------------------+ +| Task : Set a new timing. The ul_LowTiming, ul_HighTiming and | +| ul_TimingUnit determine the low/high timing base for | +| the period. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure| +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1). | +| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_LowTiming : Low base timing value. | +| ULONG_ ul_HighTiming : High base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised | +| -6: Timing Unit selection is wrong | +| -7: Low base timing selection is wrong | +| -8: High base timing selection is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetNewPWMTiming (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_TimingUnit, + ULONG ul_LowTiming, + ULONG ul_HighTiming) + { + BYTE b_ClockSelection; + INT i_ReturnValue = 0; + ULONG ul_LowTimerValue; + ULONG ul_HighTimerValue; + ULONG ul_RealLowTiming; + ULONG ul_RealHighTiming; + DWORD dw_Status; + DWORD dw_Command; + double d_RealLowTiming; + double d_RealHighTiming; + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_PWM) + { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM >= 0 && b_PWM <= 1) + { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) + { + b_ClockSelection = devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + b_ClockSelection; + + /************************/ + /* Test the timing unit */ + /************************/ + + if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + { + /*********************************/ + /* Test the low timing selection */ + /*********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_LowTiming >= 266) && (ul_LowTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_LowTiming >= 1) && (ul_LowTiming <= 571230650UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_LowTiming >= 1) && (ul_LowTiming <= 571230UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_LowTiming >= 1) && (ul_LowTiming <= 571UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_LowTiming >= 1) && (ul_LowTiming <= 9UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_LowTiming >= 242) && (ul_LowTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_LowTiming >= 1) && (ul_LowTiming <= 519691043UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_LowTiming >= 1) && (ul_LowTiming <= 519691UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_LowTiming >= 1) && (ul_LowTiming <= 520UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_LowTiming >= 1) && (ul_LowTiming <= 8UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_LowTiming >= 200) && (ul_LowTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_LowTiming >= 1) && (ul_LowTiming <= 429496729UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_LowTiming >= 1) && (ul_LowTiming <= 429496UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_LowTiming >= 1) && (ul_LowTiming <= 429UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_LowTiming >= 1) && (ul_LowTiming <= 7UL))) + { + /**********************************/ + /* Test the High timing selection */ + /**********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || + ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || + ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || + ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) + { + /************************************/ + /* Calculate the low division fator */ + /************************************/ + + switch (b_TimingUnit) + { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) (ul_LowTiming * (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (0.00025 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming = (ULONG) (ul_LowTimerValue / (0.00025 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / (0.00025 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (0.00025 * (double) b_ClockSelection)) >= (double) ((double) ul_RealLowTiming + 0.5)) + { + ul_RealLowTiming = ul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) (ul_LowTiming * (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (0.25 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming = (ULONG) (ul_LowTimerValue / (0.25 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / ((double) 0.25 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (0.25 * (double) b_ClockSelection)) >= (double) ((double) ul_RealLowTiming + 0.5)) + { + ul_RealLowTiming = ul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = ul_LowTiming * (250.0 * b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (250.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming = (ULONG) (ul_LowTimerValue / (250.0 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / (250.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (250.0 * (double) b_ClockSelection)) >= (double) ((double) ul_RealLowTiming + 0.5)) + { + ul_RealLowTiming = ul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) (ul_LowTiming * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_LowTiming * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming = (ULONG) (ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)); + d_RealLowTiming = (double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) >= (double) ((double) ul_RealLowTiming + 0.5)) + { + ul_RealLowTiming = ul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue = (ULONG) ((ul_LowTiming * 60) * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) (ul_LowTiming * 60.0) * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_LowTimerValue + 0.5))) + { + ul_LowTimerValue = ul_LowTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming = (ULONG) (ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) / 60; + d_RealLowTiming = ((double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0; + + if ((double) (((double) ul_LowTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0) >= (double) ((double) ul_RealLowTiming + 0.5)) + { + ul_RealLowTiming = ul_RealLowTiming + 1; + } + + ul_LowTiming = ul_LowTiming - 1; + ul_LowTimerValue = ul_LowTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_LowTimerValue = (ULONG) ((double) (ul_LowTimerValue) * 1.007752288); + } + + break; + } + + /*************************************/ + /* Calculate the high division fator */ + /*************************************/ + + switch (b_TimingUnit) + { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) (ul_HighTiming * (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (0.00025 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming = (ULONG) (ul_HighTimerValue / (0.00025 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / (0.00025 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (0.00025 * (double) b_ClockSelection)) >= (double) ((double) ul_RealHighTiming + 0.5)) + { + ul_RealHighTiming = ul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) (ul_HighTiming * (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (0.25 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming = (ULONG) (ul_HighTimerValue / (0.25 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / ((double) 0.25 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (0.25 * (double) b_ClockSelection)) >= (double) ((double) ul_RealHighTiming + 0.5)) + { + ul_RealHighTiming = ul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = ul_HighTiming * (250.0 * b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (250.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming = (ULONG) (ul_HighTimerValue / (250.0 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / (250.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (250.0 * (double) b_ClockSelection)) >= (double) ((double) ul_RealHighTiming + 0.5)) + { + ul_RealHighTiming = ul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) (ul_HighTiming * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) ul_HighTiming * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming = (ULONG) (ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)); + d_RealHighTiming = (double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection); + + if ((double) ((double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) >= (double) ((double) ul_RealHighTiming + 0.5)) + { + ul_RealHighTiming = ul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue = (ULONG) ((ul_HighTiming * 60) * (250000.0 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double) ((double) (ul_HighTiming * 60.0) * (250000.0 * (double) b_ClockSelection)) >= ((double) ((double) ul_HighTimerValue + 0.5))) + { + ul_HighTimerValue = ul_HighTimerValue + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming = (ULONG) (ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) / 60; + d_RealHighTiming = ((double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0; + + if ((double) (((double) ul_HighTimerValue / (250000.0 * (double) b_ClockSelection)) / 60.0) >= (double) ((double) ul_RealHighTiming + 0.5)) + { + ul_RealHighTiming = ul_RealHighTiming + 1; + } + + ul_HighTiming = ul_HighTiming - 1; + ul_HighTimerValue = ul_HighTimerValue - 2; + + if (b_ClockSelection != APCI1710_40MHZ) + { + ul_HighTimerValue = (ULONG) ((double) (ul_HighTimerValue) * 1.007752288); + } + + break; + } + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + b_TimingUnit = b_TimingUnit; + + /****************************/ + /* Save the low base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + d_LowTiming = d_RealLowTiming; + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + ul_RealLowTiming = ul_RealLowTiming; + + /****************************/ + /* Save the high base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + d_HighTiming = d_RealHighTiming; + + devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo [b_PWM]. + ul_RealHighTiming = ul_RealHighTiming; + + /************************/ + /* Write the low timing */ + /************************/ + + outl(ul_LowTimerValue,devpriv->s_BoardInfos. + ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************************/ + /* Write the high timing */ + /*************************/ + + outl(ul_HighTimerValue,devpriv->s_BoardInfos. + ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /***************************/ + /* Set the clock selection */ + /***************************/ + + dw_Command=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command = dw_Command & 0x7F; + + if (b_ClockSelection == APCI1710_40MHZ) + { + dw_Command = dw_Command | 0x80; + } + + /***************************/ + /* Set the clock selection */ + /***************************/ + + outl(dw_Command,devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + } + else + { + /***************************************/ + /* High base timing selection is wrong */ + /***************************************/ + DPRINTK("High base timing selection is wrong\n"); + i_ReturnValue = -8; + } + } + else + { + /**************************************/ + /* Low base timing selection is wrong */ + /**************************************/ + DPRINTK("Low base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else + { + /**********************************/ + /* Timing unit selection is wrong */ + /**********************************/ + DPRINTK("Timing unit selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if (dw_Status & 0x10) + else + { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else + { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } + else + { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetPWMStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| PBYTE_ pb_PWMOutputStatus, | +| PBYTE_ pb_ExternGateStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the status from selected PWM (b_PWM) from | +| selected module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_PWM : Selected PWM (0 or 1) | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_PWM =(BYTE) data[0]; + + | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_PWMOutputStatus : Return the PWM output | +| level status. | +| 0 : The PWM output level| +| is low. | +| 1 : The PWM output level| +| is high. | +| PBYTE_ pb_ExternGateStatus : Return the extern gate | +| level status. | +| 0 : The extern gate is | +| low. | +| 1 : The extern gate is | +| high. + pb_PWMOutputStatus =(PBYTE) data[0]; + pb_ExternGateStatus =(PBYTE) data[1]; | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM not enabled see function "i_APCI1710_EnablePWM"| ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadGetPWMStatus(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + + BYTE b_ModulNbr; + BYTE b_PWM; + PBYTE pb_PWMOutputStatus; + PBYTE pb_ExternGateStatus; + + i_ReturnValue = insn->n; + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_PWM =(BYTE) CR_CHAN(insn->chanspec); + pb_PWMOutputStatus =(PBYTE) &data[0]; + pb_ExternGateStatus =(PBYTE) &data[1]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_PWM) + { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM >= 0 && b_PWM <= 1) + { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) + { + /***********************/ + /* Test if PWM enabled */ + /***********************/ + + if (dw_Status & 0x1) + { + *pb_PWMOutputStatus = (BYTE) ((dw_Status >> 7) & 1); + *pb_ExternGateStatus = (BYTE) ((dw_Status >> 6) & 1); + } // if (dw_Status & 0x1) + else + { + /*******************/ + /* PWM not enabled */ + /*******************/ + DPRINTK("PWM not enabled \n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } // if (dw_Status & 0x10) + else + { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else + { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } + else + { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +{ + data[0]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].b_OldModuleMask; + data[1]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldInterruptMask; + data[2]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldCounterLatchValue; + + + /**************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv-> + s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters. + ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + return insn->n; + +} diff --git a/comedi/drivers/addi-data/APCI1710_Pwm.h b/comedi/drivers/addi-data/APCI1710_Pwm.h new file mode 100644 index 00000000..f6e265bc --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Pwm.h @@ -0,0 +1,78 @@ + + + + + + #define APCI1710_30MHZ 30 + #define APCI1710_33MHZ 33 + #define APCI1710_40MHZ 40 + + +#define APCI1710_PWM_INIT 0 +#define APCI1710_PWM_GETINITDATA 1 + +#define APCI1710_PWM_DISABLE 0 +#define APCI1710_PWM_ENABLE 1 +#define APCI1710_PWM_NEWTIMING 2 + + + + +INT i_APCI1710_InsnConfigPWM(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InitPWM (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_ClockSelection, + BYTE b_TimingUnit, + ULONG ul_LowTiming, + ULONG ul_HighTiming, + PULONG pul_RealLowTiming, + PULONG pul_RealHighTiming); + +INT i_APCI1710_GetPWMInitialisation (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + PBYTE pb_TimingUnit, + PULONG pul_LowTiming, + PULONG pul_HighTiming, + PBYTE pb_StartLevel, + PBYTE pb_StopMode, + PBYTE pb_StopLevel, + PBYTE pb_ExternGate, + PBYTE pb_InterruptEnable, + PBYTE pb_Enable); + + + + +INT i_APCI1710_InsnWritePWM(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_EnablePWM (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_StartLevel, + BYTE b_StopMode, + BYTE b_StopLevel, + BYTE b_ExternGate, + BYTE b_InterruptEnable); + +INT i_APCI1710_SetNewPWMTiming (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_TimingUnit, + ULONG ul_LowTiming, + ULONG ul_HighTiming); + +INT i_APCI1710_DisablePWM (comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM); + +INT i_APCI1710_InsnReadGetPWMStatus(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + +INT i_APCI1710_InsnBitsReadPWMInterrupt(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + diff --git a/comedi/drivers/addi-data/APCI1710_Ssi.c b/comedi/drivers/addi-data/APCI1710_Ssi.c new file mode 100644 index 00000000..99282f72 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Ssi.c @@ -0,0 +1,766 @@ +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : SSI.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 14.01.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 SSI counter module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 13/05/98 | S. Weber | SSI digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 22/03/00 | C.Guinot | 0100/0226 -> 0200/0227 | + | | | Änderung in InitSSI Funktion | + | | | b_SSIProfile >= 2 anstatt b_SSIProfile > 2 | + | | | | + +-----------------------------------------------------------------------+ + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + + +#include "APCI1710_Ssi.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitSSI | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SSIProfile, | +| BYTE_ b_PositionTurnLength, | +| BYTE_ b_TurnCptLength, | +| BYTE_ b_PCIInputClock, | +| ULONG_ ul_SSIOutputClock, | +| BYTE_ b_SSICountingMode) | ++----------------------------------------------------------------------------+ +| Task : Configure the SSI operating mode from selected module | +| (b_ModulNbr). You must calling this function be for you| +| call any other function witch access of SSI. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_SSIProfile : Selection from SSI | +| profile length (2 to 32).| +| BYTE_ b_PositionTurnLength : Selection from SSI | +| position data length | +| (1 to 31). | +| BYTE_ b_TurnCptLength : Selection from SSI turn | +| counter data length | +| (1 to 31). | +| BYTE b_PCIInputClock : Selection from PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC have a PCI bus | +| clock from 30 MHz | +| - APCI1710_33MHZ : | +| The PC have a PCI bus | +| clock from 33 MHz | +| ULONG_ ul_SSIOutputClock : Selection from SSI output| +| clock. | +| From 229 to 5 000 000 Hz| +| for 30 MHz selection. | +| From 252 to 5 000 000 Hz| +| for 33 MHz selection. | +| BYTE b_SSICountingMode : SSI counting mode | +| selection | +| - APCI1710_BINARY_MODE : | +| Binary counting mode. | +| - APCI1710_GRAY_MODE : | +| Gray counting mode. + + b_ModulNbr = CR_AREF(insn->chanspec); + b_SSIProfile = (BYTE) data[0]; + b_PositionTurnLength= (BYTE) data[1]; + b_TurnCptLength = (BYTE) data[2]; + b_PCIInputClock = (BYTE) data[3]; + ul_SSIOutputClock = (ULONG) data[4]; + b_SSICountingMode = (BYTE) data[5]; | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a SSI module | +| -4: The selected SSI profile length is wrong | +| -5: The selected SSI position data length is wrong | +| -6: The selected SSI turn counter data length is wrong | +| -7: The selected PCI input clock is wrong | +| -8: The selected SSI output clock is wrong | +| -9: The selected SSI counting mode parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnConfigInitSSI(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + UINT ui_TimerValue; + BYTE b_ModulNbr,b_SSIProfile,b_PositionTurnLength,b_TurnCptLength,b_PCIInputClock,b_SSICountingMode; + ULONG ul_SSIOutputClock; + + b_ModulNbr = CR_AREF(insn->chanspec); + b_SSIProfile = (BYTE) data[0]; + b_PositionTurnLength= (BYTE) data[1]; + b_TurnCptLength = (BYTE) data[2]; + b_PCIInputClock = (BYTE) data[3]; + ul_SSIOutputClock = (ULONG) data[4]; + b_SSICountingMode = (BYTE) data[5]; + + i_ReturnValue = insn->n; + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if SSI counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_SSI_COUNTER) + { + /*******************************/ + /* Test the SSI profile length */ + /*******************************/ + + // CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 + if (b_SSIProfile >= 2 && b_SSIProfile < 33) + { + /*************************************/ + /* Test the SSI position data length */ + /*************************************/ + + if (b_PositionTurnLength > 0 && b_PositionTurnLength < 32) + { + /*****************************************/ + /* Test the SSI turn counter data length */ + /*****************************************/ + + if (b_TurnCptLength > 0 && b_TurnCptLength < 32) + { + /***************************/ + /* Test the profile length */ + /***************************/ + + if ((b_TurnCptLength + b_PositionTurnLength) <= b_SSIProfile) + { + /****************************/ + /* Test the PCI input clock */ + /****************************/ + + if (b_PCIInputClock == APCI1710_30MHZ || b_PCIInputClock == APCI1710_33MHZ) + { + /*************************/ + /* Test the output clock */ + /*************************/ + + if ((b_PCIInputClock == APCI1710_30MHZ && + (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || + (b_PCIInputClock == APCI1710_33MHZ && + (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) + { + if (b_SSICountingMode == APCI1710_BINARY_MODE || + b_SSICountingMode == APCI1710_GRAY_MODE) + { + /**********************/ + /* Save configuration */ + /**********************/ + devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile = b_SSIProfile; + + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength = b_PositionTurnLength; + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_TurnCptLength = b_TurnCptLength; + + /*********************************/ + /* Initialise the profile length */ + /*********************************/ + + if (b_SSICountingMode == APCI1710_BINARY_MODE) + { + + outl(b_SSIProfile + 1,devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); + } + else + { + + outl(b_SSIProfile,devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); + } + + /******************************/ + /* Calculate the output clock */ + /******************************/ + + ui_TimerValue = (UINT) (((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock); + + /************************/ + /* Initialise the timer */ + /************************/ + + + outl(ui_TimerValue,devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + + + /********************************/ + /* Initialise the counting mode */ + /********************************/ + + outl(7 * b_SSICountingMode,devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); + + devpriv->s_ModuleInfo [b_ModulNbr].s_SSICounterInfo.b_SSIInit = 1; + } + else + { + /*****************************************************/ + /* The selected SSI counting mode parameter is wrong */ + /*****************************************************/ + DPRINTK("The selected SSI counting mode parameter is wrong\n"); + i_ReturnValue = -9; + } + } + else + { + /******************************************/ + /* The selected SSI output clock is wrong */ + /******************************************/ + DPRINTK("The selected SSI output clock is wrong\n"); + i_ReturnValue = -8; + } + } + else + { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = -7; + } + } + else + { + /********************************************/ + /* The selected SSI profile length is wrong */ + /********************************************/ + DPRINTK("The selected SSI profile length is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /******************************************************/ + /* The selected SSI turn counter data length is wrong */ + /******************************************************/ + DPRINTK("The selected SSI turn counter data length is wrong\n"); + i_ReturnValue = -6; + } + } + else + { + /**************************************************/ + /* The selected SSI position data length is wrong */ + /**************************************************/ + DPRINTK("The selected SSI position data length is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /********************************************/ + /* The selected SSI profile length is wrong */ + /********************************************/ + DPRINTK("The selected SSI profile length is wrong\n"); + i_ReturnValue = -4; + } + } + else + { + /**********************************/ + /* The module is not a SSI module */ + /**********************************/ + DPRINTK("The module is not a SSI module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Read1SSIValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedSSI, | +| PULONG_ pul_Position, | +| PULONG_ pul_TurnCpt) + INT i_APCI1710_ReadSSIValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : + + + Read the selected SSI counter (b_SelectedSSI) from | +| selected module (b_ModulNbr). + or Read all SSI counter (b_SelectedSSI) from | +| selected module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_SelectedSSI : Selection from SSI | +| counter (0 to 2) + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec); (in case of single ssi) + b_ReadType = (BYTE) CR_RANGE(insn->chanspec); +| ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_Position : SSI position in the turn | +| PULONG_ pul_TurnCpt : Number of turns + +pul_Position = (PULONG) &data[0]; + pul_TurnCpt = (PULONG) &data[1]; | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a SSI module | +| -4: SSI not initialised see function | +| "i_APCI1710_InitSSI" | +| -5: The selected SSI is wrong | ++----------------------------------------------------------------------------+ +*/ + + INT i_APCI1710_InsnReadSSIValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + BYTE b_Cpt; + BYTE b_Length; + BYTE b_Schift; + BYTE b_SSICpt; + DWORD dw_And; + DWORD dw_And1; + DWORD dw_And2; + DWORD dw_StatusReg; + DWORD dw_CounterValue; + BYTE b_ModulNbr; + BYTE b_SelectedSSI; + BYTE b_ReadType; + PULONG pul_Position; + PULONG pul_TurnCpt; + PULONG pul_Position1; + PULONG pul_TurnCpt1; + + + i_ReturnValue = insn->n; + pul_Position1 = (PULONG) &data[0]; // For Read1 + pul_TurnCpt1 = (PULONG) &data[1]; // For Read all + pul_Position = (PULONG) &data[0];//0-2 + pul_TurnCpt = (PULONG) &data[3];//3-5 + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec); + b_ReadType = (BYTE) CR_RANGE(insn->chanspec); + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if SSI counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_SSI_COUNTER) + { + /***************************/ + /* Test if SSI initialised */ + /***************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_SSIInit == 1) + { + + switch(b_ReadType) + { + + case APCI1710_SSI_READ1VALUE : + /****************************************/ + /* Test the selected SSI counter number */ + /****************************************/ + + if (b_SelectedSSI < 3) + { + /************************/ + /* Start the conversion */ + /************************/ + + outl(0,devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr)); + + + do + { + /*******************/ + /* Read the status */ + /*******************/ + + dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + } + while ((dw_StatusReg & 0x1) != 0); + + /******************************/ + /* Read the SSI counter value */ + /******************************/ + + dw_CounterValue = inl(devpriv->s_BoardInfos.ui_Address + 4 + (b_SelectedSSI * 4) + (64 * b_ModulNbr)); + + b_Length = devpriv->s_ModuleInfo [b_ModulNbr].s_SSICounterInfo.b_SSIProfile / 2; + + if ((b_Length * 2) != devpriv->s_ModuleInfo [b_ModulNbr].s_SSICounterInfo.b_SSIProfile) + { + b_Length ++; + } + + b_Schift = b_Length - devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; + + + *pul_Position1 = dw_CounterValue >> b_Schift; + + dw_And = 1; + + for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; b_Cpt ++) + { + dw_And = dw_And * 2; + } + + *pul_Position1 = *pul_Position1 & ((dw_And) - 1); + + *pul_TurnCpt1 = dw_CounterValue >> b_Length; + + dw_And = 1; + + for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_TurnCptLength; b_Cpt ++) + { + dw_And = dw_And * 2; + } + + *pul_TurnCpt1 = *pul_TurnCpt1 & ((dw_And) - 1); + } + else + { + /*****************************/ + /* The selected SSI is wrong */ + /*****************************/ + DPRINTK("The selected SSI is wrong\n"); + i_ReturnValue = -5; + } + break; + + case APCI1710_SSI_READALLVALUE : + dw_And1 = 1; + + for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; b_Cpt ++) + { + dw_And1 = dw_And1 * 2; + } + + dw_And2 = 1; + + for (b_Cpt = 0; b_Cpt < devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_TurnCptLength; b_Cpt ++) + { + dw_And2 = dw_And2 * 2; + } + + /************************/ + /* Start the conversion */ + /************************/ + + outl(0,devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr)); + + do + { + /*******************/ + /* Read the status */ + /*******************/ + + dw_StatusReg = inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + } + while ((dw_StatusReg & 0x1) != 0); + + for (b_SSICpt = 0; b_SSICpt < 3; b_SSICpt ++) + { + /******************************/ + /* Read the SSI counter value */ + /******************************/ + + + dw_CounterValue = inl(devpriv->s_BoardInfos.ui_Address + 4 + (b_SSICpt * 4) + (64 * b_ModulNbr)); + + b_Length = devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile / 2; + + if ((b_Length * 2) != devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile) + { + b_Length ++; + } + + b_Schift = b_Length - devpriv->s_ModuleInfo [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; + + + pul_Position [b_SSICpt] = dw_CounterValue >> b_Schift; + pul_Position [b_SSICpt] = pul_Position [b_SSICpt] & ((dw_And1) - 1); + + pul_TurnCpt [b_SSICpt] = dw_CounterValue >> b_Length; + pul_TurnCpt [b_SSICpt] = pul_TurnCpt [b_SSICpt] & ((dw_And2) - 1); + } + break; + + default : + printk("Read Type Inputs Wrong\n"); + + } // switch ending + + } + else + { + /***********************/ + /* SSI not initialised */ + /***********************/ + DPRINTK("SSI not initialised\n"); + i_ReturnValue = -4; + } + } + else + { + /**********************************/ + /* The module is not a SSI module */ + /**********************************/ + DPRINTK("The module is not a SSI module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_InputChannel, | +| PBYTE_ pb_ChannelStatus) | ++----------------------------------------------------------------------------+ +| Task : + (0) Set the digital output from selected SSI moule | +| (b_ModuleNbr) ON + (1) Set the digital output from selected SSI moule | +| (b_ModuleNbr) OFF + (2)Read the status from selected SSI digital input | +| (b_InputChannel) + (3)Read the status from all SSI digital inputs from | +| selected SSI module (b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr CR_AREF : Module number to | +| configure (0 to 3) | +| BYTE_ b_InputChannel CR_CHAN : Selection from digital | +| data[0] which IOTYPE input ( 0 to 2) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel | +| data[0] status | +| 0 : Channle is not active| +| 1 : Channle is active | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a SSI module | +| -4: The selected SSI digital input is wrong | ++----------------------------------------------------------------------------+ +*/ + + + +INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, +lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg; + BYTE b_ModulNbr; + BYTE b_InputChannel; + PBYTE pb_ChannelStatus; + PBYTE pb_InputStatus; + BYTE b_IOType; + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_IOType = (BYTE) data[0]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if SSI counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_SSI_COUNTER) + { + switch(b_IOType) + { + case APCI1710_SSI_SET_CHANNELON : + /*****************************/ + /* Set the digital output ON */ + /*****************************/ + + + outl(1,devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr)); + break ; + + case APCI1710_SSI_SET_CHANNELOFF : + /******************************/ + /* Set the digital output OFF */ + /******************************/ + + + outl(0,devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr)); + break ; + + + + case APCI1710_SSI_READ_1CHANNEL: + /******************************************/ + /* Test the digital imnput channel number */ + /******************************************/ + + b_InputChannel = (BYTE) CR_CHAN(insn->chanspec); + pb_ChannelStatus = (PBYTE) &data[0]; + + if ((b_InputChannel >= 0) && (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/comedi/drivers/addi-data/APCI1710_Ssi.h b/comedi/drivers/addi-data/APCI1710_Ssi.h new file mode 100644 index 00000000..918558dd --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Ssi.h @@ -0,0 +1,40 @@ + + + + +#define APCI1710_30MHZ 30 +#define APCI1710_33MHZ 33 +#define APCI1710_40MHZ 40 + + +#define APCI1710_BINARY_MODE 0x1 +#define APCI1710_GRAY_MODE 0x0 + +#define APCI1710_SSI_READ1VALUE 1 +#define APCI1710_SSI_READALLVALUE 2 + + +#define APCI1710_SSI_SET_CHANNELON 0 +#define APCI1710_SSI_SET_CHANNELOFF 1 +#define APCI1710_SSI_READ_1CHANNEL 2 +#define APCI1710_SSI_READ_ALLCHANNEL 3 + +/* ++----------------------------------------------------------------------------+ +| SSI INISIALISATION FUNCTION | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_InsnConfigInitSSI(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + +INT i_APCI1710_InsnReadSSIValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + + +INT i_APCI1710_InsnBitsSSIDigitalIO(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, +lsampl_t *data); + + + diff --git a/comedi/drivers/addi-data/APCI1710_Tor.c b/comedi/drivers/addi-data/APCI1710_Tor.c new file mode 100644 index 00000000..bc06967b --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Tor.c @@ -0,0 +1,1737 @@ +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : TOR.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 14.12.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 tor counter module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 27/01/99 | S. Weber | 40 MHz implementation | + +-----------------------------------------------------------------------+ + | 28/04/00 | S. Weber | Simple,double and quadruple mode implementation| + | | | Extern clock implementation | + +-----------------------------------------------------------------------+ + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + + +#include "APCI1710_Tor.h" + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitTorCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_TimingInterval, | +| PULONG_ pul_RealTimingInterval) | ++----------------------------------------------------------------------------+ +| Task : Configure the selected tor counter (b_TorCounter) | +| from selected module (b_ModulNbr). | +| The ul_TimingInterval and ul_TimingUnit determine the | +| timing base for the measurement. | +| The pul_RealTimingInterval return the real timing | +| value. You must calling this function be for you call | +| any other function witch access of the tor counter. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| + CR_AREF BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| data[0] BYTE_ b_TorCounter : Tor counter selection | +| (0 or 1). | +| data[1] BYTE_ b_PCIInputClock : Selection from PCI bus clock| +| - APCI1710_30MHZ : | +| The PC have a PCI bus | +| clock from 30 MHz | +| - APCI1710_33MHZ : | +| The PC have a PCI bus | +| clock from 33 MHz | +| - APCI1710_40MHZ | +| The APCI-1710 have a | +| integrated 40Mhz | +| quartz. | +| - APCI1710_GATE_INPUT | +| Used the gate input for | +| the base clock. If you | +| have selected this option,| +| than it is not possibl to | +| used the gate input for | +| enabled the acquisition | +| data[2] BYTE_ b_TimingUnit : Base timing unit (0 to 4) | +| 0 : ns | +| 1 : µs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| data[3] ULONG_ ul_TimingInterval : Base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing | +| data[0] value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a tor counter module | +| -4: Tor counter selection is wrong | +| -5: The selected PCI input clock is wrong | +| -6: Timing unit selection is wrong | +| -7: Base timing selection is wrong | +| -8: You can not used the 40MHz clock selection wich | +| this board | +| -9: You can not used the 40MHz clock selection wich | +| this TOR version | ++----------------------------------------------------------------------------+ +*/ + + + +INT i_APCI1710_InsnConfigInitTorCounter(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + ULONG ul_TimerValue; + DWORD dw_Command; + double d_RealTimingInterval; + BYTE b_ModulNbr; + BYTE b_TorCounter; + BYTE b_PCIInputClock; + BYTE b_TimingUnit; + ULONG ul_TimingInterval; + ULONG ul_RealTimingInterval; + + 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 >= 0 && 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 >= 0) && (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) + { + /****************************************/ + /* 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; + } + } // if (b_PCIInputClock != APCI1710_GATE_INPUT) + else + { + /*************************************************************/ + /* 2 Clock used for the overflow and the reload from counter */ + /*************************************************************/ + + ul_TimerValue = ul_TimingInterval - 2; + } // if (b_PCIInputClock != APCI1710_GATE_INPUT) + + /****************************/ + /* Save the PCI input clock */ + /****************************/ + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TorCounterModuleInfo. + b_PCIInputClock = b_PCIInputClock; + + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo [b_TorCounter]. + b_TimingUnit = b_TimingUnit; + + /************************/ + /* Save the base timing */ + /************************/ + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo [b_TorCounter]. + d_TimingInterval = d_RealTimingInterval; + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo [b_TorCounter]. + ul_RealTimingInterval = ul_RealTimingInterval; + + /*******************/ + /* Get the command */ + /*******************/ + + + dw_Command = inl(devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + dw_Command = (dw_Command >> 4) & 0xF; + + /******************/ + /* Test if 40 MHz */ + /******************/ + + if (b_PCIInputClock == APCI1710_40MHZ) + { + /****************************/ + /* Set the 40 MHz selection */ + /****************************/ + + dw_Command = dw_Command | 0x10; + } + + /*****************************/ + /* Test if extern clock used */ + /*****************************/ + + if (b_PCIInputClock == APCI1710_GATE_INPUT) + { + /****************************/ + /* Set the 40 MHz selection */ + /****************************/ + + dw_Command = dw_Command | 0x20; + } + + /*************************/ + /* Write the new command */ + /*************************/ + + + outl(dw_Command,devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + /*******************/ + /* Disable the tor */ + /*******************/ + + outl(0,devpriv->s_BoardInfos. + ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + /*************************/ + /* Set the timer 1 value */ + /*************************/ + + + outl(ul_TimerValue,devpriv->s_BoardInfos.ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + /*********************/ + /* Tor counter init. */ + /*********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo [b_TorCounter]. + b_TorCounterInit = 1; + } + else + { + /***********************************************/ + /* TOR version error for 40MHz clock selection */ + /***********************************************/ + DPRINTK("TOR version error for 40MHz clock selection\n"); + i_ReturnValue = -9; + } + } + else + { + /**************************************************************/ + /* You can not used the 40MHz clock selection wich this board */ + /**************************************************************/ + DPRINTK("You can not used the 40MHz clock selection wich this board\n"); + i_ReturnValue = -8; + } + } + else + { + /**********************************/ + /* Base timing selection is wrong */ + /**********************************/ + DPRINTK("Base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else + { + /**********************************/ + /* Timing unit selection is wrong */ + /**********************************/ + DPRINTK("Timing unit selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) + else + { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = -5; + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) + } // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) + else + { + /**********************************/ + /* Tor Counter selection is wrong */ + /**********************************/ + DPRINTK("Tor Counter selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) + } + else + { + /******************************************/ + /* The module is not a tor counter module */ + /******************************************/ + DPRINTK("The module is not a tor counter module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + data[0] = (UINT) ul_RealTimingInterval; + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableTorCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| BYTE_ b_InputMode, | +| BYTE_ b_ExternGate, | +| BYTE_ b_CycleMode, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Enable the tor counter (b_TorCounter) from selected | +| module (b_ModulNbr). You must calling the | +| "i_APCI1710_InitTorCounter" function be for you call | +| this function. | +| If you enable the tor counter interrupt, the | +| tor counter generate a interrupt after the timing cycle| +| See function "i_APCI1710_SetBoardIntRoutineX" and the | +| Interrupt mask description chapter from this manual. | +| The b_CycleMode parameter determine if you will | +| measured a single or more cycle. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1). | +| BYTE_ b_InputMode : Input signal level selection | +| 0 : Tor count each low level | +| 1 : Tor count each high level| +| BYTE_ b_ExternGate : Extern gate action selection | +| 0 : Extern gate signal not | +| used | +| 1 : Extern gate signal used. | +| If you selected the | +| single mode, each high | +| level signal start the | +| counter. | +| If you selected the | +| continuous mode, the | +| first high level signal | +| start the tor counter | +| | +| APCI1710_TOR_QUADRUPLE _MODE : | +| In the quadruple mode, the edge| +| analysis circuit generates a | +| counting pulse from each edge | +| of 2 signals which are phase | +| shifted in relation to each | +| other. | +| The gate input is used for the | +| signal B | +| | +| APCI1710_TOR_DOUBLE_MODE: | +| Functions in the same way as | +| the quadruple mode, except that| +| only two of the four edges are | +| analysed per period. | +| The gate input is used for the | +| signal B | +| | +| APCI1710_TOR_SIMPLE_MODE: | +| Functions in the same way as | +| the quadruple mode, except that| +| only one of the four edges is | +| analysed per period. | +| The gate input is used for the | +| signal B | +| | +| BYTE_ b_CycleMode : Selected the tor counter | +| acquisition mode | +| BYTE_ b_InterruptEnable : Enable or disable the | +| tor counter interrupt. | +| APCI1710_ENABLE: | +| Enable the tor counter | +| interrupt | +| APCI1710_DISABLE: | +| Disable the tor counter | +| interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | +| -6: Tor input signal selection is wrong | +| -7: Extern gate signal mode is wrong | +| -8: Tor counter acquisition mode cycle is wrong | +| -9: Interrupt parameter is wrong | +| -10:Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableTorCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter) | ++----------------------------------------------------------------------------+ +| Task : Disable the tor counter (b_TorCounter) from selected | +| module (b_ModulNbr). If you disable the tor counter | +| after a start cycle occur and you restart the tor | +| counter witch the " i_APCI1710_EnableTorCounter" | +| function, the status register is cleared | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1). | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | +| -6: Tor counter not enabled see function | +| "i_APCI1710_EnableTorCounter" | ++----------------------------------------------------------------------------+ +*/ + + + +INT i_APCI1710_InsnWriteEnableDisableTorCounter (comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_DummyRead; + DWORD dw_ConfigReg; + BYTE b_ModulNbr,b_Action; + BYTE b_TorCounter; + BYTE b_InputMode; + BYTE b_ExternGate; + BYTE b_CycleMode; + BYTE b_InterruptEnable; + + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_Action =(BYTE) data[0]; // enable or disable + b_TorCounter =(BYTE) data[1]; + b_InputMode =(BYTE) data[2] ; + b_ExternGate =(BYTE) data[3] ; + b_CycleMode =(BYTE) data[4] ; + b_InterruptEnable =(BYTE) data[5] ; + i_ReturnValue = insn->n; ; + devpriv->tsk_Current=current; // Save the current process task structure + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER) + { + /**********************************/ + /* Test the tor counter selection */ + /**********************************/ + + if (b_TorCounter >= 0 && 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 >= 0 && b_TorCounter <= 1) + else + { + /**********************************/ + /* Tor counter selection is wrong */ + /**********************************/ + DPRINTK("Tor counter selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_TorCounter >= 0 && b_TorCounter <= 1) + } + else + { + /******************************************/ + /* The module is not a tor counter module */ + /******************************************/ + DPRINTK("The module is not a tor counter module \n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error \n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetTorCounterInitialisation | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| PBYTE_ pb_TimingUnit, | +| PULONG_ pul_TimingInterval, | +| PBYTE_ pb_InputMode, | +| PBYTE_ pb_ExternGate, | +| PBYTE_ pb_CycleMode, | +| PBYTE_ pb_Enable, | +| PBYTE_ pb_InterruptEnable)| ++----------------------------------------------------------------------------+ +| Task : Enable the tor counter (b_TorCounter) from selected | +| module (b_ModulNbr). You must calling the | +| "i_APCI1710_InitTorCounter" function be for you call | +| this function. | +| If you enable the tor counter interrupt, the | +| tor counter generate a interrupt after the timing cycle| +| See function "i_APCI1710_SetBoardIntRoutineX" and the | +| Interrupt mask description chapter from this manual. | +| The b_CycleMode parameter determine if you will | +| measured a single or more cycle. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1) + + b_ModulNbr = CR_AREF(insn->chanspec); + b_TorCounter = CR_CHAN(insn->chanspec); +. | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TimingUnit : Base timing unit (0 to 4) | +| 0 : ns | +| 1 : µs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| PULONG_ pul_TimingInterval : Base timing value. | +| PBYTE_ pb_InputMode : Input signal level | +| selection | +| 0 : Tor count each low level | +| 1 : Tor count each high level| +| PBYTE_ pb_ExternGate : Extern gate action | +| selection | +| 0 : Extern gate signal not | +| used | +| 1 : Extern gate signal used| +| PBYTE_ pb_CycleMode : Tor counter acquisition | +| mode | +| PBYTE_ pb_Enable : Indicate if the tor counter| +| is enabled or no | +| 0 : Tor counter disabled | +| 1 : Tor counter enabled | +| PBYTE_ pb_InterruptEnable : Enable or disable the | +| tor counter interrupt. | +| APCI1710_ENABLE: | +| Enable the tor counter | +| interrupt | +| APCI1710_DISABLE: | +| Disable the tor counter | +| interrupt + pb_TimingUnit = (PBYTE) &data[0]; + pul_TimingInterval = (PULONG) &data[1]; + pb_InputMode = (PBYTE) &data[2]; + pb_ExternGate = (PBYTE) &data[3]; + pb_CycleMode = (PBYTE) &data[4]; + pb_Enable = (PBYTE) &data[5]; + pb_InterruptEnable = (PBYTE) &data[6]; + | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + BYTE b_ModulNbr; + BYTE b_TorCounter; + PBYTE pb_TimingUnit; + PULONG pul_TimingInterval; + PBYTE pb_InputMode; + PBYTE pb_ExternGate; + PBYTE pb_CycleMode; + PBYTE pb_Enable; + PBYTE pb_InterruptEnable ; + + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_TorCounter = CR_CHAN(insn->chanspec); + + pb_TimingUnit = (PBYTE) &data[0]; + pul_TimingInterval = (PULONG) &data[1]; + pb_InputMode = (PBYTE) &data[2]; + pb_ExternGate = (PBYTE) &data[3]; + pb_CycleMode = (PBYTE) &data[4]; + pb_Enable = (PBYTE) &data[5]; + pb_InterruptEnable = (PBYTE) &data[6]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER) + { + /**********************************/ + /* Test the tor counter selection */ + /**********************************/ + + if (b_TorCounter >= 0 && 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 >= 0 && b_TorCounter <= 1) + else + { + /**********************************/ + /* Tor counter selection is wrong */ + /**********************************/ + DPRINTK("Tor counter selection is wrong \n"); + i_ReturnValue = -4; + } // if (b_TorCounter >= 0 && b_TorCounter <= 1) + } + else + { + /******************************************/ + /* The module is not a tor counter module */ + /******************************************/ + DPRINTK("The module is not a tor counter module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadTorCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| UINT_ ui_TimeOut, | +| PBYTE_ pb_TorCounterStatus, | +| PULONG_ pul_TorCounterValue) | ++----------------------------------------------------------------------------+ +| Task case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter +(b_TorCounter) status (pb_TorCounterStatus) from selected tor counter | +| module (b_ModulNbr). + + case APCI1710_TOR_GETCOUNTERVALUE : + Return the tor counter (b_TorCounter) status | +| (pb_TorCounterStatus) and the timing value | +| (pul_TorCounterValue) after a conting cycle stop | +| from selected tor counter module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1). + b_ModulNbr = CR_AREF(insn->chanspec); + b_ReadType = (BYTE) data[0]; + b_TorCounter = (BYTE) data[1]; + ui_TimeOut = (UINT) data[2]; | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TorCounterStatus : Return the tor counter | +| status. | +| 0 : Conting cycle not started| +| Software gate not set. | +| 1 : Conting cycle started. | +| Software gate set. | +| 2 : Conting cycle stopped. | +| The conting cycle is | +| terminate. | +| 3 : A overflow occur. You | +| must change the base | +| timing witch the | +| function | +| "i_APCI1710_InitTorCounter"| +| 4 : Timeeout occur | +| PULONG pul_TorCounterValue : Tor counter value. + pb_TorCounterStatus=(PBYTE) &data[0]; + pul_TorCounterValue=(PULONG) &data[1]; | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | +| -6: Tor counter not enabled see function | +| "i_APCI1710_EnableTorCounter" | +| -7: Timeout parameter is wrong (0 to 65535) | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_TimeOut = 0; + + BYTE b_ModulNbr; + BYTE b_TorCounter; + BYTE b_ReadType; + UINT ui_TimeOut; + PBYTE pb_TorCounterStatus; + PULONG pul_TorCounterValue; + + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_ReadType = (BYTE) data[0]; + b_TorCounter = (BYTE) data[1]; + ui_TimeOut = (UINT) data[2]; + pb_TorCounterStatus=(PBYTE) &data[0]; + pul_TorCounterValue=(PULONG) &data[1]; + + /**************************/ + /* Test the module number */ + /**************************/ + + + if(b_ReadType==APCI1710_TOR_READINTERRUPT) + { + + data[0]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].b_OldModuleMask; + data[1]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldInterruptMask; + data[2]=devpriv->s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Read].ul_OldCounterLatchValue; + + + /**************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv-> + s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters. + ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + return insn->n; + } + + if (b_ModulNbr < 4) + { + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER) + { + /**********************************/ + /* Test the tor counter selection */ + /**********************************/ + + if (b_TorCounter >= 0 && 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 >= 0 && b_TorCounter <= 1) + else + { + /**********************************/ + /* Tor counter selection is wrong */ + /**********************************/ + DPRINTK("Tor counter selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_TorCounter >= 0 && 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/comedi/drivers/addi-data/APCI1710_Tor.h b/comedi/drivers/addi-data/APCI1710_Tor.h new file mode 100644 index 00000000..b29d22c1 --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Tor.h @@ -0,0 +1,56 @@ + + + + #define APCI1710_30MHZ 30 + #define APCI1710_33MHZ 33 + #define APCI1710_40MHZ 40 + + + + #define APCI1710_GATE_INPUT 10 + + +#define APCI1710_TOR_SIMPLE_MODE 2 +#define APCI1710_TOR_DOUBLE_MODE 3 +#define APCI1710_TOR_QUADRUPLE_MODE 4 + + +#define APCI1710_SINGLE 0 +#define APCI1710_CONTINUOUS 1 + + +#define APCI1710_TOR_GETPROGRESSSTATUS 0 +#define APCI1710_TOR_GETCOUNTERVALUE 1 +#define APCI1710_TOR_READINTERRUPT 2 + + +/* ++----------------------------------------------------------------------------+ +| TOR_COUNTER INISIALISATION FUNCTION | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitTorCounter(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + + + + + +INT i_APCI1710_InsnWriteEnableDisableTorCounter (comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + + +INT i_APCI1710_InsnReadGetTorCounterInitialisation(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); +/* ++----------------------------------------------------------------------------+ +| TOR_COUNTER READ FUNCTION | ++----------------------------------------------------------------------------+ +*/ + + + +INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); diff --git a/comedi/drivers/addi-data/APCI1710_Ttl.c b/comedi/drivers/addi-data/APCI1710_Ttl.c new file mode 100644 index 00000000..1307e61a --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Ttl.c @@ -0,0 +1,961 @@ + + + +/* + +-----------------------------------------------------------------------+ + | (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 : BORLANDC/MICROSOFT C | + | Module name : TTL.C | Version : 3.1 / 6.0 | + +-------------------------------+---------------------------------------+ + | Author : S.WEBER | Date : 04.06.98 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 TTL I/O module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 13/05/98 | S. Weber | TTL digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | | | | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Ttl.h" + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitTTLIODirection | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PortAMode, | +| BYTE_ b_PortBMode, | +| BYTE_ b_PortCMode, | +| BYTE_ b_PortDMode) | ++----------------------------------------------------------------------------+ +| Task APCI1710_TTL_INIT (using defaults) : Configure the TTL I/O operating mode from selected | +| module (b_ModulNbr). You must calling this function be| +| for you call any other function witch access of TTL. | + APCI1710_TTL_INITDIRECTION(user inputs for direction) + ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_InitType = (BYTE) data[0]; + b_PortAMode = (BYTE) data[1]; + b_PortBMode = (BYTE) data[2]; + b_PortCMode = (BYTE) data[3]; + b_PortDMode = (BYTE) data[4];| ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a TTL module | +| -4: Function not available for this version | +| -5: Port A mode selection is wrong | +| -6: Port B mode selection is wrong | +| -7: Port C mode selection is wrong | +| -8: Port D mode selection is wrong | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnConfigInitTTLIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + BYTE b_ModulNbr; + BYTE b_InitType; + BYTE b_PortAMode; + BYTE b_PortBMode; + BYTE b_PortCMode; + BYTE b_PortDMode; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_InitType = (BYTE) data[0]; + i_ReturnValue = insn->n; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TTL_IO) + { + switch(b_InitType) + { + case APCI1710_TTL_INIT : + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo.b_TTLInit = 1; + + /***************************/ + /* Set TTL port A to input */ + /***************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [0] = 0; + + /***************************/ + /* Set TTL port B to input */ + /***************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [1] = 0; + + /***************************/ + /* Set TTL port C to input */ + /***************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [2] = 0; + + /****************************/ + /* Set TTL port D to output */ + /****************************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [3] = 1; + + /*************************/ + /* Set the configuration */ + /*************************/ + + outl(0x8,devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr)); + break; + + + case APCI1710_TTL_INITDIRECTION : + + b_PortAMode = (BYTE) data[1]; + b_PortBMode = (BYTE) data[2]; + b_PortCMode = (BYTE) data[3]; + b_PortDMode = (BYTE) data[4]; + + /********************/ + /* Test the version */ + /********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230) + { + /************************/ + /* Test the port A mode */ + /************************/ + + if ((b_PortAMode == 0) || (b_PortAMode == 1)) + { + /************************/ + /* Test the port B mode */ + /************************/ + + if ((b_PortBMode == 0) || (b_PortBMode == 1)) + { + /************************/ + /* Test the port C mode */ + /************************/ + + if ((b_PortCMode == 0) || (b_PortCMode == 1)) + { + /************************/ + /* Test the port D mode */ + /************************/ + + if ((b_PortDMode == 0) || (b_PortDMode == 1)) + { + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_TTLInit = 1; + + /***********************/ + /* Set TTL port A mode */ + /***********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [0] = b_PortAMode; + + /***********************/ + /* Set TTL port B mode */ + /***********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [1] = b_PortBMode; + + /***********************/ + /* Set TTL port C mode */ + /***********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [2] = b_PortCMode; + + /***********************/ + /* Set TTL port D mode */ + /***********************/ + + devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [3] = b_PortDMode; + + /*************************/ + /* Set the configuration */ + /*************************/ + + + outl((b_PortAMode << 0) | + (b_PortBMode << 1) | + (b_PortCMode << 2) | + (b_PortDMode << 3),devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } + else + { + /**********************************/ + /* Port D mode selection is wrong */ + /**********************************/ + DPRINTK("Port D mode selection is wrong\n"); + i_ReturnValue = -8; + } + } + else + { + /**********************************/ + /* Port C mode selection is wrong */ + /**********************************/ + DPRINTK("Port C mode selection is wrong\n"); + i_ReturnValue = -7; + } + } + else + { + /**********************************/ + /* Port B mode selection is wrong */ + /**********************************/ + DPRINTK("Port B mode selection is wrong\n"); + i_ReturnValue = -6; + } + } + else + { + /**********************************/ + /* Port A mode selection is wrong */ + /**********************************/ + DPRINTK("Port A mode selection is wrong\n"); + i_ReturnValue = -5; + } + } + else + { + /*******************************************/ + /* Function not available for this version */ + /*******************************************/ + DPRINTK("Function not available for this version\n"); + i_ReturnValue = -4; + } + break; + DPRINTK("\n"); + default: + printk("Bad Config Type\n"); + }// switch end + } + else + { + /**********************************/ + /* The module is not a TTL module */ + /**********************************/ + DPRINTK("The module is not a TTL module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + +/* ++----------------------------------------------------------------------------+ +| INPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadTTLIOChannelValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedPort, | +| BYTE_ b_InputChannel, | +| PBYTE_ pb_ChannelStatus) | ++----------------------------------------------------------------------------+ +| Task : Read the status from selected TTL digital input | +| (b_InputChannel) ++----------------------------------------------------------------------------+ +| Task : Read the status from digital input port | +| (b_SelectedPort) from selected TTL module (b_ModulNbr) | ++----------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 7) | +| BYTE_ b_SelectedPort, : Selection from TTL I/O | +| port (0 to 2) | +| 0 : Port A selection | +| 1 : Port B selection | +| 2 : Port C selection | +| 3 : Port D selection | +| BYTE_ b_InputChannel : Selection from digital | +| input ( 0 to 2) +APCI1710_TTL_READCHANNEL + b_ModulNbr = CR_AREF(insn->chanspec); + b_SelectedPort= CR_RANGE(insn->chanspec); + b_InputChannel= CR_CHAN(insn->chanspec); + b_ReadType = (BYTE) data[0]; + + APCI1710_TTL_READPORT| + b_ModulNbr = CR_AREF(insn->chanspec); + b_SelectedPort= CR_RANGE(insn->chanspec); + b_ReadType = (BYTE) data[0]; + ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] + + PBYTE_ pb_ChannelStatus : Digital input channel | +| status | +| 0 : Channle is not active| +| 1 : Channle is active | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a TTL module | +| -4: The selected TTL input port is wrong | +| -5: The selected TTL digital input is wrong | +| -6: TTL I/O not initialised | ++----------------------------------------------------------------------------+ +*/ + + +INT i_APCI1710_InsnBitsReadTTLIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg; + BYTE b_ModulNbr; + BYTE b_SelectedPort; + BYTE b_InputChannel; + BYTE b_ReadType; + PBYTE pb_ChannelStatus; + PBYTE pb_PortValue; + + + i_ReturnValue = insn->n; + b_ReadType = (BYTE) data[0]; + b_ModulNbr = CR_AREF(insn->chanspec); + b_SelectedPort= CR_RANGE(insn->chanspec); + b_InputChannel= CR_CHAN(insn->chanspec); + + + + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TTL_IO) + { + switch(b_ReadType) + { + + case APCI1710_TTL_READCHANNEL: + pb_ChannelStatus = (PBYTE) &data[0]; + /********************************/ + /* Test the TTL I/O port number */ + /********************************/ + + if ((((b_SelectedPort >= 0) && (b_SelectedPort <= 2)) && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130)) || + (((b_SelectedPort >= 0) && (b_SelectedPort <= 3)) && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230))) + { + /******************************************/ + /* Test the digital imnput channel number */ + /******************************************/ + + if ((((b_InputChannel >= 0) && (b_InputChannel <= 7)) && (b_SelectedPort < 3)) || + (((b_InputChannel >= 0) && (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 >= 0) && (b_SelectedPort <= 2)) && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130)) || + (((b_SelectedPort >= 0) && (b_SelectedPort <= 3)) && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230))) + { + /******************************************/ + /* Test if the TTL I/O module initialised */ + /******************************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_TTLInit == 1) + { + /***********************************/ + /* Test if TTL port used for input */ + /***********************************/ + + if (((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130) || + (((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230) && + (devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [b_SelectedPort] == 0))) + { + /**************************/ + /* Read all digital input */ + /**************************/ + + dw_StatusReg=inl(devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + + *pb_PortValue = (BYTE) ((dw_StatusReg >> (8 * b_SelectedPort)) & 0xFF); + } + else + { + /*******************************/ + /* Selected TTL I/O port error */ + /*******************************/ + DPRINTK("Selected TTL I/O port error\n"); + i_ReturnValue = -4; + } + } + else + { + /***************************/ + /* TTL I/O not initialised */ + /***************************/ + DPRINTK("TTL I/O not initialised\n"); + i_ReturnValue = -5; + } + } + else + { + /*******************************/ + /* Selected TTL I/O port error */ + /*******************************/ + DPRINTK("Selected TTL I/O port error\n"); + i_ReturnValue = -4; + } + break; + + default: + printk("Bad ReadType\n"); + + }//End Switch + } + else + { + /**********************************/ + /* The module is not a TTL module */ + /**********************************/ + DPRINTK("The module is not a TTL module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device +*dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read the status from all digital input ports | +| (port A, port B and port C) from selected TTL | +| module (b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_PortValue : Digital TTL inputs port | +| status | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a TTL module | +| -4: TTL I/O not initialised | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device *dev,comedi_subdevice *s, +comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg; + BYTE b_ModulNbr; + PULONG pul_PortValue; + + b_ModulNbr=(BYTE) CR_AREF(insn->chanspec); + i_ReturnValue=insn->n; + pul_PortValue=(PULONG) &data[0]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TTL_IO) + { + /******************************************/ + /* Test if the TTL I/O module initialised */ + /******************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_TTLInit == 1) + { + /**************************/ + /* Read all digital input */ + /**************************/ + + + dw_StatusReg=inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + /**********************/ + /* Test if TTL Rev1.0 */ + /**********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130) + { + *pul_PortValue = dw_StatusReg & 0xFFFFFFUL; + } + else + { + /**************************************/ + /* Test if port A not used for output */ + /**************************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo.b_PortConfiguration [0] == 1) + { + *pul_PortValue = dw_StatusReg & 0x3FFFF00UL; + } + + /**************************************/ + /* Test if port B not used for output */ + /**************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [1] == 1) + { + *pul_PortValue = dw_StatusReg & 0x3FF00FFUL; + } + + /**************************************/ + /* Test if port C not used for output */ + /**************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [2] == 1) + { + *pul_PortValue = dw_StatusReg & 0x300FFFFUL; + } + + /**************************************/ + /* Test if port D not used for output */ + /**************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration [3] == 1) + { + *pul_PortValue = dw_StatusReg & 0xFFFFFFUL; + } + } + } + else + { + /***************************/ + /* TTL I/O not initialised */ + /***************************/ + DPRINTK("TTL I/O not initialised\n"); + i_ReturnValue = -5; + } + } + else + { + /**********************************/ + /* The module is not a TTL module */ + /**********************************/ + DPRINTK("The module is not a TTL module\n"); + i_ReturnValue = -3; + } + } + else + { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); + } + +/* ++----------------------------------------------------------------------------+ +| OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetTTLIOChlOn | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_OutputChannel) +INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Sets or resets the output witch has been passed with the | +| parameter b_Channel. Setting an output means setting | +| an ouput high. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel : Selection from digital output | +| channel (0 or 1) | +| 0 : PD0 | +| 1 : PD1 | +| 2 to 9 : PA | +| 10 to 17: PB | +| 18 to 25: PC | + + b_ModulNbr = CR_AREF(insn->chanspec); + b_OutputChannel= CR_CHAN(insn->chanspec); + ui_State = data[0]; // ON or OFF ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a TTL I/O module | +| -4: The selected digital output is wrong | +| -5: TTL I/O not initialised see function | +| " i_APCI1710_InitTTLIO" ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) + { + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + BYTE b_ModulNbr; + BYTE b_OutputChannel; + UINT ui_State; + + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_OutputChannel= CR_CHAN(insn->chanspec); + ui_State = data[0]; // ON or OFF + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) + { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF0000UL) == APCI1710_TTL_IO) + { + /******************************************/ + /* Test if the TTL I/O module initialised */ + /******************************************/ + + if (devpriv->s_ModuleInfo [b_ModulNbr]. + s_TTLIOInfo. + b_TTLInit == 1) + { + /***********************************/ + /* Test the TTL I/O channel number */ + /***********************************/ + + if ((((b_OutputChannel >= 0) && (b_OutputChannel <= 1)) && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) == 0x3130)) || + (((b_OutputChannel >= 0) && (b_OutputChannel <= 25)) && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3230))) + { + /****************************************************/ + /* Test if the selected channel is a output channel */ + /****************************************************/ + + if (((b_OutputChannel >= 0) && (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/comedi/drivers/addi-data/APCI1710_Ttl.h b/comedi/drivers/addi-data/APCI1710_Ttl.h new file mode 100644 index 00000000..f7ecfc0f --- /dev/null +++ b/comedi/drivers/addi-data/APCI1710_Ttl.h @@ -0,0 +1,39 @@ + + + + +#define APCI1710_TTL_INIT 0 +#define APCI1710_TTL_INITDIRECTION 1 + + +#define APCI1710_TTL_READCHANNEL 0 +#define APCI1710_TTL_READPORT 1 + + +/* ++----------------------------------------------------------------------------+ +| TTL INISIALISATION FUNCTION | ++----------------------------------------------------------------------------+ +*/ + + + INT i_APCI1710_InsnConfigInitTTLIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); +/* ++----------------------------------------------------------------------------+ +| TTL INPUT FUNCTION | ++----------------------------------------------------------------------------+ +*/ + + INT i_APCI1710_InsnBitsReadTTLIO(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + INT i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); +/* ++----------------------------------------------------------------------------+ +| TTL OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + + INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); diff --git a/comedi/drivers/addi-data/Makefile.am b/comedi/drivers/addi-data/Makefile.am new file mode 100644 index 00000000..799e43ea --- /dev/null +++ b/comedi/drivers/addi-data/Makefile.am @@ -0,0 +1,8 @@ + +AM_CFLAGS = $(COMEDI_CFLAGS) $(LINUX_CFLAGS) +LINK = $(top_builddir)/modtool --link -o $@ + +module_PROGRAMS = addi_common.ko + +addi_common_ko_SOURCES = addi_common.c + diff --git a/comedi/drivers/addi-data/addi_amcc_s5933.h b/comedi/drivers/addi-data/addi_amcc_s5933.h new file mode 100644 index 00000000..76b6af22 --- /dev/null +++ b/comedi/drivers/addi-data/addi_amcc_s5933.h @@ -0,0 +1,447 @@ + +//addi_amcc_s5933.h + +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : addi_amcc_s5933.h | Version : 2.96 Redhat Linux | + | | kernel-2.4.2 | + +-------------------------------+---------------------------------------+ + | Author : | Date : | + +-----------------------------------------------------------------------+ + | Description :|Header file for AMCC s 5933 | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + + +#ifndef _AMCC_S5933_H_ +#define _AMCC_S5933_H_ + +#include +#include + +#ifdef PCI_SUPPORT_VER1 +#error No support for 2.1.55 and older +#endif + +#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 // written on base0 + +#define AMWEN_ENABLE 0x02 // added for step 6 dma written on base2 +#define A2P_FIFO_WRITE_ENABLE 0x01 + +#define AGCSTS_TC_ENABLE 0x10000000 // for transfer count enable bit + +// ADDON RELATED ADDITIONS +// Constant + #define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00 + #define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200 + #define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L + #define APCI3120_AMWEN_ENABLE 0x02 + #define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01 + #define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L + #define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L + #define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L + #define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0 + #define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0 + #define APCI3120_DISABLE_BUS_MASTER_PCI 0x0 + + // ADD_ON ::: this needed since apci supports 16 bit interface to add on + #define APCI3120_ADD_ON_AGCSTS_LOW 0x3C + #define APCI3120_ADD_ON_AGCSTS_HIGH APCI3120_ADD_ON_AGCSTS_LOW + 2 + #define APCI3120_ADD_ON_MWAR_LOW 0x24 + #define APCI3120_ADD_ON_MWAR_HIGH APCI3120_ADD_ON_MWAR_LOW + 2 + #define APCI3120_ADD_ON_MWTC_LOW 0x058 + #define APCI3120_ADD_ON_MWTC_HIGH APCI3120_ADD_ON_MWTC_LOW + 2 + +// AMCC + #define APCI3120_AMCC_OP_MCSR 0x3C + #define APCI3120_AMCC_OP_REG_INTCSR 0x38 + +/****************************************************************************/ +/* AMCC Operation Register Offsets - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_OMB1 0x00 +#define AMCC_OP_REG_OMB2 0x04 +#define AMCC_OP_REG_OMB3 0x08 +#define AMCC_OP_REG_OMB4 0x0c +#define AMCC_OP_REG_IMB1 0x10 +#define AMCC_OP_REG_IMB2 0x14 +#define AMCC_OP_REG_IMB3 0x18 +#define AMCC_OP_REG_IMB4 0x1c +#define AMCC_OP_REG_FIFO 0x20 +#define AMCC_OP_REG_MWAR 0x24 +#define AMCC_OP_REG_MWTC 0x28 +#define AMCC_OP_REG_MRAR 0x2c +#define AMCC_OP_REG_MRTC 0x30 +#define AMCC_OP_REG_MBEF 0x34 +#define AMCC_OP_REG_INTCSR 0x38 +#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* INT source */ +#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */ +#define AMCC_OP_REG_MCSR 0x3c +#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */ +#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */ + +#define AMCC_FIFO_DEPTH_DWORD 8 +#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32)) + +/****************************************************************************/ +/* AMCC Operation Registers Size - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_SIZE 64 /* in bytes */ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - Add-on */ +/****************************************************************************/ + +#define AMCC_OP_REG_AIMB1 0x00 +#define AMCC_OP_REG_AIMB2 0x04 +#define AMCC_OP_REG_AIMB3 0x08 +#define AMCC_OP_REG_AIMB4 0x0c +#define AMCC_OP_REG_AOMB1 0x10 +#define AMCC_OP_REG_AOMB2 0x14 +#define AMCC_OP_REG_AOMB3 0x18 +#define AMCC_OP_REG_AOMB4 0x1c +#define AMCC_OP_REG_AFIFO 0x20 +#define AMCC_OP_REG_AMWAR 0x24 +#define AMCC_OP_REG_APTA 0x28 +#define AMCC_OP_REG_APTD 0x2c +#define AMCC_OP_REG_AMRAR 0x30 +#define AMCC_OP_REG_AMBEF 0x34 +#define AMCC_OP_REG_AINT 0x38 +#define AMCC_OP_REG_AGCSTS 0x3c +#define AMCC_OP_REG_AMWTC 0x58 +#define AMCC_OP_REG_AMRTC 0x5c + +/****************************************************************************/ +/* AMCC - Add-on General Control/Status Register */ +/****************************************************************************/ + +#define AGCSTS_CONTROL_MASK 0xfffff000 +#define AGCSTS_NV_ACC_MASK 0xe0000000 +#define AGCSTS_RESET_MASK 0x0e000000 +#define AGCSTS_NV_DA_MASK 0x00ff0000 +#define AGCSTS_BIST_MASK 0x0000f000 +#define AGCSTS_STATUS_MASK 0x000000ff +#define AGCSTS_TCZERO_MASK 0x000000c0 +#define AGCSTS_FIFO_ST_MASK 0x0000003f + +#define AGCSTS_RESET_MBFLAGS 0x08000000 +#define AGCSTS_RESET_P2A_FIFO 0x04000000 +#define AGCSTS_RESET_A2P_FIFO 0x02000000 +#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO) + +#define AGCSTS_A2P_TCOUNT 0x00000080 +#define AGCSTS_P2A_TCOUNT 0x00000040 + +#define AGCSTS_FS_P2A_EMPTY 0x00000020 +#define AGCSTS_FS_P2A_HALF 0x00000010 +#define AGCSTS_FS_P2A_FULL 0x00000008 + +#define AGCSTS_FS_A2P_EMPTY 0x00000004 +#define AGCSTS_FS_A2P_HALF 0x00000002 +#define AGCSTS_FS_A2P_FULL 0x00000001 + +/****************************************************************************/ +/* AMCC - Add-on Interrupt Control/Status Register */ +/****************************************************************************/ + +#define AINT_INT_MASK 0x00ff0000 +#define AINT_SEL_MASK 0x0000ffff +#define AINT_IS_ENSEL_MASK 0x00001f1f + +#define AINT_INT_ASSERTED 0x00800000 +#define AINT_BM_ERROR 0x00200000 +#define AINT_BIST_INT 0x00100000 + +#define AINT_RT_COMPLETE 0x00080000 +#define AINT_WT_COMPLETE 0x00040000 + +#define AINT_OUT_MB_INT 0x00020000 +#define AINT_IN_MB_INT 0x00010000 + +#define AINT_READ_COMPL 0x00008000 +#define AINT_WRITE_COMPL 0x00004000 + +#define AINT_OMB_ENABLE 0x00001000 +#define AINT_OMB_SELECT 0x00000c00 +#define AINT_OMB_BYTE 0x00000300 + +#define AINT_IMB_ENABLE 0x00000010 +#define AINT_IMB_SELECT 0x0000000c +#define AINT_IMB_BYTE 0x00000003 + +/* Enable Bus Mastering */ +#define EN_A2P_TRANSFERS 0x00000400 +/* FIFO Flag Reset */ +#define RESET_A2P_FLAGS 0x04000000L +/* FIFO Relative Priority */ +#define A2P_HI_PRIORITY 0x00000100L +/* Identify Interrupt Sources */ +#define ANY_S593X_INT 0x00800000L +#define READ_TC_INT 0x00080000L +#define WRITE_TC_INT 0x00040000L +#define IN_MB_INT 0x00020000L +#define MASTER_ABORT_INT 0x00100000L +#define TARGET_ABORT_INT 0x00200000L +#define BUS_MASTER_INT 0x00200000L + +/****************************************************************************/ + +struct pcilst_struct{ + struct pcilst_struct *next; + int used; + struct pci_dev *pcidev; + unsigned short vendor; + unsigned short device; + unsigned int master; + unsigned char pci_bus; + unsigned char pci_slot; + unsigned char pci_func; + unsigned int io_addr[5]; + unsigned int irq; +}; + +struct pcilst_struct *amcc_devices; // ptr to root list of all amcc devices + + +int i_ADDIDATADeviceID[]={0x15B8,0x10E8}; + + +/****************************************************************************/ + +void v_pci_card_list_init(unsigned short pci_vendor, char display); +void v_pci_card_list_cleanup(unsigned short pci_vendor); +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, unsigned short device_id); +int i_find_free_pci_card_by_position(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot, struct pcilst_struct **card); +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot); + +int i_pci_card_alloc(struct pcilst_struct *amcc); +int i_pci_card_free(struct pcilst_struct *amcc); +void v_pci_card_list_display(void); +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, unsigned char *pci_func, + unsigned short *io_addr, unsigned short *irq, unsigned short *master); + +/****************************************************************************/ + +/* build list of amcc cards in this system */ +void v_pci_card_list_init(unsigned short pci_vendor, char display) +{ + struct pci_dev *pcidev; + struct pcilst_struct *amcc,*last; + int i; + int i_Count=0; + amcc_devices=NULL; + last=NULL; + +#if LINUX_VERSION_CODE < 0x020300 + for(pcidev=pci_devices;pcidev;pcidev=pcidev->next){ +#else + pci_for_each_dev(pcidev){ +#endif + for(i_Count=0;i_Count<2;i_Count++) + { + pci_vendor=i_ADDIDATADeviceID[i_Count]; + if(pcidev->vendor==pci_vendor){ + amcc=kmalloc(sizeof(*amcc),GFP_KERNEL); + memset(amcc,0,sizeof(*amcc)); + + amcc->pcidev=pcidev; + if (last) { last->next=amcc; } + else { amcc_devices=amcc; } + last=amcc; + +#if LINUX_VERSION_CODE < 0x020300 + amcc->vendor=pcidev->vendor; + amcc->device=pcidev->device; + amcc->master=pcidev->master; + amcc->pci_bus=pcidev->bus->number; + amcc->pci_slot=PCI_SLOT(pcidev->devfn); + amcc->pci_func=PCI_FUNC(pcidev->devfn); + for (i=0;i<5;i++) + amcc->io_addr[i]=pcidev->base_address[i] & ~3UL; + amcc->irq=pcidev->irq; +#else + amcc->vendor=pcidev->vendor; + amcc->device=pcidev->device; +#if 0 + amcc->master=pcidev->master; // how get this information under 2.4 kernels? +#endif + amcc->pci_bus=pcidev->bus->number; + amcc->pci_slot=PCI_SLOT(pcidev->devfn); + amcc->pci_func=PCI_FUNC(pcidev->devfn); + for (i=0;i<5;i++) + amcc->io_addr[i]=pcidev->resource[i].start & ~3UL; + amcc->irq=pcidev->irq; +#endif + + } + } + } + + if (display) v_pci_card_list_display(); +} + +/****************************************************************************/ +/* free up list of amcc cards in this system */ +void v_pci_card_list_cleanup(unsigned short pci_vendor) +{ + struct pcilst_struct *amcc,*next; + + for(amcc=amcc_devices;amcc;amcc=next){ + next=amcc->next; + kfree(amcc); + } + + amcc_devices=NULL; +} + +/****************************************************************************/ +/* find first unused card with this device_id */ +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, unsigned short device_id) +{ + struct pcilst_struct *amcc,*next; + + for (amcc=amcc_devices;amcc;amcc=next) { + next=amcc->next; + if ((!amcc->used)&&(amcc->device==device_id)&&(amcc->vendor==vendor_id)) return amcc; + + } + + return NULL; +} + +/****************************************************************************/ +/* find card on requested position */ +int i_find_free_pci_card_by_position(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot, struct pcilst_struct **card) +{ + struct pcilst_struct *amcc,*next; + + *card=NULL; + for (amcc=amcc_devices;amcc;amcc=next) { + next=amcc->next; + if ((amcc->vendor==vendor_id)&&(amcc->device==device_id)&&(amcc->pci_bus==pci_bus)&&(amcc->pci_slot==pci_slot)) { + if (!(amcc->used)) { + *card=amcc; + return 0; // ok, card is found + } else { + rt_printk(" - \nCard on requested position is used b:s %d:%d!\n",pci_bus,pci_slot); + return 2; // card exist but is used + } + } + } + + return 1; // no card found +} + +/****************************************************************************/ +/* mark card as used */ +int i_pci_card_alloc(struct pcilst_struct *amcc) +{ + if (!amcc) return -1; + + if (amcc->used) return 1; + amcc->used=1; + return 0; +} + +/****************************************************************************/ +/* mark card as free */ +int i_pci_card_free(struct pcilst_struct *amcc) +{ + if (!amcc) return -1; + + if (!amcc->used) return 1; + amcc->used=0; + return 0; +} + +/****************************************************************************/ +/* display list of found cards */ +void v_pci_card_list_display(void) +{ + struct pcilst_struct *amcc,*next; + + printk("List of pci cards\n"); + printk("bus:slot:func vendor device master io_amcc io_daq irq used\n"); + + for (amcc=amcc_devices;amcc;amcc=next) { + next=amcc->next; + printk("%2d %2d %2d 0x%4x 0x%4x %3s 0x%4x 0x%4x %2d %2d\n", + amcc->pci_bus,amcc->pci_slot,amcc->pci_func,amcc->vendor,amcc->device,amcc->master?"yes":"no", + amcc->io_addr[0],amcc->io_addr[2],amcc->irq,amcc->used); + + } +} + +/****************************************************************************/ +/* return all card information for driver */ +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, unsigned char *pci_func, + unsigned short *io_addr, unsigned short *irq, unsigned short *master) +{ + int i; + + if (!amcc) return -1; + *pci_bus=amcc->pci_bus; + *pci_slot=amcc->pci_slot; + *pci_func=amcc->pci_func; + for (i=0;i<5;i++) + io_addr[i]=amcc->io_addr[i]; + *irq=amcc->irq; + *master=amcc->master; + return 0; +} + +/****************************************************************************/ +/* select and alloc card */ +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot) +{ + struct pcilst_struct *card; + + if ((pci_bus<1)&(pci_slot<1)) { // use autodetection + if ((card=ptr_find_free_pci_card_by_device(vendor_id,device_id))==NULL) { + rt_printk(" - Unused card not found in system!\n"); + return NULL; + } + } else { + switch (i_find_free_pci_card_by_position(vendor_id,device_id,pci_bus,pci_slot,&card)) { + case 1: + rt_printk(" - Card not found on requested position b:s %d:%d!\n",pci_bus,pci_slot); + return NULL; + case 2: + rt_printk(" - Card on requested position is used b:s %d:%d!\n",pci_bus,pci_slot); + return NULL; + } + } + + + if (i_pci_card_alloc(card)!=0) { + rt_printk(" - Can't allocate card!\n"); + return NULL; + } + + return card; +} +#endif diff --git a/comedi/drivers/addi-data/addi_common.c b/comedi/drivers/addi-data/addi_common.c new file mode 100644 index 00000000..d1ebfa7f --- /dev/null +++ b/comedi/drivers/addi-data/addi_common.c @@ -0,0 +1,1154 @@ + + + + +/*************************************************** + Generic Driver For ADDI APCI CARDs + + + + CONFIG OPTIONS + option[0] - PCI bus number - if bus number and slot number are 0, + then driver search for first unused card + option[1] - PCI slot number + + option[2]= 0 DMA ENABLE + = 1 DMA DISABLE + + ******************************************************************/ + +/*====================================================================== + Authors Email ID + Santosh Raktawan santosh.raktawan@tatainfotech.com + Sarath Chandran K R sarath.chandran@tatainfotech.com +========================================================================*/ + + + + +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : addi_common.c | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : | Date : | + +-----------------------------------------------------------------------+ + | Description : ADDI COMMON Main Module | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + + + + + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "addi_common.h" +#include "addi_amcc_s5933.h" +//#include "addi_eeprom.c" + +#define devpriv ((addi_private *)dev->private) +#define this_board ((boardtype *)dev->board_ptr) + + +#include "addi_eeprom.c" +#include "hwdrv_apci3120.c" +#include "hwdrv_apci1032.c" +#include "hwdrv_apci1516.c" +#include "hwdrv_apci2016.c" +#include "hwdrv_apci2032.c" +#include "hwdrv_apci2200.c" +#include "hwdrv_apci1564.c" +#include "hwdrv_apci1500.c" +#include "hwdrv_apci3501.c" +#include "hwdrv_apci035.c" +#include "hwdrv_apci3200.c" +#include "hwdrv_APCI1710.c" + +static boardtype boardtypes[] = +{ + {"apci3120", APCI3120_BOARD_VENDOR_ID, 0x818D, + AMCC_OP_REG_SIZE, APCI3120_ADDRESS_RANGE,8,0, + ADDIDATA_NO_EEPROM,NULL, + 16, 8, 16, 8, 0xffff, 0x3fff, + &range_apci3120_ai, &range_apci3120_ao, + 4,4,0x0f,1,1,10000,100000, + v_APCI3120_Interrupt, + i_APCI3120_Reset, + i_APCI3120_InsnConfigAnalogInput, + i_APCI3120_InsnReadAnalogInput, + NULL, + NULL, + i_APCI3120_CommandTestAnalogInput, + i_APCI3120_CommandAnalogInput, + i_APCI3120_StopCyclicAcquisition, + NULL, + i_APCI3120_InsnWriteAnalogOutput, + NULL, + NULL, + i_APCI3120_InsnReadDigitalInput, + NULL, + i_APCI3120_InsnBitsDigitalInput, + i_APCI3120_InsnConfigDigitalOutput, + i_APCI3120_InsnWriteDigitalOutput, + i_APCI3120_InsnBitsDigitalOutput, + NULL, + i_APCI3120_InsnConfigTimer, + i_APCI3120_InsnWriteTimer, + i_APCI3120_InsnReadTimer, + NULL + }, + + {"apci1032",APCI1032_BOARD_VENDOR_ID,0x1003, + 4,APCI1032_ADDRESS_RANGE,0,0, + ADDIDATA_EEPROM,ADDIDATA_93C76, + 0,0,0,0,0,0,0,0, + 32,0,0,0,0,0,0, + v_APCI1032_Interrupt, + i_APCI1032_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1032_ConfigDigitalInput, + i_APCI1032_Read1DigitalInput, + NULL, + i_APCI1032_ReadMoreDigitalInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, + {"apci1516",APCI1516_BOARD_VENDOR_ID,0x1001, + 128,APCI1516_ADDRESS_RANGE,32,0, + ADDIDATA_EEPROM,ADDIDATA_S5920, + 0,0,0,0,0,0,NULL,NULL,8, + 8,0,0,1,0,0, + NULL, + i_APCI1516_Reset, + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1516_Read1DigitalInput, + NULL, + i_APCI1516_ReadMoreDigitalInput, + i_APCI1516_ConfigDigitalOutput, + i_APCI1516_WriteDigitalOutput, + i_APCI1516_ReadDigitalOutput, + NULL, + i_APCI1516_ConfigWatchdog, + i_APCI1516_StartStopWriteWatchdog, + i_APCI1516_ReadWatchdog, + NULL + }, + + {"apci2016",APCI2016_BOARD_VENDOR_ID,0x1002, + 128,APCI2016_ADDRESS_RANGE,32,0, + ADDIDATA_EEPROM,ADDIDATA_S5920, + 0,0,0,0,0,0, + NULL,NULL, + 0,16,0,0,1,0,0, + NULL, + i_APCI2016_Reset, + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI2016_ConfigDigitalOutput, + i_APCI2016_WriteDigitalOutput, + i_APCI2016_BitsDigitalOutput, + NULL, + i_APCI2016_ConfigWatchdog, + i_APCI2016_StartStopWriteWatchdog, + i_APCI2016_ReadWatchdog, + NULL + }, + + {"apci2032", APCI2032_BOARD_VENDOR_ID, 0x1004, + 4,APCI2032_ADDRESS_RANGE,0,0, + ADDIDATA_EEPROM,ADDIDATA_93C76, + 0, 0, 0, 0, 0, 0, + NULL, NULL, + 0,32,0xffffffff,0,1,0,0, + v_APCI2032_Interrupt, + i_APCI2032_Reset, + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI2032_ConfigDigitalOutput, + i_APCI2032_WriteDigitalOutput, + i_APCI2032_ReadDigitalOutput, + i_APCI2032_ReadInterruptStatus, + i_APCI2032_ConfigWatchdog, + i_APCI2032_StartStopWriteWatchdog, + i_APCI2032_ReadWatchdog, + NULL + }, + {"apci2200",APCI2200_BOARD_VENDOR_ID,0x1005, + 4,APCI2200_ADDRESS_RANGE,0,0, + ADDIDATA_EEPROM,ADDIDATA_93C76, + 0,0,0,0,0,0,NULL,NULL,8, + 16,0,0,1,0,0, + NULL, + i_APCI2200_Reset, + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI2200_Read1DigitalInput, + NULL, + i_APCI2200_ReadMoreDigitalInput, + i_APCI2200_ConfigDigitalOutput, + i_APCI2200_WriteDigitalOutput, + i_APCI2200_ReadDigitalOutput, + NULL, + i_APCI2200_ConfigWatchdog, + i_APCI2200_StartStopWriteWatchdog, + i_APCI2200_ReadWatchdog, + NULL + }, + {"apci1564",APCI1564_BOARD_VENDOR_ID,0x1006, + 128,APCI1564_ADDRESS_RANGE,0,0, + ADDIDATA_EEPROM,ADDIDATA_93C76, + 0,0,0,0,0,0, + NULL,NULL, + 32,32,0xffffffff,0,1,0,0, + v_APCI1564_Interrupt, + i_APCI1564_Reset, + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1564_ConfigDigitalInput, + i_APCI1564_Read1DigitalInput, + NULL, + i_APCI1564_ReadMoreDigitalInput, + i_APCI1564_ConfigDigitalOutput, + i_APCI1564_WriteDigitalOutput, + i_APCI1564_ReadDigitalOutput, + i_APCI1564_ReadInterruptStatus, + i_APCI1564_ConfigTimerCounterWatchdog, + i_APCI1564_StartStopWriteTimerCounterWatchdog, + i_APCI1564_ReadTimerCounterWatchdog, + NULL + }, + {"apci1500", APCI1500_BOARD_VENDOR_ID, 0x80fc, + 128,APCI1500_ADDRESS_RANGE,4,0, + ADDIDATA_NO_EEPROM,NULL, + 0, 0, 0, 0, 0, 0, + NULL, NULL, + 16,16,0xffff,0,1,0,0, + v_APCI1500_Interrupt, + i_APCI1500_Reset, + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1500_ConfigDigitalInputEvent, + i_APCI1500_Initialisation, + i_APCI1500_StartStopInputEvent, + i_APCI1500_ReadMoreDigitalInput, + i_APCI1500_ConfigDigitalOutputErrorInterrupt, + i_APCI1500_WriteDigitalOutput, + i_APCI1500_ConfigureInterrupt, + NULL, + i_APCI1500_ConfigCounterTimerWatchdog, + i_APCI1500_StartStopTriggerTimerCounterWatchdog, + i_APCI1500_ReadInterruptMask, + i_APCI1500_ReadCounterTimerWatchdog + }, + + + {"apci3001", APCI3120_BOARD_VENDOR_ID, 0x828D, + AMCC_OP_REG_SIZE, APCI3120_ADDRESS_RANGE,8,0, + ADDIDATA_NO_EEPROM,NULL, + 16, 8, 16, 0, 0xfff, 0, + &range_apci3120_ai, NULL, + 4,4,0x0f,1,1,10000,100000, + v_APCI3120_Interrupt, + i_APCI3120_Reset, + i_APCI3120_InsnConfigAnalogInput, + i_APCI3120_InsnReadAnalogInput, + NULL,NULL, + i_APCI3120_CommandTestAnalogInput, + i_APCI3120_CommandAnalogInput, + i_APCI3120_StopCyclicAcquisition, + NULL, + NULL, + NULL, + NULL, + i_APCI3120_InsnReadDigitalInput, + NULL, + i_APCI3120_InsnBitsDigitalInput, + i_APCI3120_InsnConfigDigitalOutput, + i_APCI3120_InsnWriteDigitalOutput, + i_APCI3120_InsnBitsDigitalOutput, + NULL, + i_APCI3120_InsnConfigTimer, + i_APCI3120_InsnWriteTimer, + i_APCI3120_InsnReadTimer, + NULL + }, + {"apci3501", APCI3501_BOARD_VENDOR_ID, 0x3001, + 64,APCI3501_ADDRESS_RANGE,0,0, + ADDIDATA_EEPROM,ADDIDATA_S5933, + 0, 0, 0, 8, 0,16383, + NULL,&range_apci3501_ao, + 2,2,0x3,0,1,0,0, + v_APCI3501_Interrupt, + i_APCI3501_Reset, + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3501_ConfigAnalogOutput, + i_APCI3501_WriteAnalogOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3501_ReadDigitalInput, + i_APCI3501_ConfigDigitalOutput, + i_APCI3501_WriteDigitalOutput, + i_APCI3501_ReadDigitalOutput, + NULL, + i_APCI3501_ConfigTimerCounterWatchdog, + i_APCI3501_StartStopWriteTimerCounterWatchdog, + i_APCI3501_ReadTimerCounterWatchdog, + NULL + }, + {"apci035", APCI035_BOARD_VENDOR_ID, 0x0300, + 127,APCI035_ADDRESS_RANGE ,0,0,1,ADDIDATA_S5920, + 16,8,16,0, 0xff, 0, + &range_apci035_ai, NULL, + 0,0,0,0,1,10000,100000, + v_APCI035_Interrupt, + i_APCI035_Reset, + i_APCI035_ConfigAnalogInput, + i_APCI035_ReadAnalogInput , + NULL,NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI035_ConfigTimerWatchdog, + i_APCI035_StartStopWriteTimerWatchdog, + i_APCI035_ReadTimerWatchdog, + NULL + }, + {"apci3200", APCI3200_BOARD_VENDOR_ID, 0x3000, + 128,256,4,4,ADDIDATA_EEPROM,ADDIDATA_S5920, + 16,8,16,0, 0x3ffff, 0, + &range_apci3200_ai, NULL, + 4,4,0,0,0,10000,100000, + v_APCI3200_Interrupt, + i_APCI3200_Reset, + i_APCI3200_ConfigAnalogInput, + i_APCI3200_ReadAnalogInput , + i_APCI3200_InsnWriteReleaseAnalogInput, + i_APCI3200_InsnBits_AnalogInput_Test, + i_APCI3200_CommandTestAnalogInput, + i_APCI3200_CommandAnalogInput, + i_APCI3200_StopCyclicAcquisition, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3200_ReadDigitalInput, + i_APCI3200_ConfigDigitalOutput, + i_APCI3200_WriteDigitalOutput, + i_APCI3200_ReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + NULL + }, + + {"apci1710",APCI1710_BOARD_VENDOR_ID,APCI1710_BOARD_DEVICE_ID, + 128,8,256,0, + ADDIDATA_NO_EEPROM,NULL, + 0, 0, 0, 0, 0, 0, + NULL, NULL, + 0,0,0,0,0,0,0, + v_APCI1710_Interrupt, + i_APCI1710_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + } + +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype)) + +comedi_driver driver_addi ={ + driver_name: "addi_common", + module: THIS_MODULE, + attach: i_ADDI_Attach, + detach: i_ADDI_Detach, + num_names: n_boardtypes, + board_name: boardtypes, + offset: sizeof(boardtype), + }; + + + +//This macro is defined in comedidev.h +/* #define COMEDI_INITCLEANUP(x) \ + int init_module(void){return comedi_driver_register(&(x));} \ + void cleanup_module(void){comedi_driver_unregister(&(x));} +*/ + +COMEDI_INITCLEANUP(driver_addi); + + + + +/* ++----------------------------------------------------------------------------+ +| Function name :static int i_ADDI_Attach(comedi_device *dev, | +| comedi_devconfig *it) | +| | ++----------------------------------------------------------------------------+ +| Task :Detects the card. | +| Configure the driver for a particular board. | +| This function does all the initializations and memory | +| allocation of data structures for the driver. | ++----------------------------------------------------------------------------+ +| Input Parameters :comedi_device *dev | +| comedi_devconfig *it | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + + +static int i_ADDI_Attach(comedi_device *dev,comedi_devconfig *it) +{ + comedi_subdevice *s; + int ret,pages,i; + DWORD dw_Dummy; + unsigned short io_addr[5],master,irq;//v_58 + unsigned int iobase_a,iobase_main,iobase_addon,iobase_reserved; + struct pcilst_struct *card=NULL; + unsigned char pci_bus,pci_slot,pci_func; + + if (!pci_list_builded) + { + v_pci_card_list_init(this_board->i_VendorId,1); //1 for displaying the list.. + pci_list_builded=1; + } + //rt_printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); + + if ((card=ptr_select_and_alloc_pci_card(this_board->i_VendorId, this_board->i_DeviceId, it->options[0], it->options[1]))==NULL) + return -EIO; + if ((i_pci_card_data(card,&pci_bus,&pci_slot,&pci_func,&io_addr[0],&irq,&master))<0) + { + i_pci_card_free(card); + rt_printk(" - Can't get AMCC data!\n"); + return -EIO; + } + iobase_a=io_addr[0]; + iobase_main=io_addr[1]; + iobase_addon=io_addr[2]; + iobase_reserved=io_addr[3]; + rt_printk(", b:s:f=%d:%d:%d, base0:0x%4x, base1: 0x%4x, base2: 0x%4x",pci_bus,pci_slot,pci_func,io_addr[0],io_addr[1],io_addr[2]); + if (check_region(iobase_main, this_board->i_IorangeBase1) < 0) + { + rt_printk("I/O port conflict\n"); + return -EIO; + } + //if(this_board->i_Dma) + if(iobase_a) + { + if (check_region(iobase_a, this_board->i_IorangeBase0) < 0) + { + printk("AMCC check region failed\n"); + rt_printk("I/O port conflict\n"); + return -EIO; + } + } + + // ## + if(io_addr[2]) + { + if (check_region(io_addr[2], this_board->i_IorangeBase2) < 0) + { + printk("Base 2 check region failed\n"); + rt_printk("I/O port conflict\n"); + return -EIO; + } + + + } + //## + dev->iobase=iobase_main;// DAQ base address... + request_region(dev->iobase, this_board->i_IorangeBase1, "ADDI COMMON"); + + dev->board_name =this_board->pc_DriverName; + if((ret=alloc_private(dev,sizeof(addi_private)))<0) + return -ENOMEM; + devpriv->amcc=card; + devpriv->master=master; //testing + devpriv->iobase=dev->iobase; + devpriv->i_IobaseAmcc=iobase_a;//AMCC base address... + devpriv->i_IobaseAddon=iobase_addon;//ADD ON base address.... + devpriv->i_IobaseReserved=iobase_reserved; + + //if(this_board->i_Dma) + if(iobase_a) + { + request_region(devpriv->i_IobaseAmcc,this_board->i_IorangeBase0, "ADDI COMMON"); + } + + //## + if(io_addr[2]) + { + request_region(io_addr[2],this_board->i_IorangeBase2, "ADDI COMMON"); + } + + //## + + if (irq>0) + { + if (comedi_request_irq(irq, v_ADDI_Interrupt, SA_SHIRQ, "ADDI COMMON", dev)) + { + rt_printk(", unable to allocate IRQ %d, DISABLING IT", irq); + irq=0; /* Can't use IRQ */ + } + else + { + rt_printk(", irq=%d", irq); + } + } + else + { + rt_printk(", IRQ disabled"); + } + rt_printk("\n%d %d %d\n",it->options[0],it->options[1],it->options[2]); + dev->irq = irq; + + // Read eepeom and fill boardtype Structure + + if(this_board->i_PCIEeprom) + { + if (!(strcmp(this_board->pc_EepromChip, "S5920"))) + { + // Set 3 wait stait + if(!(strcmp(this_board->pc_DriverName,"apci035"))) + { + outl(0x80808082,devpriv->i_IobaseAmcc+0x60); + } + else + { + outl(0x83838383,devpriv->i_IobaseAmcc+0x60); + } + // Enable the interrupt for the controler + dw_Dummy = inl(devpriv->i_IobaseAmcc+ 0x38); + outl(dw_Dummy | 0x2000,devpriv->i_IobaseAmcc+0x38); + } + i_EepromReadMainHeader(io_addr[0],this_board->pc_EepromChip,dev); + } + if (it->options[2]>0) + { + devpriv->us_UseDma=ADDI_DISABLE; + } + else + { + devpriv->us_UseDma=ADDI_ENABLE; + } + + if(this_board->i_Dma) + { + if (devpriv->us_UseDma==ADDI_ENABLE) + { + // alloc DMA buffers + devpriv->b_DmaDoubleBuffer=0; + for (i=0; i<2; i++) + { + for (pages=4; pages>=0; pages--) + { + + if((devpriv->ul_DmaBufferVirtual[i]=__get_free_pages(GFP_KERNEL,pages))) + break; + + } + + + if (devpriv->ul_DmaBufferVirtual[i]) + { + + devpriv->ui_DmaBufferPages[i]=pages; + devpriv->ui_DmaBufferSize[i]=PAGE_SIZE*pages; + devpriv->ui_DmaBufferSamples[i]=devpriv->ui_DmaBufferSize[i]>>1; + devpriv->ul_DmaBufferHw[i]=virt_to_bus((void*)devpriv->ul_DmaBufferVirtual[i]); + + } + } + if (!devpriv->ul_DmaBufferVirtual[0]) + { + rt_printk(", Can't allocate DMA buffer, DMA disabled!"); + master=0; + devpriv->us_UseDma=ADDI_DISABLE; + } + + if (devpriv->ul_DmaBufferVirtual[1]) + devpriv->b_DmaDoubleBuffer=1; + + + } + + + if ((devpriv->us_UseDma==ADDI_ENABLE)) + { + rt_printk("\nDMA ENABLED\n"); + } + else + { + rt_printk("\nDMA DISABLED\n"); + } + } + + + + if (!strcmp(this_board->pc_DriverName,"apci1710")) + { + dev->n_subdevices = 9; + if((ret=alloc_subdevices(dev))<0) + return ret; + + // Allocate and Initialise Timer Subdevice Structures + s = dev->subdevices + 0; + + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_WRITEABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 3; + s->maxdata = 0; + s->len_chanlist = 3; + s->range_table = &range_digital; + s->insn_write=i_APCI1710_InsnWriteEnableDisableTimer; + s->insn_read=i_APCI1710_InsnReadAllTimerValue; + s->insn_config=i_APCI1710_InsnConfigInitTimer; + s->insn_bits=i_APCI1710_InsnBitsTimer; + + + // Allocate and Initialise DIO Subdevice Structures + s = dev->subdevices + 1; + + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITEABLE|SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 7; + s->maxdata = 1; + s->len_chanlist = 7; + s->range_table = &range_digital; + s->insn_config=i_APCI1710_InsnConfigDigitalIO; + s->insn_read= i_APCI1710_InsnReadDigitalIOChlValue; + s->insn_bits=i_APCI1710_InsnBitsDigitalIOPortOnOff; + s->insn_write=i_APCI1710_InsnWriteDigitalIOChlOnOff; + + + // Allocate and Initialise Chrono Subdevice Structures + s = dev->subdevices + 2; + + s->type = COMEDI_SUBD_CHRONO; + s->subdev_flags = SDF_WRITEABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 4; + s->maxdata = 0; + s->len_chanlist = 4; + s->range_table = &range_digital; + s->insn_write=i_APCI1710_InsnWriteEnableDisableChrono; + s->insn_read=i_APCI1710_InsnReadChrono; + s->insn_config=i_APCI1710_InsnConfigInitChrono; + s->insn_bits=i_APCI1710_InsnBitsChronoDigitalIO; + + + // Allocate and Initialise PWM Subdevice Structures + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_PWM; + s->subdev_flags = SDF_WRITEABLE|SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 3; + s->maxdata = 1; + s->len_chanlist = 3; + s->range_table = &range_digital; + s->io_bits=0; //all bits input + s->insn_config = i_APCI1710_InsnConfigPWM; + s->insn_read = i_APCI1710_InsnReadGetPWMStatus; + s->insn_write = i_APCI1710_InsnWritePWM; + s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt; + + // Allocate and Initialise TTLIO Subdevice Structures + s = dev->subdevices + 4; + s->type = COMEDI_SUBD_TTLIO; + s->subdev_flags = SDF_WRITEABLE|SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 8; + s->maxdata = 1; + s->len_chanlist = 8; + s->range_table = &range_apci1710_ttl; // to pass arguments in range + s->insn_config = i_APCI1710_InsnConfigInitTTLIO; + s->insn_bits = i_APCI1710_InsnBitsReadTTLIO; + s->insn_write = i_APCI1710_InsnWriteSetTTLIOChlOnOff; + s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue; + + + // Allocate and Initialise TOR Subdevice Structures + s = dev->subdevices + 5; + s->type = COMEDI_SUBD_TOR; + s->subdev_flags = SDF_WRITEABLE|SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 8; + s->maxdata = 1; + s->len_chanlist = 8; + s->range_table = &range_digital; + s->io_bits=0; //all bits input + s->insn_config = i_APCI1710_InsnConfigInitTorCounter; + s->insn_read = i_APCI1710_InsnReadGetTorCounterInitialisation; + s->insn_write = i_APCI1710_InsnWriteEnableDisableTorCounter; + s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue; + + // Allocate and Initialise SSI Subdevice Structures + s = dev->subdevices + 6; + s->type = COMEDI_SUBD_SSI; + s->subdev_flags = SDF_WRITEABLE|SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan =4; + s->maxdata = 1; + s->len_chanlist = 4; + s->range_table = &range_apci1710_ssi; + s->insn_config = i_APCI1710_InsnConfigInitSSI; + s->insn_read = i_APCI1710_InsnReadSSIValue; + s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO; + + // Allocate and Initialise PULSEENCODER Subdevice Structures + s = dev->subdevices + 7; + s->type = COMEDI_SUBD_PULSEENCODER; + s->subdev_flags = SDF_WRITEABLE|SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 4; + s->maxdata = 1; + s->len_chanlist = 4; + s->range_table = &range_digital; + s->insn_config = i_APCI1710_InsnConfigInitPulseEncoder; + s->insn_write = i_APCI1710_InsnWriteEnableDisablePulseEncoder; + s->insn_bits = i_APCI1710_InsnBitsReadWritePulseEncoder; + s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder; + + // Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures + s = dev->subdevices + 8; + s->type = COMEDI_SUBD_INCREMENTALCOUNTER; + s->subdev_flags = SDF_WRITEABLE|SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 500; + s->maxdata = 1; + s->len_chanlist = 500; + s->range_table = &range_apci1710_inccpt; + s->insn_config = i_APCI1710_InsnConfigINCCPT; + s->insn_write = i_APCI1710_InsnWriteINCCPT; + s->insn_read = i_APCI1710_InsnReadINCCPT; + s->insn_bits = i_APCI1710_InsnBitsINCCPT; + + // save base address + devpriv->s_BoardInfos.ui_Address=io_addr[2]; + } + else + { + dev->n_subdevices = 6; + if((ret=alloc_subdevices(dev))<0) + return ret; + + // Allocate and Initialise AI Subdevice Structures + s = dev->subdevices + 0; + if(this_board->i_NbrAiChannel) + { + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE|SDF_RT|SDF_COMMON|SDF_GROUND|SDF_DIFF; + s->n_chan = this_board->i_NbrAiChannel; + s->maxdata = this_board->i_AiMaxdata; + s->len_chanlist = this_board->i_AiChannelList; + s->range_table = this_board->pr_AiRangelist; + + + + s->insn_config=this_board->i_hwdrv_InsnConfigAnalogInput; + s->insn_read=this_board->i_hwdrv_InsnReadAnalogInput; + s->insn_write=this_board->i_hwdrv_InsnWriteAnalogInput; + s->insn_bits=this_board->i_hwdrv_InsnBitsAnalogInput; + s->do_cmdtest=this_board->i_hwdrv_CommandTestAnalogInput; + s->do_cmd=this_board->i_hwdrv_CommandAnalogInput; + s->cancel=this_board->i_hwdrv_CancelAnalogInput; + + } + else + { + s->type=COMEDI_SUBD_UNUSED; + } + + // Allocate and Initialise AO Subdevice Structures + s = dev->subdevices + 1; + if(this_board->i_NbrAoChannel) + { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITEABLE|SDF_GROUND|SDF_COMMON|SDF_RT; + s->n_chan = this_board->i_NbrAoChannel; + s->maxdata = this_board->i_AoMaxdata; + s->len_chanlist = this_board->i_NbrAoChannel; + s->range_table = this_board->pr_AoRangelist; + s->insn_config=this_board->i_hwdrv_InsnConfigAnalogOutput; + s->insn_write=this_board->i_hwdrv_InsnWriteAnalogOutput; + } + else + { + s->type=COMEDI_SUBD_UNUSED; + } + // Allocate and Initialise DI Subdevice Structures + s = dev->subdevices + 2; + if(this_board->i_NbrDiChannel) + { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = this_board->i_NbrDiChannel; + s->maxdata = 1; + s->len_chanlist = this_board->i_NbrDiChannel; + s->range_table = &range_digital; + s->io_bits=0; /* all bits input */ + + s->insn_config=this_board->i_hwdrv_InsnConfigDigitalInput; + s->insn_read=this_board->i_hwdrv_InsnReadDigitalInput; + s->insn_write=this_board->i_hwdrv_InsnWriteDigitalInput; + s->insn_bits=this_board->i_hwdrv_InsnBitsDigitalInput; + + } + else + { + s->type=COMEDI_SUBD_UNUSED; + } + // Allocate and Initialise DO Subdevice Structures + s = dev->subdevices + 3; + if(this_board->i_NbrDoChannel) + { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITEABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan= this_board->i_NbrDoChannel; + s->maxdata = this_board->i_DoMaxdata; + s->len_chanlist =this_board->i_NbrDoChannel ; + s->range_table = &range_digital; + s->io_bits=0xf; /* all bits output */ + + s->insn_config=this_board->i_hwdrv_InsnConfigDigitalOutput;//for digital output memory.. + s->insn_write=this_board->i_hwdrv_InsnWriteDigitalOutput; + s->insn_bits=this_board->i_hwdrv_InsnBitsDigitalOutput; + s->insn_read=this_board->i_hwdrv_InsnReadDigitalOutput; + } + else + { + s->type=COMEDI_SUBD_UNUSED; + } + + // Allocate and Initialise Timer Subdevice Structures + s = dev->subdevices + 4; + if(this_board->i_Timer) + { + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_WRITEABLE|SDF_RT|SDF_GROUND|SDF_COMMON; + s->n_chan = 1; + s->maxdata = 0; + s->len_chanlist = 1; + s->range_table = &range_digital; + + s->insn_write=this_board->i_hwdrv_InsnWriteTimer; + s->insn_read=this_board->i_hwdrv_InsnReadTimer; + s->insn_config=this_board->i_hwdrv_InsnConfigTimer; + s->insn_bits=this_board->i_hwdrv_InsnBitsTimer; + } + else + { + s->type=COMEDI_SUBD_UNUSED; + } + + /* EEPROM */ + s=dev->subdevices+5; + if(this_board->i_PCIEeprom) + { + s->type=COMEDI_SUBD_MEMORY; + s->subdev_flags=SDF_READABLE|SDF_INTERNAL; + s->n_chan=256; + s->maxdata=0xffff; + s->insn_read=i_ADDIDATA_InsnReadEeprom; + } + else + { + s->type=COMEDI_SUBD_UNUSED; + } + } + i_ADDI_Reset(dev); + devpriv->b_ValidDriver=1; + return 0; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function name : static int i_ADDI_Detach(comedi_device *dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Deallocates resources of the addi_common driver | +| Free the DMA buffers, unregister irq. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + + +static int i_ADDI_Detach(comedi_device *dev) +{ + + if (dev->private) + { + if (devpriv->b_ValidDriver) i_ADDI_Reset(dev); + if(devpriv->i_IobaseAmcc) + release_region(devpriv->i_IobaseAmcc,this_board->i_IorangeBase0); + if (devpriv->allocated) + i_pci_card_free(devpriv->amcc); + if (devpriv->ul_DmaBufferVirtual[0]) + free_pages(devpriv->ul_DmaBufferVirtual[0],devpriv->ui_DmaBufferPages[0]); + if (devpriv->ul_DmaBufferVirtual[1]) + free_pages(devpriv->ul_DmaBufferVirtual[1],devpriv->ui_DmaBufferPages[1]); + } + + if(dev->irq) + { + free_irq(dev->irq,dev); + } + + if(dev->iobase) release_region(dev->iobase,this_board->i_IorangeBase1); + + if(devpriv->i_IobaseAddon) release_region(devpriv->i_IobaseAddon,this_board->i_IorangeBase2); + + if (pci_list_builded) + { + //v_pci_card_list_cleanup(PCI_VENDOR_ID_AMCC); + v_pci_card_list_cleanup(this_board->i_VendorId); + pci_list_builded=0; + } + + return 0; +} + + +/* ++----------------------------------------------------------------------------+ +| Function name : static int i_ADDI_Reset(comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task : Disables all interrupts, Resets digital output to low, | +| Set all analog output to low | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +static int i_ADDI_Reset(comedi_device *dev) +{ + + this_board->i_hwdrv_Reset(dev); + return 0; +} + + + +// Interrupt function +/* ++----------------------------------------------------------------------------+ +| Function name : | +|static void v_ADDI_Interrupt(int irq, void *d, struct pt_regs *regs) | +| | ++----------------------------------------------------------------------------+ +| Task : Registerd interrupt routine | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +static void v_ADDI_Interrupt(int irq, void *d, struct pt_regs *regs) +{ +comedi_device *dev = d; +this_board->v_hwdrv_Interrupt(irq,d,regs); +return; +} +// EEPROM Read Function +/* ++----------------------------------------------------------------------------+ +| Function name : | +|INT i_ADDIDATA_InsnReadEeprom(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +| | ++----------------------------------------------------------------------------+ +| Task : Read 256 words from EEPROM | +| | ++----------------------------------------------------------------------------+ +| Input Parameters :(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + +static int i_ADDIDATA_InsnReadEeprom(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + WORD w_Data; + WORD w_Address; + w_Address = CR_CHAN(insn->chanspec);// address to be read as 0,1,2,3...255 + + w_Data=w_EepromReadWord(devpriv->i_IobaseAmcc,this_board->pc_EepromChip,0x100+(2*w_Address)); + data[0]=w_Data; + //multiplied by 2 bcozinput will be like 0,1,2...255 + return insn->n; + +} + + + + + diff --git a/comedi/drivers/addi-data/addi_common.h b/comedi/drivers/addi-data/addi_common.h new file mode 100644 index 00000000..3747497e --- /dev/null +++ b/comedi/drivers/addi-data/addi_common.h @@ -0,0 +1,475 @@ +/***********ADDI_COMMON.H*********************/ + + + + + +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : addi_common.h | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : | Date : | + +-----------------------------------------------------------------------+ + | Description : ADDI COMMON Header File | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + + + + +//including header files + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "addi_amcc_s5933.h" +#include +#include + +#define ERROR -1 +#define SUCCESS 1 + +// variable type definition + +#define VOID void +#define UINT unsigned int +#define ULONG unsigned long +#define USHORT unsigned short +#define PUSHORT unsigned short * +#define INT int +#define BYTE unsigned char +#define PBYTE unsigned char * +#define PINT int * +#define PUINT unsigned int * +#define CHAR char +#define PCHAR char * +#define PRANGE comedi_lrange * +#define LOBYTE(W) (BYTE )((W)&0xFF) +#define HIBYTE(W) (BYTE )(((W)>>8)&0xFF) +#define MAKEWORD(H,L) (USHORT )((L)|( (H)<<8) ) +#define LOWORD(W) (USHORT )((W)&0xFFFF) +#define HIWORD(W) (USHORT )(((W)>>16)&0xFFFF) +#define MAKEDWORD(H,L) (UINT )((L)|( (H)<<16) ) + +#define DWORD unsigned long +#define WORD unsigned short + +#define ADDI_ENABLE 1 +#define ADDI_DISABLE 0 +#define APCI1710_SAVE_INTERRUPT 1 + +#define ADDIDATA_EEPROM 1 +#define ADDIDATA_NO_EEPROM 0 +#define ADDIDATA_93C76 "93C76" +#define ADDIDATA_S5920 "S5920" +#define ADDIDATA_S5933 "S5933" + +// Structures +// structure for the boardtype +typedef struct { + + PCHAR pc_DriverName; // driver name + INT i_VendorId; //PCI vendor a device ID of card + INT i_DeviceId; + INT i_IorangeBase0; + INT i_IorangeBase1; + INT i_IorangeBase2; // base 2 range + INT i_IorangeBase3; // base 3 range + INT i_PCIEeprom; // eeprom present or not + PCHAR pc_EepromChip; // type of chip + INT i_NbrAiChannel; // num of A/D chans + INT i_NbrAiChannelDiff;// num of A/D chans in diff mode + INT i_AiChannelList;// len of chanlist + INT i_NbrAoChannel;// num of D/A chans + INT i_AiMaxdata;// resolution of A/D + INT i_AoMaxdata;// resolution of D/A + PRANGE pr_AiRangelist; // rangelist for A/D + PRANGE pr_AoRangelist;// rangelist for D/A + + INT i_NbrDiChannel; // Number of DI channels + INT i_NbrDoChannel; // Number of DO channels + INT i_DoMaxdata; // data to set all chanels high + + INT i_Dma; // dma present or not + INT i_Timer; // timer subdevice present or not + UINT ui_MinAcquisitiontimeNs; // Minimum Acquisition in Nano secs + UINT ui_MinDelaytimeNs; // Minimum Delay in Nano secs + +// interrupt and reset + void (*v_hwdrv_Interrupt)(int irq, void *d, struct pt_regs *regs); + int (*i_hwdrv_Reset)(comedi_device *dev); + +//Subdevice functions +//ANALOG INPUT + +int (*i_hwdrv_InsnConfigAnalogInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnReadAnalogInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnWriteAnalogInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnBitsAnalogInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_CommandTestAnalogInput)(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) ; +int (*i_hwdrv_CommandAnalogInput)(comedi_device * dev,comedi_subdevice * s); +int (*i_hwdrv_CancelAnalogInput)(comedi_device * dev, comedi_subdevice * s); + + +//Analog Output +int (*i_hwdrv_InsnConfigAnalogOutput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnWriteAnalogOutput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnBitsAnalogOutput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +//Digital Input +int (*i_hwdrv_InsnConfigDigitalInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + int (*i_hwdrv_InsnReadDigitalInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnWriteDigitalInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnBitsDigitalInput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +//Digital Output +int (*i_hwdrv_InsnConfigDigitalOutput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnWriteDigitalOutput)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnBitsDigitalOutput)(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); +int (*i_hwdrv_InsnReadDigitalOutput)(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); +//TIMER + int (*i_hwdrv_InsnConfigTimer)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + int (*i_hwdrv_InsnWriteTimer)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + int (*i_hwdrv_InsnReadTimer)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + int (*i_hwdrv_InsnBitsTimer)(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +} boardtype; + + + + + + +//MODULE INFO STRUCTURE + + + + typedef union + { + /*****************************/ + /* Incremental counter infos */ + /*****************************/ + + struct + { + union + { + struct + { + BYTE b_ModeRegister1; + BYTE b_ModeRegister2; + BYTE b_ModeRegister3; + BYTE b_ModeRegister4; + }s_ByteModeRegister; + DWORD dw_ModeRegister1_2_3_4; + }s_ModeRegister; + + struct + { + unsigned int b_IndexInit : 1; + unsigned int b_CounterInit : 1; + unsigned int b_ReferenceInit : 1; + unsigned int b_IndexInterruptOccur : 1; + unsigned int b_CompareLogicInit : 1; + unsigned int b_FrequencyMeasurementInit : 1; + unsigned int b_FrequencyMeasurementEnable : 1; + }s_InitFlag; + + }s_SiemensCounterInfo; + + /*************/ + /* SSI infos */ + /*************/ + + struct + { + BYTE b_SSIProfile; + BYTE b_PositionTurnLength; + BYTE b_TurnCptLength; + BYTE b_SSIInit; + }s_SSICounterInfo; + + + /*****************/ + /* TTL I/O infos */ + /*****************/ + + struct + { + BYTE b_TTLInit; + BYTE b_PortConfiguration [4]; + }s_TTLIOInfo; + + /*********************/ + /* Digital I/O infos */ + /*********************/ + + struct + { + BYTE b_DigitalInit; + BYTE b_ChannelAMode; + BYTE b_ChannelBMode; + BYTE b_OutputMemoryEnabled; + DWORD dw_OutputMemory; + }s_DigitalIOInfo; + + /*********************/ + /* 82X54 timer infos */ + /*********************/ + + struct + { + struct + { + BYTE b_82X54Init; + BYTE b_InputClockSelection; + BYTE b_InputClockLevel; + BYTE b_OutputLevel; + BYTE b_HardwareGateLevel; + DWORD dw_ConfigurationWord; + }s_82X54TimerInfo [3]; + BYTE b_InterruptMask; + }s_82X54ModuleInfo; + + /*********************/ + /* Chronometer infos */ + /*********************/ + + struct + { + BYTE b_ChronoInit; + BYTE b_InterruptMask; + BYTE b_PCIInputClock; + BYTE b_TimingUnit; + BYTE b_CycleMode; + double d_TimingInterval; + DWORD dw_ConfigReg; + }s_ChronoModuleInfo; + + /***********************/ + /* Pulse encoder infos */ + /***********************/ + + struct + { + struct + { + BYTE b_PulseEncoderInit; + }s_PulseEncoderInfo [4]; + DWORD dw_SetRegister; + DWORD dw_ControlRegister; + DWORD dw_StatusRegister; + }s_PulseEncoderModuleInfo; + + /********************/ + /* Tor conter infos */ + /********************/ + + struct + { + struct + { + BYTE b_TorCounterInit; + BYTE b_TimingUnit; + BYTE b_InterruptEnable; + double d_TimingInterval; + ULONG ul_RealTimingInterval; + }s_TorCounterInfo [2]; + BYTE b_PCIInputClock; + }s_TorCounterModuleInfo; + + /*************/ + /* PWM infos */ + /*************/ + + struct + { + struct + { + BYTE b_PWMInit; + BYTE b_TimingUnit; + BYTE b_InterruptEnable; + double d_LowTiming; + double d_HighTiming; + ULONG ul_RealLowTiming; + ULONG ul_RealHighTiming; + }s_PWMInfo [2]; + BYTE b_ClockSelection; + }s_PWMModuleInfo; + + /*************/ + /* ETM infos */ + /*************/ + + struct + { + struct + { + BYTE b_ETMEnable; + BYTE b_ETMInterrupt; + }s_ETMInfo [2]; + BYTE b_ETMInit; + BYTE b_TimingUnit; + BYTE b_ClockSelection; + double d_TimingInterval; + ULONG ul_Timing; + }s_ETMModuleInfo; + + /*************/ + /* CDA infos */ + /*************/ + + struct + { + BYTE b_CDAEnable; + BYTE b_CDAInterrupt; + BYTE b_CDAInit; + BYTE b_FctSelection; + BYTE b_CDAReadFIFOOverflow; + }s_CDAModuleInfo; + + }str_ModuleInfo; +// Private structure for the addi_apci3120 driver + +typedef struct{ + + INT iobase; + INT i_IobaseAmcc; // base+size for AMCC chip + INT i_IobaseAddon; //addon base address + INT i_IobaseReserved; + struct pcilst_struct *amcc; // ptr too AMCC data + UINT master; // master capable + BYTE allocated; // we have blocked card + BYTE b_ValidDriver;// driver is ok + BYTE b_AiContinuous; // we do unlimited AI + UINT ui_AiActualScan; //how many scans we finished + UINT ui_AiBufferPtr;// data buffer ptr in samples + UINT ui_AiNbrofChannels;// how many channels is measured + UINT ui_AiScanLength;// Length of actual scanlist + UINT ui_AiActualScanPosition; // position in actual scan + PUINT pui_AiChannelList; // actual chanlist + UINT ui_AiChannelList[32]; // actual chanlist + UINT ui_AiReadData[32]; + UINT ui_AiTimer0; //Timer Constant for Timer0 + UINT ui_AiTimer1; //Timer constant for Timer1 + UINT ui_AiFlags; + UINT ui_AiDataLength; + sampl_t *AiData; // Pointer to sample data + UINT ui_AiNbrofScans;// number of scans to do + USHORT us_UseDma; // To use Dma or not + BYTE b_DmaDoubleBuffer;// we can use double buffering + UINT ui_DmaActualBuffer; // which buffer is used now + ULONG ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer + ULONG ul_DmaBufferHw[2]; // hw address of DMA buff + UINT ui_DmaBufferSize[2];// size of dma buffer in bytes + UINT ui_DmaBufferUsesize[2];// which size e may now used for transfer + UINT ui_DmaBufferSamples[2];// size in samples + UINT ui_DmaBufferPages[2];// number of pages in buffer + BYTE b_DigitalOutputRegister; // Digital Output Register + BYTE b_OutputMemoryStatus; + BYTE b_AnalogInputChannelNbr; // Analog input channel Nbr + BYTE b_AnalogOutputChannelNbr;// Analog input Output Nbr + BYTE b_TimerSelectMode; // Contain data written at iobase + 0C + BYTE b_ModeSelectRegister; // Contain data written at iobase + 0E + USHORT us_OutputRegister; // Contain data written at iobase + 0 + BYTE b_InterruptState; + BYTE b_TimerInit; // Specify if InitTimerWatchdog was load + BYTE b_TimerStarted; // Specify if timer 2 is running or not + BYTE b_Timer2Mode; // Specify the timer 2 mode + BYTE b_Timer2Interrupt;//Timer2 interrupt enable or disable + BYTE b_AiCyclicAcquisition;// indicate cyclic acquisition + BYTE b_InterruptMode; // eoc eos or dma + BYTE b_EocEosInterrupt; // Enable disable eoc eos interrupt + UINT ui_EocEosConversionTime; + BYTE b_ExttrigEnable; // To enable or disable external trigger + struct task_struct *tsk_Current; // Pointer to the current process + + + + // Hardware board infos for 1710 + + struct + { + UINT ui_Address; // Board address + UINT ui_FlashAddress; + BYTE b_InterruptNbr; // Board interrupt number + BYTE b_SlotNumber; // PCI slot number + BYTE b_BoardVersion; + DWORD dw_MolduleConfiguration [4]; // Module configuration + }s_BoardInfos; + + + /*******************/ + /* Interrupt infos */ + /*******************/ + + + struct + { + ULONG ul_InterruptOccur; /* 0 : No interrupt occur */ + /* > 0 : Interrupt occur */ + UINT ui_Read; /* Read FIFO */ + UINT ui_Write; /* Write FIFO */ + struct + { + BYTE b_OldModuleMask; + ULONG ul_OldInterruptMask; /* Interrupt mask */ + ULONG ul_OldCounterLatchValue; /* Interrupt counter value */ + }s_FIFOInterruptParameters [APCI1710_SAVE_INTERRUPT]; + }s_InterruptParameters; + + str_ModuleInfo s_ModuleInfo [4]; + + } addi_private; + + +static unsigned short pci_list_builded=0; /* set to 1 when list of card is known */ + + + + + + + +//Function declarations + +static int i_ADDI_Attach(comedi_device *dev,comedi_devconfig *it); +static int i_ADDI_Detach(comedi_device *dev); +static int i_ADDI_Reset(comedi_device *dev); + +static void v_ADDI_Interrupt(int irq, void *d, struct pt_regs *regs); +static int i_ADDIDATA_InsnReadEeprom(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + + diff --git a/comedi/drivers/addi-data/addi_eeprom.c b/comedi/drivers/addi-data/addi_eeprom.c new file mode 100644 index 00000000..72c0d318 --- /dev/null +++ b/comedi/drivers/addi-data/addi_eeprom.c @@ -0,0 +1,884 @@ + + +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : addi_eeprom.c | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : | Date : | + +-----------------------------------------------------------------------+ + | Description : ADDI EEPROM Module | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + + + + + + + + +#define NVCMD_BEGIN_READ (0x7 << 5 ) // nvRam begin read command +#define NVCMD_LOAD_LOW (0x4 << 5 ) // nvRam load low command +#define NVCMD_LOAD_HIGH (0x5 << 5 ) // nvRam load high command +#define EE76_CMD_LEN 13 // bits in instructions +#define EE_READ 0x0180 // 01 1000 0000 read instruction + +#define WORD unsigned short +#define DWORD unsigned int +#define PWORD unsigned short * +#define PDWORD unsigned int * + + + + +#define EEPROM_DIGITALINPUT 0 +#define EEPROM_DIGITALOUTPUT 1 +#define EEPROM_ANALOGINPUT 2 +#define EEPROM_ANALOGOUTPUT 3 +#define EEPROM_TIMER 4 +#define EEPROM_WATCHDOG 5 +#define EEPROM_TIMER_WATCHDOG_COUNTER 10 + +struct str_Functionality +{ + BYTE b_Type; + WORD w_Address; +}; + + +typedef struct +{ + WORD w_HeaderSize; + BYTE b_Nfunctions; + struct str_Functionality s_Functions[7]; +}str_MainHeader; + + + +typedef struct +{ + WORD w_Nchannel; + BYTE b_Interruptible; + WORD w_NinterruptLogic; +}str_DigitalInputHeader; + +typedef struct +{ + WORD w_Nchannel; +}str_DigitalOutputHeader; + +// used for timer as well as watchdog + +typedef struct +{ + WORD w_HeaderSize; + BYTE b_Resolution; + BYTE b_Mode; // in case of Watchdog it is functionality + WORD w_MinTiming; + BYTE b_TimeBase; +}str_TimerDetails; +typedef struct +{ + + WORD w_Ntimer; + str_TimerDetails s_TimerDetails[4]; // supports 4 timers +}str_TimerMainHeader; + + +typedef struct +{ + WORD w_Nchannel; + BYTE b_Resolution; + }str_AnalogOutputHeader ; + +typedef struct +{ + WORD w_Nchannel; + WORD w_MinConvertTiming; + WORD w_MinDelayTiming; + BYTE b_HasDma; + BYTE b_Resolution; +} str_AnalogInputHeader; + + /*****************************************/ + /* Read Header Functions */ + /*****************************************/ + +INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,comedi_device *dev); + +INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_DigitalInputHeader *s_Header); + +INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_DigitalOutputHeader *s_Header); + +INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_TimerMainHeader *s_Header); + +INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_AnalogOutputHeader *s_Header); + +INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_AnalogInputHeader *s_Header); + + /******************************************/ + /* Eeprom Specific Functions */ + /******************************************/ +WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_EepromStartAddress); +VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress); +VOID v_EepromClock76(DWORD dw_Address,DWORD dw_RegisterValue); +VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress); +VOID v_EepromSendCommand76(DWORD dw_Address,DWORD dw_EepromCommand,BYTE b_DataLengthInBits); +VOID v_EepromCs76Read(DWORD dw_Address,WORD w_offset,PWORD pw_Value); + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : WORD w_EepromReadWord | +| (WORD w_PCIBoardEepromAddress, | +| PCHAR pc_PCIChipInformation, | +| WORD w_EepromStartAddress) | ++----------------------------------------------------------------------------+ +| Task : Read from eepromn a word | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| PCHAR pc_PCIChipInformation : PCI Chip Type. | +| | +| WORD w_EepromStartAddress : Selected eeprom address | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : Read word value from eeprom | ++----------------------------------------------------------------------------+ +*/ + +WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_EepromStartAddress) +{ + BYTE b_Counter = 0; + BYTE b_ReadByte = 0; + BYTE b_ReadLowByte = 0; + BYTE b_ReadHighByte = 0; + BYTE b_SelectedAddressLow = 0; + BYTE b_SelectedAddressHigh = 0; + WORD w_ReadWord = 0; + + + /**************************/ + /* Test the PCI chip type */ + /**************************/ + + + if ((!strcmp(pc_PCIChipInformation, "S5920")) || + (!strcmp(pc_PCIChipInformation, "S5933"))) + { + + for (b_Counter=0; b_Counter<2; b_Counter++) + { + b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256; //Read the low 8 bit part + b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256; //Read the high 8 bit part + + /************************************/ + /* Select the load low address mode */ + /************************************/ + outb(NVCMD_LOAD_LOW,w_PCIBoardEepromAddress + 0x3F); + + + /****************/ + /* Wait on busy */ + /****************/ + v_EepromWaitBusy (w_PCIBoardEepromAddress); + + /************************/ + /* Load the low address */ + /************************/ + outb(b_SelectedAddressLow,w_PCIBoardEepromAddress + 0x3E); + + + /****************/ + /* Wait on busy */ + /****************/ + v_EepromWaitBusy (w_PCIBoardEepromAddress); + + /*************************************/ + /* Select the load high address mode */ + /*************************************/ + outb(NVCMD_LOAD_HIGH,w_PCIBoardEepromAddress + 0x3F); + + + /****************/ + /* Wait on busy */ + /****************/ + v_EepromWaitBusy (w_PCIBoardEepromAddress); + + /*************************/ + /* Load the high address */ + /*************************/ + outb(b_SelectedAddressHigh,w_PCIBoardEepromAddress +0x3E); + + + /****************/ + /* Wait on busy */ + /****************/ + v_EepromWaitBusy (w_PCIBoardEepromAddress); + + /************************/ + /* Select the READ mode */ + /************************/ + outb(NVCMD_BEGIN_READ,w_PCIBoardEepromAddress + 0x3F); + + + /****************/ + /* Wait on busy */ + /****************/ + v_EepromWaitBusy (w_PCIBoardEepromAddress); + + /*****************************/ + /* Read data into the EEPROM */ + /*****************************/ + b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E); + + + /****************/ + /* Wait on busy */ + /****************/ + + v_EepromWaitBusy (w_PCIBoardEepromAddress); + + /*********************************/ + /* Select the upper address part */ + /*********************************/ + + if(b_Counter==0) + { + b_ReadLowByte=b_ReadByte; + } // if(b_Counter==0) + else + { + b_ReadHighByte=b_ReadByte; + } // if(b_Counter==0) + } // for (b_Counter=0; b_Counter<2; b_Counter++) + + w_ReadWord=(b_ReadLowByte | (((WORD) b_ReadHighByte) * 256)); + + } // end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) + if (!strcmp(pc_PCIChipInformation, "93C76")) + { + /*************************************/ + /* Read 16 bit from the EEPROM 93C76 */ + /*************************************/ + + v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress, &w_ReadWord); + } + + return (w_ReadWord); + } + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : VOID v_EepromWaitBusy | +| (WORD w_PCIBoardEepromAddress) | ++----------------------------------------------------------------------------+ +| Task : Wait the busy flag from PCI controller | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom base address | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : - | ++----------------------------------------------------------------------------+ +*/ + +VOID v_EepromWaitBusy(WORD w_PCIBoardEepromAddress) + { + BYTE b_EepromBusy = 0; + + do + { + /*************/ + /* IMPORTANT */ + /*************/ + + /************************************************************************/ + /* An error has been written in the AMCC 5933 book at the page B-13*/ + /* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and */ + /* the operator register is AMCC_OP_REG_MCSR+3*/ + /* WORD read EEPROM=0x8000 andAMCC_OP_REG_MCSR+2 */ + /* DWORD read EEPROM=0x80000000 and AMCC_OP_REG_MCSR */ + /************************************************************************/ + b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F); + b_EepromBusy = b_EepromBusy &0x80; + } while(b_EepromBusy == 0x80); + + } + + + +/* ++---------------------------------------------------------------------------------+ +| Function Name : VOID v_EepromClock76(DWORD dw_Address, | +| DWORD dw_RegisterValue) | ++---------------------------------------------------------------------------------+ +| Task : This function sends the clocking sequence to the EEPROM. | ++---------------------------------------------------------------------------------+ +| Input Parameters : DWORD dw_Address : PCI eeprom base address | +| DWORD dw_RegisterValue : PCI eeprom register value to write.| ++---------------------------------------------------------------------------------+ +| Output Parameters : - | ++---------------------------------------------------------------------------------+ +| Return Value : - | ++---------------------------------------------------------------------------------+ +*/ + +VOID v_EepromClock76(DWORD dw_Address,DWORD dw_RegisterValue) + { + + /************************/ + /* Set EEPROM clock Low */ + /************************/ + outl(dw_RegisterValue & 0x6,dw_Address); + + /***************/ + /* Wait 0.1 ms */ + /***************/ + udelay(100); + + /*************************/ + /* Set EEPROM clock High */ + /*************************/ + outl(dw_RegisterValue | 0x1,dw_Address); + + /***************/ + /* Wait 0.1 ms */ + /***************/ + udelay(100); + + } + +/* ++---------------------------------------------------------------------------------+ +| Function Name : VOID v_EepromSendCommand76(DWORD dw_Address, | +| DWORD dw_EepromCommand, | +| BYTE b_DataLengthInBits) | ++---------------------------------------------------------------------------------+ +| Task : This function sends a Command to the EEPROM 93C76. | ++---------------------------------------------------------------------------------+ +| Input Parameters : DWORD dw_Address : PCI eeprom base address | +| DWORD dw_EepromCommand : PCI eeprom command to write. | +| BYTE b_DataLengthInBits : PCI eeprom command data length. | ++---------------------------------------------------------------------------------+ +| Output Parameters : - | ++---------------------------------------------------------------------------------+ +| Return Value : - | ++---------------------------------------------------------------------------------+ +*/ + +VOID v_EepromSendCommand76(DWORD dw_Address,DWORD dw_EepromCommand,BYTE b_DataLengthInBits) + { + CHAR c_BitPos = 0; + DWORD dw_RegisterValue = 0; + + + /*****************************/ + /* Enable EEPROM Chip Select */ + /*****************************/ + dw_RegisterValue = 0x2; + + /********************************************************************/ + /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ + /********************************************************************/ + outl(dw_RegisterValue,dw_Address); + + + /***************/ + /* Wait 0.1 ms */ + /***************/ + udelay(100); + + + /*******************************************/ + /* Send EEPROM command - one bit at a time */ + /*******************************************/ + for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--) + { + + /**********************************/ + /* Check if current bit is 0 or 1 */ + /**********************************/ + if (dw_EepromCommand & (1 << c_BitPos)) + { + /***********/ + /* Write 1 */ + /***********/ + + dw_RegisterValue = dw_RegisterValue | 0x4; + } + else + { + /***********/ + /* Write 0 */ + /***********/ + + dw_RegisterValue = dw_RegisterValue & 0x3; + } + + /*********************/ + /* Write the command */ + /*********************/ + outl(dw_RegisterValue,dw_Address); + + + /***************/ + /* Wait 0.1 ms */ + /***************/ + udelay(100); + + + /****************************/ + /* Trigger the EEPROM clock */ + /****************************/ + v_EepromClock76(dw_Address, dw_RegisterValue); + + } + + } + +/* ++---------------------------------------------------------------------------------+ +| Function Name : VOID v_EepromCs76Read(DWORD dw_Address, | +| WORD w_offset, | +| PWORD pw_Value) | ++---------------------------------------------------------------------------------+ +| Task : This function read a value from the EEPROM 93C76. | ++---------------------------------------------------------------------------------+ +| Input Parameters : DWORD dw_Address : PCI eeprom base address | +| WORD w_offset : Offset of the adress to read | +| PWORD pw_Value : PCI eeprom 16 bit read value. | ++---------------------------------------------------------------------------------+ +| Output Parameters : - | ++---------------------------------------------------------------------------------+ +| Return Value : - | ++---------------------------------------------------------------------------------+ +*/ + +VOID v_EepromCs76Read(DWORD dw_Address,WORD w_offset, PWORD pw_Value) + { + CHAR c_BitPos = 0; + DWORD dw_RegisterValue = 0; + DWORD dw_RegisterValueRead = 0; + + + /*************************************************/ + /* Send EEPROM read command and offset to EEPROM */ + /*************************************************/ + v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2), EE76_CMD_LEN); + + /*******************************/ + /* Get the last register value */ + /*******************************/ + dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2; + + /*****************************/ + /* Set the 16-bit value of 0 */ + /*****************************/ + *pw_Value = 0; + + /************************/ + /* Get the 16-bit value */ + /************************/ + for (c_BitPos = 0; c_BitPos < 16; c_BitPos++) + { + + /****************************/ + /* Trigger the EEPROM clock */ + /****************************/ + v_EepromClock76(dw_Address, dw_RegisterValue); + + /**********************/ + /* Get the result bit */ + /**********************/ + dw_RegisterValueRead = inl(dw_Address); + + /***************/ + /* Wait 0.1 ms */ + /***************/ + udelay(100); + + /***************************************/ + /* Get bit value and shift into result */ + /***************************************/ + if (dw_RegisterValueRead & 0x8) + { + + /**********/ + /* Read 1 */ + /**********/ + *pw_Value = (*pw_Value << 1) | 0x1; + } + else + { + /**********/ + /* Read 0 */ + /**********/ + *pw_Value = (*pw_Value << 1); + + } + } + + /*************************/ + /* Clear all EEPROM bits */ + /*************************/ + dw_RegisterValue = 0x0; + + /********************************************************************/ + /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ + /********************************************************************/ + outl(dw_RegisterValue,dw_Address); + + /***************/ + /* Wait 0.1 ms */ + /***************/ + udelay(100); + + } + + + + /******************************************/ + /* EEPROM HEADER READ FUNCTIONS */ + /******************************************/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress, | +| PCHAR pc_PCIChipInformation,comedi_device *dev) | ++----------------------------------------------------------------------------+ +| Task : Read from eeprom Main Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| PCHAR pc_PCIChipInformation : PCI Chip Type. | +| | +| comedi_device *dev : comedi device structure | +| pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ + + +INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,comedi_device *dev) +{ + WORD w_Temp,i,w_Count=0; + UINT ui_Temp; + str_MainHeader s_MainHeader; + str_DigitalInputHeader s_DigitalInputHeader; + str_DigitalOutputHeader s_DigitalOutputHeader; + //str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; + str_AnalogOutputHeader s_AnalogOutputHeader; + str_AnalogInputHeader s_AnalogInputHeader; + + // Read size + s_MainHeader.w_HeaderSize = w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+8); + + // Read nbr of functionality + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+10); + s_MainHeader.b_Nfunctions =(BYTE)w_Temp & 0x00FF; + + // Read functionality details + for(i=0;ii_NbrDiChannel=s_DigitalInputHeader.w_Nchannel; + break; + + case EEPROM_DIGITALOUTPUT: + i_EepromReadDigitalOutputHeader(w_PCIBoardEepromAddress,pc_PCIChipInformation, + s_MainHeader.s_Functions[i].w_Address,&s_DigitalOutputHeader); + this_board->i_NbrDoChannel=s_DigitalOutputHeader.w_Nchannel; + ui_Temp=0xffffffff; + this_board->i_DoMaxdata= ui_Temp >>(32 - this_board->i_NbrDoChannel); + break; + + case EEPROM_ANALOGINPUT: + i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress,pc_PCIChipInformation, + s_MainHeader.s_Functions[i].w_Address,&s_AnalogInputHeader); + this_board->i_NbrAiChannel=s_AnalogInputHeader.w_Nchannel; + this_board->i_Dma=s_AnalogInputHeader.b_HasDma; + this_board->ui_MinAcquisitiontimeNs=(UINT)s_AnalogInputHeader.w_MinConvertTiming * 1000; + this_board->ui_MinDelaytimeNs =(UINT)s_AnalogInputHeader.w_MinDelayTiming * 1000; + ui_Temp=0xffff; + this_board->i_AiMaxdata = ui_Temp >> (16 - s_AnalogInputHeader.b_Resolution); + break; + + case EEPROM_ANALOGOUTPUT: + i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress,pc_PCIChipInformation, + s_MainHeader.s_Functions[i].w_Address,&s_AnalogOutputHeader); + this_board->i_NbrAoChannel=s_AnalogOutputHeader.w_Nchannel; + ui_Temp=0xffff; + this_board->i_AoMaxdata= ui_Temp >>(16 - s_AnalogOutputHeader.b_Resolution); + break; + + case EEPROM_TIMER: + this_board->i_Timer=1;//Timer subdevice present + break; + + case EEPROM_WATCHDOG: + this_board->i_Timer=1; //Timer subdevice present + break; + + case EEPROM_TIMER_WATCHDOG_COUNTER: + this_board->i_Timer=1; //Timer subdevice present + } + } + + return 0; +} + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadDigitalInputHeader(WORD | +| w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation, | +| WORD w_Address,str_DigitalInputHeader *s_Header) | +| | ++----------------------------------------------------------------------------+ +| Task : Read Digital Input Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| PCHAR pc_PCIChipInformation : PCI Chip Type. | +| | +| str_DigitalInputHeader *s_Header: Digita Input Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ +INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_DigitalInputHeader *s_Header) +{ + WORD w_Temp; + + // read nbr of channels + s_Header->w_Nchannel=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+6); + + // interruptible or not + w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+8); + s_Header->b_Interruptible=(BYTE) (w_Temp>>7)& 0x01; + +// How many interruptible logic + s_Header->w_NinterruptLogic=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+10); + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadDigitalOutputHeader(WORD | +| w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation, | +| WORD w_Address,str_DigitalOutputHeader *s_Header) | +| | ++----------------------------------------------------------------------------+ +| Task : Read Digital Output Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| PCHAR pc_PCIChipInformation : PCI Chip Type. | +| | +| str_DigitalOutputHeader *s_Header: Digital Output Header| +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ +INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_DigitalOutputHeader *s_Header) +{ +// Read Nbr channels + s_Header->w_Nchannel=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+6); +return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, | +| PCHAR pc_PCIChipInformation,WORD w_Address, | +| str_TimerMainHeader *s_Header) | ++----------------------------------------------------------------------------+ +| Task : Read Timer or Watchdog Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| PCHAR pc_PCIChipInformation : PCI Chip Type. | +| | +| str_TimerMainHeader *s_Header: Timer Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ +INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_TimerMainHeader *s_Header) +{ + +WORD i,w_Size=0,w_Temp; + + +//Read No of Timer +s_Header->w_Ntimer=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+6); +//Read header size + +for(i=0;iw_Ntimer;i++) +{ + s_Header->s_TimerDetails[i].w_HeaderSize=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+8+w_Size+0); + w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+8+w_Size+2) ; + + //Read Resolution + s_Header->s_TimerDetails[i].b_Resolution=(BYTE)(w_Temp>>10)&0x3F; + + //Read Mode + s_Header->s_TimerDetails[i].b_Mode =(BYTE) (w_Temp>>4)&0x3F; + + w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+8+w_Size+4) ; + + //Read MinTiming + s_Header->s_TimerDetails[i].w_MinTiming =(w_Temp>>6)&0x3FF; + + //Read Timebase + s_Header->s_TimerDetails[i].b_TimeBase =(BYTE)(w_Temp)&0x3F; + w_Size += s_Header->s_TimerDetails[i].w_HeaderSize; +} + +return 0; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadAnlogOutputHeader(WORD | +| w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation, | +| WORD w_Address,str_AnalogOutputHeader *s_Header) | ++----------------------------------------------------------------------------+ +| Task : Read Nalog Output Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| PCHAR pc_PCIChipInformation : PCI Chip Type. | +| | +| str_AnalogOutputHeader *s_Header:Anlog Output Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ + +INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_AnalogOutputHeader *s_Header) +{ + WORD w_Temp; + // No of channels for 1st hard component + w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+10); + s_Header->w_Nchannel=(w_Temp>>4)& 0x03FF; + // Resolution for 1st hard component + w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+16); + s_Header->b_Resolution=(BYTE)(w_Temp>>8) & 0xFF; + return 0; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadAnlogInputHeader(WORD | +| w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation, | +| WORD w_Address,str_AnalogInputHeader *s_Header) | ++----------------------------------------------------------------------------+ +| Task : Read Nalog Output Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| PCHAR pc_PCIChipInformation : PCI Chip Type. | +| | +| str_AnalogInputHeader *s_Header:Anlog Input Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ + +// Reads only for ONE hardware component +INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress,PCHAR pc_PCIChipInformation,WORD w_Address,str_AnalogInputHeader *s_Header) +{ + WORD w_Temp,w_Offset; + w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+10); + s_Header->w_Nchannel=(w_Temp>>4)& 0x03FF; + s_Header->w_MinConvertTiming=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+16); +s_Header->w_MinDelayTiming=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+30); +w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+20); +s_Header->b_HasDma=(w_Temp>>13) & 0x01; // whether dma present or not + +w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+72);// reading Y +w_Temp=w_Temp & 0x00FF; +if(w_Temp)//Y>0 +{ +w_Offset=74+(2*w_Temp)+(10*(1+(w_Temp/16)));// offset of first analog input single header +w_Offset= w_Offset+2; // resolution +} +else//Y=0 +{ +w_Offset=74; +w_Offset= w_Offset+2; // resolution +} + +// read Resolution +w_Temp=w_EepromReadWord(w_PCIBoardEepromAddress,pc_PCIChipInformation,0x100+w_Address+w_Offset); +s_Header->b_Resolution=w_Temp & 0x001F;// last 5 bits + +return 0; +} diff --git a/comedi/drivers/addi-data/amcc_s5933_58.h b/comedi/drivers/addi-data/amcc_s5933_58.h new file mode 100644 index 00000000..6a67cbd1 --- /dev/null +++ b/comedi/drivers/addi-data/amcc_s5933_58.h @@ -0,0 +1,438 @@ +/* + Modified by umesh on 16th may 2001 + Modified by sarath on 22nd may 2001 +*/ + + + +/* + comedi/drivers/amcc_s5933_v_58.h + + Stuff for AMCC S5933 PCI Controller + + Author: Michal Dobes + + Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver + made by Andrea Cisternino + 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 +#include + +#ifdef PCI_SUPPORT_VER1 +#error Sorry, no support for 2.1.55 and older! :-(((( +#endif + +/***********Added by sarath for compatibility with APCI3120 + +*************************/ + +#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 // written on base0 + +#define AMWEN_ENABLE 0x02 // added for step 6 dma written on base2 +#define A2P_FIFO_WRITE_ENABLE 0x01 + +#define AGCSTS_TC_ENABLE 0x10000000 // Added for transfer count enable bit + +// ADDON RELATED ADDITIONS +// Constant + #define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00 + #define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200 + #define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L + #define APCI3120_AMWEN_ENABLE 0x02 + #define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01 + #define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L + #define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L + #define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L + #define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0 + #define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0 + #define APCI3120_DISABLE_BUS_MASTER_PCI 0x0 + + + // ADD_ON ::: this needed since apci supports 16 bit interface to add on + #define APCI3120_ADD_ON_AGCSTS_LOW 0x3C + #define APCI3120_ADD_ON_AGCSTS_HIGH APCI3120_ADD_ON_AGCSTS_LOW + 2 + #define APCI3120_ADD_ON_MWAR_LOW 0x24 + #define APCI3120_ADD_ON_MWAR_HIGH APCI3120_ADD_ON_MWAR_LOW + 2 + #define APCI3120_ADD_ON_MWTC_LOW 0x058 + #define APCI3120_ADD_ON_MWTC_HIGH APCI3120_ADD_ON_MWTC_LOW + 2 + +// AMCC + #define APCI3120_AMCC_OP_MCSR 0x3C + #define APCI3120_AMCC_OP_REG_INTCSR 0x38 + +/*******from here all upward definitions are added by sarath */ + + + +/****************************************************************************/ +/* AMCC Operation Register Offsets - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_OMB1 0x00 +#define AMCC_OP_REG_OMB2 0x04 +#define AMCC_OP_REG_OMB3 0x08 +#define AMCC_OP_REG_OMB4 0x0c +#define AMCC_OP_REG_IMB1 0x10 +#define AMCC_OP_REG_IMB2 0x14 +#define AMCC_OP_REG_IMB3 0x18 +#define AMCC_OP_REG_IMB4 0x1c +#define AMCC_OP_REG_FIFO 0x20 +#define AMCC_OP_REG_MWAR 0x24 +#define AMCC_OP_REG_MWTC 0x28 +#define AMCC_OP_REG_MRAR 0x2c +#define AMCC_OP_REG_MRTC 0x30 +#define AMCC_OP_REG_MBEF 0x34 +#define AMCC_OP_REG_INTCSR 0x38 +#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* INT source */ +#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */ +#define AMCC_OP_REG_MCSR 0x3c +#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */ +#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */ + +#define AMCC_FIFO_DEPTH_DWORD 8 +#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32)) + +/****************************************************************************/ +/* AMCC Operation Registers Size - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_SIZE 64 /* in bytes */ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - Add-on */ +/****************************************************************************/ + +#define AMCC_OP_REG_AIMB1 0x00 +#define AMCC_OP_REG_AIMB2 0x04 +#define AMCC_OP_REG_AIMB3 0x08 +#define AMCC_OP_REG_AIMB4 0x0c +#define AMCC_OP_REG_AOMB1 0x10 +#define AMCC_OP_REG_AOMB2 0x14 +#define AMCC_OP_REG_AOMB3 0x18 +#define AMCC_OP_REG_AOMB4 0x1c +#define AMCC_OP_REG_AFIFO 0x20 +#define AMCC_OP_REG_AMWAR 0x24 +#define AMCC_OP_REG_APTA 0x28 +#define AMCC_OP_REG_APTD 0x2c +#define AMCC_OP_REG_AMRAR 0x30 +#define AMCC_OP_REG_AMBEF 0x34 +#define AMCC_OP_REG_AINT 0x38 +#define AMCC_OP_REG_AGCSTS 0x3c +#define AMCC_OP_REG_AMWTC 0x58 +#define AMCC_OP_REG_AMRTC 0x5c + +/****************************************************************************/ +/* AMCC - Add-on General Control/Status Register */ +/****************************************************************************/ + +#define AGCSTS_CONTROL_MASK 0xfffff000 +#define AGCSTS_NV_ACC_MASK 0xe0000000 +#define AGCSTS_RESET_MASK 0x0e000000 +#define AGCSTS_NV_DA_MASK 0x00ff0000 +#define AGCSTS_BIST_MASK 0x0000f000 +#define AGCSTS_STATUS_MASK 0x000000ff +#define AGCSTS_TCZERO_MASK 0x000000c0 +#define AGCSTS_FIFO_ST_MASK 0x0000003f + +#define AGCSTS_RESET_MBFLAGS 0x08000000 +#define AGCSTS_RESET_P2A_FIFO 0x04000000 +#define AGCSTS_RESET_A2P_FIFO 0x02000000 +#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO) + +#define AGCSTS_A2P_TCOUNT 0x00000080 +#define AGCSTS_P2A_TCOUNT 0x00000040 + +#define AGCSTS_FS_P2A_EMPTY 0x00000020 +#define AGCSTS_FS_P2A_HALF 0x00000010 +#define AGCSTS_FS_P2A_FULL 0x00000008 + +#define AGCSTS_FS_A2P_EMPTY 0x00000004 +#define AGCSTS_FS_A2P_HALF 0x00000002 +#define AGCSTS_FS_A2P_FULL 0x00000001 + +/****************************************************************************/ +/* AMCC - Add-on Interrupt Control/Status Register */ +/****************************************************************************/ + +#define AINT_INT_MASK 0x00ff0000 +#define AINT_SEL_MASK 0x0000ffff +#define AINT_IS_ENSEL_MASK 0x00001f1f + +#define AINT_INT_ASSERTED 0x00800000 +#define AINT_BM_ERROR 0x00200000 +#define AINT_BIST_INT 0x00100000 + +#define AINT_RT_COMPLETE 0x00080000 +#define AINT_WT_COMPLETE 0x00040000 + +#define AINT_OUT_MB_INT 0x00020000 +#define AINT_IN_MB_INT 0x00010000 + +#define AINT_READ_COMPL 0x00008000 +#define AINT_WRITE_COMPL 0x00004000 + +#define AINT_OMB_ENABLE 0x00001000 +#define AINT_OMB_SELECT 0x00000c00 +#define AINT_OMB_BYTE 0x00000300 + +#define AINT_IMB_ENABLE 0x00000010 +#define AINT_IMB_SELECT 0x0000000c +#define AINT_IMB_BYTE 0x00000003 + +/* Enable Bus Mastering */ +#define EN_A2P_TRANSFERS 0x00000400 +/* FIFO Flag Reset */ +#define RESET_A2P_FLAGS 0x04000000L +/* FIFO Relative Priority */ +#define A2P_HI_PRIORITY 0x00000100L +/* Identify Interrupt Sources */ +#define ANY_S593X_INT 0x00800000L +#define READ_TC_INT 0x00080000L +#define WRITE_TC_INT 0x00040000L +#define IN_MB_INT 0x00020000L +#define MASTER_ABORT_INT 0x00100000L +#define TARGET_ABORT_INT 0x00200000L +#define BUS_MASTER_INT 0x00200000L + +/****************************************************************************/ + +struct pcilst_struct{ + struct pcilst_struct *next; + int used; + struct pci_dev *pcidev; + unsigned short vendor; + unsigned short device; + unsigned int master; + unsigned char pci_bus; + unsigned char pci_slot; + unsigned char pci_func; + unsigned int io_addr[5]; + unsigned int irq; +}; + +struct pcilst_struct *amcc_devices; // ptr to root list of all amcc devices + +/****************************************************************************/ + +void v_pci_card_list_init(unsigned short pci_vendor, char display); +void v_pci_card_list_cleanup(unsigned short pci_vendor); +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, unsigned short device_id); +int i_find_free_pci_card_by_position(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot, struct pcilst_struct **card); +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot); + +int i_pci_card_alloc(struct pcilst_struct *amcc); +int i_pci_card_free(struct pcilst_struct *amcc); +void v_pci_card_list_display(void); +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, unsigned char *pci_func, + unsigned short *io_addr, unsigned short *irq, unsigned short *master); + +/****************************************************************************/ + +/* build list of amcc cards in this system */ +void v_pci_card_list_init(unsigned short pci_vendor, char display) +{ + struct pci_dev *pcidev; + struct pcilst_struct *amcc,*last; + int i; + + amcc_devices=NULL; + last=NULL; + +#if LINUX_VERSION_CODE < 0x020300 + for(pcidev=pci_devices;pcidev;pcidev=pcidev->next){ +#else + pci_for_each_dev(pcidev){ +#endif + if(pcidev->vendor==pci_vendor){ + amcc=kmalloc(sizeof(*amcc),GFP_KERNEL); + memset(amcc,0,sizeof(*amcc)); + + amcc->pcidev=pcidev; + if (last) { last->next=amcc; } + else { amcc_devices=amcc; } + last=amcc; + +#if LINUX_VERSION_CODE < 0x020300 + amcc->vendor=pcidev->vendor; + amcc->device=pcidev->device; + amcc->master=pcidev->master; + amcc->pci_bus=pcidev->bus->number; + amcc->pci_slot=PCI_SLOT(pcidev->devfn); + amcc->pci_func=PCI_FUNC(pcidev->devfn); + for (i=0;i<5;i++) + amcc->io_addr[i]=pcidev->base_address[i] & ~3UL; + amcc->irq=pcidev->irq; +#else + amcc->vendor=pcidev->vendor; + amcc->device=pcidev->device; +#if 0 + amcc->master=pcidev->master; // how get this information under 2.4 kernels? +#endif + amcc->pci_bus=pcidev->bus->number; + amcc->pci_slot=PCI_SLOT(pcidev->devfn); + amcc->pci_func=PCI_FUNC(pcidev->devfn); + for (i=0;i<5;i++) + amcc->io_addr[i]=pcidev->resource[i].start & ~3UL; + amcc->irq=pcidev->irq; +#endif + + } + } + + if (display) v_pci_card_list_display(); +} + +/****************************************************************************/ +/* free up list of amcc cards in this system */ +void v_pci_card_list_cleanup(unsigned short pci_vendor) +{ + struct pcilst_struct *amcc,*next; + + for(amcc=amcc_devices;amcc;amcc=next){ + next=amcc->next; + kfree(amcc); + } + + amcc_devices=NULL; +} + +/****************************************************************************/ +/* find first unused card with this device_id */ +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, unsigned short device_id) +{ + struct pcilst_struct *amcc,*next; + + for (amcc=amcc_devices;amcc;amcc=next) { + next=amcc->next; + if ((!amcc->used)&&(amcc->device==device_id)&&(amcc->vendor==vendor_id)) return amcc; + + } + + return NULL; +} + +/****************************************************************************/ +/* find card on requested position */ +int i_find_free_pci_card_by_position(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot, struct pcilst_struct **card) +{ + struct pcilst_struct *amcc,*next; + + *card=NULL; + for (amcc=amcc_devices;amcc;amcc=next) { + next=amcc->next; + if ((amcc->vendor==vendor_id)&&(amcc->device==device_id)&&(amcc->pci_bus==pci_bus)&&(amcc->pci_slot==pci_slot)) { + if (!(amcc->used)) { + *card=amcc; + return 0; // ok, card is found + } else { + rt_printk(" - \nCard on requested position is used b:s %d:%d!\n",pci_bus,pci_slot); + return 2; // card exist but is used + } + } + } + + return 1; // no card found +} + +/****************************************************************************/ +/* mark card as used */ +int i_pci_card_alloc(struct pcilst_struct *amcc) +{ + if (!amcc) return -1; + + if (amcc->used) return 1; + amcc->used=1; + return 0; +} + +/****************************************************************************/ +/* mark card as free */ +int i_pci_card_free(struct pcilst_struct *amcc) +{ + if (!amcc) return -1; + + if (!amcc->used) return 1; + amcc->used=0; + return 0; +} + +/****************************************************************************/ +/* display list of found cards */ +void v_pci_card_list_display(void) +{ + struct pcilst_struct *amcc,*next; + + printk("List of pci cards\n"); + printk("bus:slot:func vendor device master io_amcc io_daq irq used\n"); + + for (amcc=amcc_devices;amcc;amcc=next) { + next=amcc->next; + printk("%2d %2d %2d 0x%4x 0x%4x %3s 0x%4x 0x%4x %2d %2d\n", + amcc->pci_bus,amcc->pci_slot,amcc->pci_func,amcc->vendor,amcc->device,amcc->master?"yes":"no", + amcc->io_addr[0],amcc->io_addr[2],amcc->irq,amcc->used); + + } +} + +/****************************************************************************/ +/* return all card information for driver */ +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, unsigned char *pci_func, + unsigned short *io_addr, unsigned short *irq, unsigned short *master) +{ + int i; + + if (!amcc) return -1; + *pci_bus=amcc->pci_bus; + *pci_slot=amcc->pci_slot; + *pci_func=amcc->pci_func; + for (i=0;i<5;i++) + io_addr[i]=amcc->io_addr[i]; + *irq=amcc->irq; + *master=amcc->master; + return 0; +} + +/****************************************************************************/ +/* select and alloc card */ +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot) +{ + struct pcilst_struct *card; + + if ((pci_bus<1)&(pci_slot<1)) { // use autodetection + if ((card=ptr_find_free_pci_card_by_device(vendor_id,device_id))==NULL) { + rt_printk(" - Unused card not found in system!\n"); + return NULL; + } + } else { + switch (i_find_free_pci_card_by_position(vendor_id,device_id,pci_bus,pci_slot,&card)) { + case 1: + rt_printk(" - Card not found on requested position b:s %d:%d!\n",pci_bus,pci_slot); + return NULL; + case 2: + rt_printk(" - Card on requested position is used b:s %d:%d!\n",pci_bus,pci_slot); + return NULL; + } + } + + + if (i_pci_card_alloc(card)!=0) { + rt_printk(" - Can't allocate card!\n"); + return NULL; + } + + return card; +} + +#endif + + + diff --git a/comedi/drivers/addi-data/hwdrv_APCI1710.c b/comedi/drivers/addi-data/hwdrv_APCI1710.c new file mode 100644 index 00000000..5acb77f0 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_APCI1710.c @@ -0,0 +1,1077 @@ + #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" + +int i_APCI1710_Reset(comedi_device *dev); +VOID v_APCI1710_Interrupt(int irq, void *d, struct pt_regs *regs) ; +//for 1710 + + int i_APCI1710_Reset(comedi_device *dev) +{ + int ret; + DWORD dw_Dummy; + + /*********************************/ + /* Read all module configuration */ + /*********************************/ + ret=inl(devpriv->s_BoardInfos.ui_Address+60); + devpriv->s_BoardInfos.dw_MolduleConfiguration [0]=ret; + + ret=inl(devpriv->s_BoardInfos.ui_Address+124); + devpriv->s_BoardInfos.dw_MolduleConfiguration [1]=ret; + + ret=inl(devpriv->s_BoardInfos.ui_Address+188); + devpriv->s_BoardInfos.dw_MolduleConfiguration [2]=ret; + + ret=inl(devpriv->s_BoardInfos.ui_Address+252); + devpriv->s_BoardInfos.dw_MolduleConfiguration [3]=ret; + + // outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60); + outl(0x83838383,devpriv->s_BoardInfos.ui_Address+0x60); + + // Enable the interrupt for the controler + dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address+ 0x38); + outl(dw_Dummy | 0x2000,devpriv->s_BoardInfos.ui_Address+0x38); + + return 0; +} + + +/* ++----------------------------------------------------------------------------+ +| Function's Name : __VOID__ v_APCI1710_InterruptFunction | +| (BYTE b_Interrupt, __CPPARGS) | ++----------------------------------------------------------------------------+ +| Task : APCI-1710 interrupt function | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE b_Interrupt : Interrupt number | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 : OK | +| -1 : Error | ++----------------------------------------------------------------------------+ +*/ + + + + + +VOID v_APCI1710_Interrupt(int irq, void *d, struct pt_regs *regs) +{ + comedi_device *dev = d; + comedi_subdevice *s = dev->subdevices + 0; + BYTE b_ModuleCpt = 0; + BYTE b_InterruptFlag = 0; + BYTE b_PWMCpt = 0; + BYTE b_ETMCpt = 0; + BYTE b_TorCounterCpt = 0; + BYTE b_PulseIncoderCpt = 0; + UINT ui_16BitValue; + ULONG ul_InterruptLatchReg; + ULONG ul_LatchRegisterValue; + ULONG ul_82X54InterruptStatus; + ULONG ul_StatusRegister; + + str_ModuleInfo * ps_ModuleInfo; + + printk("APCI1710 Interrupt\n"); + for (b_ModuleCpt = 0; b_ModuleCpt < 4; b_ModuleCpt ++, ps_ModuleInfo ++) + { + + /**************************/ + /* 1199/0225 to 0100/0226 */ + /**************************/ + ps_ModuleInfo = &devpriv->s_ModuleInfo [b_ModuleCpt]; + + + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModuleCpt] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) + { + + //printk("TIMER Interrupt Occurred\n"); + ul_82X54InterruptStatus= inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if ((ul_82X54InterruptStatus & ps_ModuleInfo-> + s_82X54ModuleInfo. + b_InterruptMask) != 0) + { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = (ul_82X54InterruptStatus & ps_ModuleInfo-> + s_82X54ModuleInfo. + b_InterruptMask) << 4; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = 0; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + } // if ((ul_82X54InterruptStatus & 0x7) != 0) + } // 82X54 timer + + + + + + /***************************/ + /* Test if increm. counter */ + /***************************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModuleCpt] & 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) + { + + ul_InterruptLatchReg=inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModuleCpt)); + + /*********************/ + /* Test if interrupt */ + /*********************/ + + if ((ul_InterruptLatchReg & 0x22) && (ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & 0x80)) + { + /************************************/ + /* Test if strobe latch I interrupt */ + /************************************/ + + if (ul_InterruptLatchReg & 2) + { + ul_LatchRegisterValue=inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModuleCpt)); + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 1UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + + } + + /*************************************/ + /* Test if strobe latch II interrupt */ + /*************************************/ + + if (ul_InterruptLatchReg & 0x20) + { + + ul_LatchRegisterValue=inl(devpriv->s_BoardInfos. + ui_Address + 8 + (64 * b_ModuleCpt)); + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 2UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + } + } + + + ul_InterruptLatchReg=inl(devpriv-> s_BoardInfos. + ui_Address + 24 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if index interrupt */ + /***************************/ + + if (ul_InterruptLatchReg & 0x8) + { + ps_ModuleInfo-> + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInterruptOccur = 1; + + if (ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & APCI1710_INDEX_AUTO_MODE) + { + + outl(ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4,devpriv-> + s_BoardInfos. + ui_Address + 20 + (64 * b_ModuleCpt)); + } + + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if ((ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & APCI1710_ENABLE_INDEX_INT) == APCI1710_ENABLE_INDEX_INT) + { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 4UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + } + } + + /*****************************/ + /* Test if compare interrupt */ + /*****************************/ + + if (ul_InterruptLatchReg & 0x10) + { + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if ((ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & APCI1710_ENABLE_COMPARE_INT) == APCI1710_ENABLE_COMPARE_INT) + { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 8UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + + } + } + + /*******************************************/ + /* Test if frequency measurement interrupt */ + /*******************************************/ + + if (ul_InterruptLatchReg & 0x20) + { + /*******************/ + /* Read the status */ + /*******************/ + + ul_StatusRegister=inl(devpriv->s_BoardInfos. + ui_Address + 32 + (64 * b_ModuleCpt)); + + /******************/ + /* Read the value */ + /******************/ + + + ul_LatchRegisterValue=inl(devpriv->s_BoardInfos. + ui_Address + 28 + (64 * b_ModuleCpt)); + + switch ((ul_StatusRegister >> 1) & 3) + { + case 0: + /*************************/ + /* Test the counter mode */ + /*************************/ + + if ((devpriv-> + s_ModuleInfo [b_ModuleCpt]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER) + { + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & 0xFFFFU) != 0) + { + ui_16BitValue = (UINT) ul_LatchRegisterValue & 0xFFFFU; + ul_LatchRegisterValue = (ul_LatchRegisterValue & 0xFFFF0000UL) | (0xFFFFU - ui_16BitValue); + } + + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & 0xFFFF0000UL) != 0) + { + ui_16BitValue = (UINT) ((ul_LatchRegisterValue >> 16) & 0xFFFFU); + ul_LatchRegisterValue = (ul_LatchRegisterValue & 0xFFFFUL) | ((0xFFFFU - ui_16BitValue) << 16); + } + } + else + { + if (ul_LatchRegisterValue != 0) + { + ul_LatchRegisterValue = 0xFFFFFFFFUL - ul_LatchRegisterValue; + } + } + break; + + case 1: + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & 0xFFFF0000UL) != 0) + { + ui_16BitValue = (UINT) ((ul_LatchRegisterValue >> 16) & 0xFFFFU); + ul_LatchRegisterValue = (ul_LatchRegisterValue & 0xFFFFUL) | ((0xFFFFU - ui_16BitValue) << 16); + } + break; + + case 2: + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & 0xFFFFU) != 0) + { + ui_16BitValue = (UINT) ul_LatchRegisterValue & 0xFFFFU; + ul_LatchRegisterValue = (ul_LatchRegisterValue & 0xFFFF0000UL) | (0xFFFFU - ui_16BitValue); + } + break; + } + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 0x10000UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + + + } + } // Incremental counter + + + + + + + /***************/ + /* Test if CDA */ + /***************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModuleCpt] & 0xFFFF0000UL) == APCI1710_CDA) + { + /******************************************/ + /* Test if CDA enable and functionality 0 */ + /******************************************/ + + if ((devpriv-> + s_ModuleInfo [b_ModuleCpt]. + s_CDAModuleInfo. + b_CDAEnable == APCI1710_ENABLE) && (devpriv-> + s_ModuleInfo [b_ModuleCpt]. + s_CDAModuleInfo. + b_FctSelection == 0)) + { + /****************************/ + /* Get the interrupt status */ + /****************************/ + + + ul_StatusRegister=inl(devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModuleCpt)); + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if (ul_StatusRegister & 1) + { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 0x80000UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = 0; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + + /**********************/ + /* Call user function */ + /**********************/ + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + } // if (ul_StatusRegister & 1) + + } + } // CDA + + + /***********************/ + /* Test if PWM counter */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModuleCpt] & 0xFFFF0000UL) == APCI1710_PWM) + { + for (b_PWMCpt = 0; b_PWMCpt < 2; b_PWMCpt ++) + { + /*************************************/ + /* Test if PWM interrupt initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModuleCpt]. + s_PWMModuleInfo. + s_PWMInfo [b_PWMCpt]. + b_InterruptEnable == APCI1710_ENABLE) + { + /*****************************/ + /* Read the interrupt status */ + /*****************************/ + + ul_StatusRegister=inl(devpriv->s_BoardInfos. + ui_Address + 16 + (20 * b_PWMCpt) + (64 * b_ModuleCpt)); + + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if (ul_StatusRegister & 0x1) + { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 0x4000UL << b_PWMCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + + } // if (ul_StatusRegister & 0x1) + } // if (APCI1710_ENABLE) + } // for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++) + } // PWM counter + + + + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModuleCpt] & 0xFFFF0000UL) == APCI1710_TOR_COUNTER) + { + for (b_TorCounterCpt = 0; b_TorCounterCpt < 2; b_TorCounterCpt ++) + { + /*************************************/ + /* Test if tor interrupt initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo [b_ModuleCpt]. + s_TorCounterModuleInfo. + s_TorCounterInfo [b_TorCounterCpt]. + b_InterruptEnable == APCI1710_ENABLE) + { + /*****************************/ + /* Read the interrupt status */ + /*****************************/ + + + ul_StatusRegister=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (16 * b_TorCounterCpt) + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if (ul_StatusRegister & 0x1) + { + /******************************/ + /* Read the tor counter value */ + /******************************/ + + + ul_LatchRegisterValue=inl(devpriv->s_BoardInfos. + ui_Address + 0 + (16 * b_TorCounterCpt) + (64 * b_ModuleCpt)); + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 0x1000UL << b_TorCounterCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + /**********************/ + /* Call user function */ + /**********************/ + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + } // if (ul_StatusRegister & 0x1) + } // if (APCI1710_ENABLE) + } // for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++) + } // Tor counter + + + + + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModuleCpt] & 0xFFFF0000UL) == APCI1710_CHRONOMETER) + { + + //printk("APCI1710 Chrono Interrupt\n"); + /*****************************/ + /* Read the interrupt status */ + /*****************************/ + + + ul_InterruptLatchReg=inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if ((ul_InterruptLatchReg & 0x8) == 0x8) + { + /****************************/ + /* Clear the interrupt flag */ + /****************************/ + + + outl(0,devpriv->s_BoardInfos. + ui_Address + 32 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if continuous mode */ + /***************************/ + + if (ps_ModuleInfo-> + s_ChronoModuleInfo. + b_CycleMode == APCI1710_ENABLE) + { + /********************/ + /* Clear the status */ + /********************/ + + + outl(0,devpriv->s_BoardInfos. + ui_Address + 36 + (64 * b_ModuleCpt)); + } + + /*************************/ + /* Read the timing value */ + /*************************/ + + + ul_LatchRegisterValue=inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModuleCpt)); + + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if (ps_ModuleInfo-> + s_ChronoModuleInfo. + b_InterruptMask) + { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 0x80; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + } + } + } // Chronometer + + + + /*************************/ + /* Test if pulse encoder */ + /*************************/ + + if ((devpriv-> + s_BoardInfos. + dw_MolduleConfiguration [b_ModuleCpt] & 0xFFFF0000UL) == APCI1710_PULSE_ENCODER) + { + /****************************/ + /* Read the status register */ + /****************************/ + + + ul_StatusRegister=inl(devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModuleCpt)); + + if (ul_StatusRegister & 0xF) + { + for (b_PulseIncoderCpt = 0; b_PulseIncoderCpt < 4; b_PulseIncoderCpt ++) + { + /*************************************/ + /* Test if pulse encoder initialised */ + /*************************************/ + + if ((ps_ModuleInfo-> + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo [b_PulseIncoderCpt]. + b_PulseEncoderInit == 1) && + (((ps_ModuleInfo-> + s_PulseEncoderModuleInfo. + dw_SetRegister >> b_PulseIncoderCpt) & 1) == 1) && + (((ul_StatusRegister >> (b_PulseIncoderCpt)) & 1) == 1)) + { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 0x100UL << b_PulseIncoderCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur ++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + + } + } + } + }//pulse encoder + + } + return ; + +} + diff --git a/comedi/drivers/addi-data/hwdrv_APCI1710.h b/comedi/drivers/addi-data/hwdrv_APCI1710.h new file mode 100644 index 00000000..9d0777c4 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_APCI1710.h @@ -0,0 +1,78 @@ + + + + + +#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 INT int + #define UINT unsigned int + #define BYTE unsigned char + #define CHAR char + #define LONG long + #define ULONG unsigned long + #define VOID void + #define PINT int * + #define PUINT unsigned int * + #define PBYTE unsigned char * + #define PCHAR char * + #define PLONG long * + #define PULONG unsigned long * + #define DWORD unsigned long + #define WORD unsigned short + + #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 + + comedi_lrange range_apci1710_ttl={ 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1) + } +}; + + + comedi_lrange range_apci1710_ssi={ 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1) + } +}; + +comedi_lrange range_apci1710_inccpt={ 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1) + } +}; diff --git a/comedi/drivers/addi-data/hwdrv_apci035.c b/comedi/drivers/addi-data/hwdrv_apci035.c new file mode 100644 index 00000000..8d08c4f4 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci035.c @@ -0,0 +1,600 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci035.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 10.12.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-035 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci035.h" +INT i_WatchdogNbr=0; +INT i_Temp=0; +INT i_Flag=1; +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_ConfigTimerWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Configure As Timer | +| 1 Configure As Watchdog | + data[1] : Watchdog number +| data[2] : Time base Unit | +| data[3] : Reload Value | + data[4] : External Trigger | + 1:Enable + 0:Disable + data[5] :External Trigger Level + 00 Trigger Disabled + 01 Trigger Enabled (Low level) + 10 Trigger Enabled (High Level) + 11 Trigger Enabled (High/Low level) + data[6] : External Gate | + 1:Enable + 0:Disable + data[7] : External Gate level + 00 Gate Disabled + 01 Gate Enabled (Low level) + 10 Gate Enabled (High Level) + data[8] :Warning Relay + 1: ENABLE + 0: DISABLE + data[9] :Warning Delay available + data[10] :Warning Relay Time unit + data[11] :Warning Relay Time Reload value + data[12] :Reset Relay + 1 : ENABLE + 0 : DISABLE + data[13] :Interrupt + 1 : ENABLE + 0 : DISABLE + +| ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ConfigTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_Status=0; +UINT ui_Command=0; +UINT ui_Mode=0; +i_Temp=0; +devpriv->tsk_Current=current; +devpriv->b_TimerSelectMode=data[0]; +i_WatchdogNbr=data[1]; +if(data[0]==0) + { + ui_Mode=2; + } +else + { + ui_Mode=0; + } +//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +ui_Command=0; +//ui_Command = ui_Command & 0xFFFFF9FEUL; +outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +ui_Command=0; +ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +/************************/ +/* Set the reload value */ +/************************/ +outl( data[3],devpriv->iobase+((i_WatchdogNbr-1)*32) + 4); +/*********************/ +/* Set the time unit */ +/*********************/ +outl(data[2],devpriv->iobase+((i_WatchdogNbr-1)*32) + 8); +if (data[0] == ADDIDATA_TIMER) + { + + + /******************************/ + /* Set the mode : */ + /* - Disable the hardware */ + /* - Disable the counter mode */ + /* - Disable the warning */ + /* - Disable the reset */ + /* - Enable the timer mode */ + /* - Set the timer mode */ + /******************************/ + + + ui_Command = (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL; + + }//if (data[0] == ADDIDATA_TIMER) + else + { + if(data[0]==ADDIDATA_WATCHDOG) + { + + /******************************/ + /* Set the mode : */ + /* - Disable the hardware */ + /* - Disable the counter mode */ + /* - Disable the warning */ + /* - Disable the reset */ + /* - Disable the timer mode */ + /******************************/ + + + ui_Command = ui_Command & 0xFFF819E2UL; + + } + else + { + printk("\n The parameter for Timer/watchdog selection is in error\n"); + return -EINVAL; + } + } +outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +ui_Command=0; +ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +/********************************/ +/* Disable the hardware trigger */ +/********************************/ +ui_Command = ui_Command & 0xFFFFF89FUL; + if (data[4] == ADDIDATA_ENABLE) + { + /**********************************/ + /* Set the hardware trigger level */ + /**********************************/ + ui_Command = ui_Command | ( data[5] << 5); + } +outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +ui_Command=0; +ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +/*****************************/ +/* Disable the hardware gate */ +/*****************************/ +ui_Command = ui_Command & 0xFFFFF87FUL; +if (data[6] == ADDIDATA_ENABLE) + { +/*******************************/ +/* Set the hardware gate level */ +/*******************************/ + ui_Command = ui_Command |( data[7] << 7); + } +outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +ui_Command=0; +ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +/*******************************/ +/* Disable the hardware output */ +/*******************************/ +ui_Command = ui_Command & 0xFFFFF9FBUL; +/*********************************/ +/* Set the hardware output level */ +/*********************************/ +ui_Command = ui_Command |( data[8] << 2); +outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +if(data[9]==ADDIDATA_ENABLE) + { + /************************/ + /* Set the reload value */ + /************************/ + outl (data[11],devpriv->iobase+((i_WatchdogNbr-1)*32) + 24); + /**********************/ + /* Set the time unite */ + /**********************/ + outl(data[10],devpriv->iobase+((i_WatchdogNbr-1)*32)+ 28); + } + + ui_Command=0; + ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + /*******************************/ + /* Disable the hardware output */ + /*******************************/ + ui_Command = ui_Command & 0xFFFFF9F7UL; + /*********************************/ + /* Set the hardware output level */ + /*********************************/ + ui_Command = ui_Command |( data[12] << 3); + outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + /*************************************/ + /** Enable the watchdog interrupt **/ + /*************************************/ +ui_Command=0; +ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); +/*******************************/ +/* Set the interrupt selection */ +/*******************************/ +ui_Status =inl(devpriv->iobase+((i_WatchdogNbr-1)*32) + 16); + +ui_Command = (ui_Command & 0xFFFFF9FDUL) | ( data[13] << 1); +outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + +return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_StartStopWriteTimerWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Selected Timer , or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 - Stop Selected Timer/Watchdog | +| 1 - Start Selected Timer/Watchdog | +| 2 - Trigger Selected Timer/Watchdog | +| 3 - Stop All Timer/Watchdog | +| 4 - Start All Timer/Watchdog | +| 5 - Trigger All Timer/Watchdog | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Command = 0; + INT i_Count=0; + if (data[0]==1) + { + ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + /**********************/ + /* Start the hardware */ + /**********************/ + ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL; + outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + } // if (data[0]==1) + if(data[0]==2) + { + ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + /***************************/ + /* Set the trigger command */ + /***************************/ + ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL; + outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + } + + if (data[0]==0) //Stop The Watchdog + { + //Stop The Watchdog + ui_Command=0; + //ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + //ui_Command = ui_Command & 0xFFFFF9FEUL; + outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + } // if (data[1]==0) + if(data[0]==3)//stop all Watchdogs + { + ui_Command=0; + for(i_Count=1;i_Count<=4;i_Count++) + { + if(devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + { + ui_Command=0x2UL; + } + else + { + ui_Command = 0x10UL; + } + i_WatchdogNbr=i_Count; + outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32) + 0); + } + } + if(data[0]==4)//start all Watchdogs + { + ui_Command = 0; + for(i_Count=1;i_Count<=4;i_Count++) + { + if(devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + { + ui_Command = 0x1UL; + } + else + { + ui_Command = 0x8UL; + } + i_WatchdogNbr=i_Count; + outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32) + 0); + } + } + if(data[0]==5)//trigger all Watchdogs + { + ui_Command =0; + for(i_Count=1;i_Count<=4;i_Count++) + { + if(devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + { + ui_Command=0x4UL; + } + else + { + ui_Command = 0x20UL; + } + i_WatchdogNbr=i_Count; + outl(ui_Command,devpriv->iobase+((i_WatchdogNbr-1)*32) + 0); + } + i_Temp=1; + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_ReadTimerWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : software trigger status data[1] : hardware trigger status +| data[2] : Software clear status + data[3] : Overflow status data[4] : Timer actual value + + ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ReadTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_Status = 0; // Status register + i_WatchdogNbr=insn->unused[0]; + /******************/ + /* Get the status */ + /******************/ + ui_Status =inl(devpriv->iobase+((i_WatchdogNbr-1)*32) + 16); + /***********************************/ + /* Get the software trigger status */ + /***********************************/ + data[0] = ((ui_Status >> 1) & 1); + /***********************************/ + /* Get the hardware trigger status */ + /***********************************/ + data[1] = ((ui_Status >> 2) & 1); + /*********************************/ + /* Get the software clear status */ + /*********************************/ + data[2] = ((ui_Status >> 3) & 1); + /***************************/ + /* Get the overflow status */ + /***************************/ + data[3] = ((ui_Status >> 0) & 1); + if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + { + data[4]=inl(devpriv->iobase+((i_WatchdogNbr-1)*32) + 0); + + } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI035_ConfigAnalogInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Analog Input Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| data[0] : Warning delay value +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +devpriv->tsk_Current=current; +outl(0x200 | 0, devpriv->iobase+128 + 0x4); +outl(0, devpriv->iobase+128 + 0); +/********************************/ +/* Initialise the warning value */ +/********************************/ +outl(0x300 | 0, devpriv->iobase+128 + 0x4); +outl((data[0] << 8), devpriv->iobase+128 + 0); +outl(0x200000UL , devpriv->iobase+128 + 12); + +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_ReadAnalogInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : Digital Value Of Input | +| | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ReadAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_CommandRegister=0; +/******************/ +/* Set the start */ +/******************/ +ui_CommandRegister =0x80000; + /******************************/ + /* Write the command register */ + /******************************/ +outl(ui_CommandRegister, devpriv->iobase+128 + 8); + +/***************************************/ +/* Read the digital value of the input */ +/***************************************/ +data[0] = inl (devpriv->iobase+ 128 + 28); +return insn->n; +} + + + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_Reset(comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task :Resets the registers of the card | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_Reset(comedi_device *dev) +{ +INT i_Count=0; +for(i_Count=1;i_Count<=4;i_Count++) + { + i_WatchdogNbr=i_Count; + outl(0x0,devpriv->iobase+((i_WatchdogNbr-1)*32) + 0);//stop all timers + } +outl(0x0 , devpriv->iobase+128 + 12);//Disable the warning delay + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI035_Interrupt | +| (int irq , void *d, struct pt_regs *regs) | ++----------------------------------------------------------------------------+ +| Task : Interrupt processing Routine | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | +| struct pt_regs *regs : structure pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static void v_APCI035_Interrupt(int irq, void *d, struct pt_regs *regs) +{ + 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/comedi/drivers/addi-data/hwdrv_apci035.h b/comedi/drivers/addi-data/hwdrv_apci035.h new file mode 100644 index 00000000..853ad7f9 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci035.h @@ -0,0 +1,124 @@ +// Card Specific information +#define APCI035_BOARD_VENDOR_ID 0x15B8 +#define APCI035_ADDRESS_RANGE 255 + +INT i_TW_Number; +struct +{ + INT i_Gain ; + INT i_Polarity; + INT i_OffsetRange; + INT i_Coupling; + INT i_SingleDiff; + INT i_AutoCalibration; + UINT ui_ReloadValue; + UINT ui_TimeUnitReloadVal; + INT i_Interrupt; + INT i_ModuleSelection; +}Config_Parameters_Main; + + + +//ANALOG INPUT RANGE +comedi_lrange range_apci035_ai={ 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1) + } +}; + +// Timer / Watchdog Related Defines + +#define APCI035_TCW_SYNC_ENABLEDISABLE 0 +#define APCI035_TCW_RELOAD_VALUE 4 +#define APCI035_TCW_TIMEBASE 8 +#define APCI035_TCW_PROG 12 +#define APCI035_TCW_TRIG_STATUS 16 +#define APCI035_TCW_IRQ 20 +#define APCI035_TCW_WARN_TIMEVAL 24 +#define APCI035_TCW_WARN_TIMEBASE 28 + +#define ADDIDATA_TIMER 0 +#define ADDIDATA_WATCHDOG 1 + +#define APCI035_TW1 0 +#define APCI035_TW2 32 +#define APCI035_TW3 64 +#define APCI035_TW4 96 + +#define APCI035_AI_OFFSET 0 +#define APCI035_TEMP 128 +#define APCI035_ALR_SEQ 4 +#define APCI035_START_STOP_INDEX 8 +#define APCI035_ALR_START_STOP 12 +#define APCI035_ALR_IRQ 16 +#define APCI035_EOS 20 +#define APCI035_CHAN_NO 24 +#define APCI035_CHAN_VAL 28 +#define APCI035_CONV_TIME_TIME_BASE 36 +#define APCI035_RELOAD_CONV_TIME_VAL 32 +#define APCI035_DELAY_TIME_TIME_BASE 44 +#define APCI035_RELOAD_DELAY_TIME_VAL 40 +#define ENABLE_EXT_TRIG 1 +#define ENABLE_EXT_GATE 2 +#define ENABLE_EXT_TRIG_GATE 3 + +#define ANALOG_INPUT 0 +#define TEMPERATURE 1 +#define RESISTANCE 2 + +#define ADDIDATA_GREATER_THAN_TEST 0 +#define ADDIDATA_LESS_THAN_TEST 1 + + +#define APCI035_MAXVOLT 2.5 + +#define ADDIDATA_UNIPOLAR 1 +#define ADDIDATA_BIPOLAR 2 + +//ADDIDATA Enable Disable +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + + + + + + +// Hardware Layer functions for Apci035 + + + +// TIMER +// timer value is passed as u seconds +INT i_APCI035_ConfigTimerWatchdog (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI035_StartStopWriteTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI035_ReadTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +//Temperature Related Defines (Analog Input Subdevice) + +INT i_APCI035_ConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI035_ReadAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +//Interrupt +static void v_APCI035_Interrupt(int irq, void *d, struct pt_regs *regs) ; + +//Reset functions +INT i_APCI035_Reset(comedi_device *dev); + + + + + + + + + + diff --git a/comedi/drivers/addi-data/hwdrv_apci1032.c b/comedi/drivers/addi-data/hwdrv_apci1032.c new file mode 100644 index 00000000..cef17cdb --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1032.c @@ -0,0 +1,267 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci1032.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 31.10.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1032 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci1032.h" +#include +//Global variables + UINT ui_InterruptStatus=0 ; + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_ConfigDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures the digital input Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 1 Enable Digital Input Interrupt | +| 0 Disable Digital Input Interrupt | +| data[1] : 0 ADDIDATA Interrupt OR LOGIC | +| : 1 ADDIDATA Interrupt AND LOGIC | +| data[2] : Interrupt mask for the mode 1 | +| data[3] : Interrupt mask for the mode 2 | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1032_ConfigDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_TmpValue; + + ULONG ul_Command1 = 0; + ULONG ul_Command2 = 0; + devpriv->tsk_Current=current; + /*******************************/ + /* Set the digital input logic */ + /*******************************/ + if ( data[0] == ADDIDATA_ENABLE) + { + ul_Command1 = ul_Command1 | data[2]; + ul_Command2 = ul_Command2 | data[3]; + outl (ul_Command1 , devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_MODE1); + outl (ul_Command2 , devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_MODE2); + if (data[1] == ADDIDATA_OR) + { + outl(0x4 ,devpriv->iobase+APCI1032_DIGITAL_IP_IRQ); + ui_TmpValue=inl(devpriv->iobase+APCI1032_DIGITAL_IP_IRQ); + }//if (data[1] == ADDIDATA_OR) + else + { + outl(0x6 ,devpriv->iobase+APCI1032_DIGITAL_IP_IRQ); + }//else if(data[1] == ADDIDATA_OR) + }// if( data[0] == ADDIDATA_ENABLE) + else + { + ul_Command1 = ul_Command1 & 0xFFFF0000; + ul_Command2 = ul_Command2 & 0xFFFF0000; + outl (ul_Command1 , devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_MODE1); + outl (ul_Command2 , devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_MODE2); + outl(0x0 ,devpriv->iobase+APCI1032_DIGITAL_IP_IRQ); + }//else if ( data[0] == ADDIDATA_ENABLE) + + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_Read1DigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1032_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_TmpValue=0; + UINT ui_Channel; + ui_Channel=CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <=31) + { + ui_TmpValue=(UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP); + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> ui_Channel)&0x1 ; + }//if(ui_Channel >= 0 && ui_Channel <=31) + else + { + //comedi_error(dev," \n chan spec wrong\n"); + return -EINVAL; // "sorry channel spec wrong " + }//else if(ui_Channel >= 0 && ui_Channel <=31) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_ReadMoreDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To be Read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1032_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_PortValue=data[0]; + UINT ui_Mask=0; + UINT ui_NoOfChannels; + + ui_NoOfChannels=CR_CHAN(insn->chanspec); + if (data[1]==0) + { + *data=(UINT)inl(devpriv->iobase + APCI1032_DIGITAL_IP ); + switch (ui_NoOfChannels) + { + case 2:ui_Mask=3; + *data=(*data >>(2*ui_PortValue))&ui_Mask; + break; + case 4:ui_Mask=15; + *data=(*data >>(4*ui_PortValue))&ui_Mask; + break; + case 8:ui_Mask=255; + *data=(*data >>(8*ui_PortValue))&ui_Mask; + break; + case 16:ui_Mask=65535; + *data=(*data >>(16*ui_PortValue))&ui_Mask; + break; + case 31: break; + default: + //comedi_error(dev," \nchan spec wrong\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + }//switch(ui_NoOfChannels) + }//if(data[1]==0) + else + { + if (data[1]==1) + { + *data=ui_InterruptStatus; + }//if(data[1]==1) + }//else if(data[1]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI1032_Interrupt | +| (int irq , void *d, struct pt_regs *regs) | ++----------------------------------------------------------------------------+ +| Task : Interrupt handler for the interruptible digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | +| struct pt_regs *regs : structure pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static VOID v_APCI1032_Interrupt(int irq,void* d, struct pt_regs *regs) +{ + comedi_device *dev =d; + + UINT ui_Temp; + //disable the interrupt + ui_Temp=inl(devpriv->iobase+APCI1032_DIGITAL_IP_IRQ); + outl(ui_Temp& APCI1032_DIGITAL_IP_INTERRUPT_DISABLE ,devpriv->iobase+APCI1032_DIGITAL_IP_IRQ); + ui_InterruptStatus=inl(devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_STATUS); + ui_InterruptStatus=ui_InterruptStatus & 0X0000FFFF; + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + outl(ui_Temp ,devpriv->iobase+APCI1032_DIGITAL_IP_IRQ);//enable the interrupt +return; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_Reset(comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1032_Reset(comedi_device *dev) +{ + outl(0x0 ,devpriv->iobase+APCI1032_DIGITAL_IP_IRQ);//disable the interrupts + inl(devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_STATUS);//Reset the interrupt status register + outl (0x0 , devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_MODE1);//Disable the and/or interrupt + outl (0x0 , devpriv->iobase+APCI1032_DIGITAL_IP_INTERRUPT_MODE2); + return 0; +} + + + + + + + + + + diff --git a/comedi/drivers/addi-data/hwdrv_apci1032.h b/comedi/drivers/addi-data/hwdrv_apci1032.h new file mode 100644 index 00000000..8e55bf5c --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1032.h @@ -0,0 +1,59 @@ +/********* Definitions for APCI-1032 card *****/ + +#define APCI1032_BOARD_VENDOR_ID 0x15B8 +#define APCI1032_ADDRESS_RANGE 20 +//DIGITAL INPUT DEFINE + +#define APCI1032_DIGITAL_IP 0 +#define APCI1032_DIGITAL_IP_INTERRUPT_MODE1 4 +#define APCI1032_DIGITAL_IP_INTERRUPT_MODE2 8 +#define APCI1032_DIGITAL_IP_IRQ 16 + +//Digital Input IRQ Function Selection +#define ADDIDATA_OR 0 +#define ADDIDATA_AND 1 + +//Digital Input Interrupt Status +#define APCI1032_DIGITAL_IP_INTERRUPT_STATUS 12 + + + +//Digital Input Interrupt Enable Disable. +#define APCI1032_DIGITAL_IP_INTERRUPT_ENABLE 0x4 +#define APCI1032_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB + + + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + + + + +// Hardware Layer functions for Apci1032 + + +//DI +// for di read + +INT i_APCI1032_ConfigDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +INT i_APCI1032_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +INT i_APCI1032_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + + + + + + +// Interrupt functions..... + +static VOID v_APCI1032_Interrupt(int irq, void *d, struct pt_regs *regs) ; +//Reset +INT i_APCI1032_Reset(comedi_device *dev); + + \ No newline at end of file diff --git a/comedi/drivers/addi-data/hwdrv_apci1500.c b/comedi/drivers/addi-data/hwdrv_apci1500.c new file mode 100644 index 00000000..c4e460a2 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -0,0 +1,2726 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci1500.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Karl Andrade | Date : 13.12.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1500 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ +#include "hwdrv_apci1500.h" + +int i_TimerCounter1Init=0; +int i_TimerCounter2Init=0; +int i_WatchdogCounter3Init=0; +int i_Event1Status=0,i_Event2Status=0; +int i_TimerCounterWatchdogInterrupt=0; +int i_Logic=0,i_CounterLogic=0; +int i_InterruptMask=0; +int i_InputChannel=0; + int i_TimerCounter1Enabled=0, i_TimerCounter2Enabled=0,i_WatchdogCounter3Enabled=0; + + + +/* + +----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigDigitalInputEvent | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : An event can be generated for each port. | +| The first event is related to the first 8 channels | +| (port 1) and the second to the following 6 channels | +| (port 2). An interrupt is generated when one or both | +| events have occurred | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] :Number of the input port on | +| which the event will take place | +| (1 or 2) + data[1] : The event logic for port 1 has | +| three possibilities | +| :0 APCI1500_AND :This logic | +| links | +| the inputs | +| with an AND | +| logic. | +| 1 APCI1500_OR :This logic | +| links | +| the inputs | +| with a | +| OR logic. | +| 2 APCI1500_OR_PRIORITY | +| :This logic | +| links | +| the inputs | +| with a | +| priority | +| OR logic. | +| Input 1 | +| has the | +| highest | +| priority | +| level and | +| input 8 | +| the smallest| +| For the second port the user has| +| 1 possibility: | +| APCI1500_OR :This logic | +| links | +| the inputs | +| with a | +| polarity | +| OR logic | +| data[2] : These 8-character word for port1| +| and 6-character word for port 2 | +| give the mask of the event. | +| Each place gives the state | +| of the input channels and can | +| have one of these six characters| +| | +| 0 : This input must be on 0 | +| 1 : This input must be on 1 | +| 2 : This input reacts to | +| a falling edge | +| 3 : This input reacts to a | +| rising edge | +| 4 : This input reacts to both edges | +| +| 5 : This input is not | +| used for event | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_ConfigDigitalInputEvent(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +int i_PatternPolarity=0,i_PatternTransition=0,i_PatternMask=0; +int i_MaxChannel=0,i_Count=0,i_EventMask=0; +int i_PatternTransitionCount=0,i_RegValue; +int i; + + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Disables the main interrupt on the board */ + /**********************************************/ + outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + if (data[0] == 1) + { + i_MaxChannel = 8; + }// if (data[0] == 1) + else + { + if(data[0]==2) + { + i_MaxChannel = 6; + }// if(data[0]==2) + else + { + printk("\nThe specified port event does not exist\n"); + return -EINVAL; + }//else if(data[0]==2) + }//else if (data[0] == 1) +switch(data[1]) + { + case 0: data[1]= APCI1500_AND; + break; + case 1: data[1]= APCI1500_OR; + break; + case 2: data[1]= APCI1500_OR_PRIORITY; + break; + default:printk("\nThe specified interrupt logic does not exist\n"); + return -EINVAL; + }//switch(data[1]); + +i_Logic=data[1]; +for (i_Count = i_MaxChannel,i=0; i_Count >0;i_Count --,i++) + { + i_EventMask=data[2+i]; + switch(i_EventMask) + { + case 0 : i_PatternMask = i_PatternMask | (1 << (i_MaxChannel-i_Count)); + break; + case 1 : i_PatternMask = i_PatternMask | (1 << (i_MaxChannel-i_Count)); + i_PatternPolarity = i_PatternPolarity |(1 << (i_MaxChannel-i_Count)); + break; + case 2 : i_PatternMask = i_PatternMask |(1 << (i_MaxChannel-i_Count)); + i_PatternTransition = i_PatternTransition |(1 << (i_MaxChannel-i_Count)); + break; + case 3 : i_PatternMask = i_PatternMask | (1 << (i_MaxChannel-i_Count)); + i_PatternPolarity = i_PatternPolarity |(1 << (i_MaxChannel-i_Count)); + i_PatternTransition = i_PatternTransition |(1 << (i_MaxChannel-i_Count)); + break; + case 4 : i_PatternTransition = i_PatternTransition |(1 << (i_MaxChannel-i_Count)); + break; + case 5 : break; + default : printk("\nThe option indicated in the event mask does not exist\n"); + return -EINVAL; + }// switch(i_EventMask) + }//for (i_Count = i_MaxChannel; i_Count >0;i_Count --) + + if (data[0]== 1) + { + /****************************/ + /* Test the interrupt logic */ + /****************************/ + + if (data[1] == APCI1500_AND || + data[1] == APCI1500_OR || + data[1] == APCI1500_OR_PRIORITY) + { + /**************************************/ + /* Tests if a transition was declared */ + /* for a OR PRIORITY logic */ + /**************************************/ + + if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0) + { + /********************************************/ + /* Transition error on an OR PRIORITY logic */ + /********************************************/ + printk("\nTransition error on an OR PRIORITY logic\n"); + return -EINVAL; + }// if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0) + + + + /*************************************/ + /* Tests if more than one transition */ + /* was declared for an AND logic */ + /*************************************/ + + if (data[1]== APCI1500_AND) + { + for (i_Count = 0; i_Count < 8; i_Count++) + { + i_PatternTransitionCount=i_PatternTransitionCount+((i_PatternTransition>>i_Count)&0x1); + + } //for (i_Count = 0; i_Count < 8; i_Count++) + + if (i_PatternTransitionCount > 1) + { + /****************************************/ + /* Transition error on an AND logic */ + /****************************************/ + printk("\n Transition error on an AND logic\n"); + return -EINVAL; + }// if (i_PatternTransitionCount > 1) + }// if (data[1]== APCI1500_AND) + + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port A */ + /******************/ + outb(0xF0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Selects the polarity register of port 1 */ + /**********************************************/ + outb(APCI1500_RW_PORT_A_PATTERN_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternPolarity,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the pattern mask register of */ + /* port 1 */ + /*********************************************/ + outb(APCI1500_RW_PORT_A_PATTERN_MASK,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternMask,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /********************************************/ + /* Selects the pattern transition register */ + /* of port 1 */ + /********************************************/ + outb(APCI1500_RW_PORT_A_PATTERN_TRANSITION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternTransition,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 1 */ + /******************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 1 */ + /******************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Port A new mode */ + /**********************/ + + i_RegValue=(i_RegValue & 0xF9) | data[1]|0x9; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + i_Event1Status=1; + + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port A */ + /*****************/ + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) + else + { + printk("\nThe choice for interrupt logic does not exist\n"); + return -EINVAL; + }// else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) + }// if (data[0]== 1) + + + /************************************/ + /* Test if event setting for port 2 */ + /************************************/ + + if (data[0] == 2) + { + /************************/ + /* Test the event logic */ + /************************/ + + if (data[1] == APCI1500_OR) + { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port B */ + /******************/ + outb(0x74,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the mode specification mask */ + /* register of port B */ + /****************************************/ + outb( APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port B */ + /******************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=i_RegValue & 0xF9; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**********************************/ + /* Selects error channels 1 and 2 */ + /**********************************/ + + i_PatternMask = (i_PatternMask | 0xC0); + i_PatternPolarity = (i_PatternPolarity | 0xC0); + i_PatternTransition = (i_PatternTransition | 0xC0); + + /**********************************************/ + /* Selects the polarity register of port 2 */ + /**********************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb( i_PatternPolarity,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Selects the pattern transition register */ + /* of port 2 */ + /**********************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternTransition,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Selects the pattern Mask register */ + /* of port 2 */ + /**********************************************/ + + outb(APCI1500_RW_PORT_B_PATTERN_MASK,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternMask,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 2 */ + /******************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 2 */ + /******************************************/ + outb( APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=(i_RegValue & 0xF9) | 4; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + i_Event2Status=1; + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port B */ + /*****************/ + + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }// if (data[1] == APCI1500_OR) + else + { + printk("\nThe choice for interrupt logic does not exist\n"); + return -EINVAL; + }//elseif (data[1] == APCI1500_OR) + }//if(data[0]==2) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_StartStopInputEvent | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Allows or disallows a port event | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| lsampl_t *data : Data Pointer to read status | + data[0] :0 Start input event + 1 Stop input event + data[1] :No of port (1 or 2) ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_StartStopInputEvent(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +int i_Event1InterruptStatus=0,i_Event2InterruptStatus=0,i_RegValue; +switch(data[0]) + { + case START : + /*************************/ + /* Tests the port number */ + /*************************/ + + if (data[1] == 1 || data[1] == 2) + { + /***************************/ + /* Test if port 1 selected */ + /***************************/ + + if ( data[1] == 1) + { + /*****************************/ + /* Test if event initialised */ + /*****************************/ + if(i_Event1Status==1) + { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port A */ + /******************/ + outb(0xF0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 1 */ + /***************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Allows the pattern interrupt */ + /*************************************/ + outb(0xC0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port A */ + /*****************/ + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_Event1InterruptStatus=1; + outb(APCI1500_RW_PORT_A_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + }// if(i_Event1Status==1) + else + { + printk("\nEvent 1 not initialised\n"); + return -EINVAL; + }//else if(i_Event1Status==1) + }//if (data[1]==1) + if(data[1]==2) + { + + if(i_Event2Status==1) + { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port B */ + /******************/ + outb(0x74,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 2 */ + /***************************************************/ + outb( APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Allows the pattern interrupt */ + /*************************************/ + outb(0xC0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port B */ + /*****************/ + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_Event2InterruptStatus=1; + }// if(i_Event2Status==1) + else + { + printk("\nEvent 2 not initialised\n"); + return -EINVAL; + }//else if(i_Event2Status==1) + }// if(data[1]==2) + }// if (data[1] == 1 || data[0] == 2) + else + { + printk("\nThe port parameter is in error\n"); + return -EINVAL; + }//else if (data[1] == 1 || data[0] == 2) + + break; + + case STOP : + /*************************/ + /* Tests the port number */ + /*************************/ + + if (data[1] == 1 || data[1] == 2) + { + /***************************/ + /* Test if port 1 selected */ + /***************************/ + + if ( data[1] == 1) + { + /*****************************/ + /* Test if event initialised */ + /*****************************/ + if(i_Event1Status==1) + { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port A */ + /******************/ + outb(0xF0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 1 */ + /***************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Inhibits the pattern interrupt */ + /*************************************/ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port A */ + /*****************/ + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_Event1InterruptStatus=0; + }// if(i_Event1Status==1) + else + { + printk("\nEvent 1 not initialised\n"); + return -EINVAL; + }//else if(i_Event1Status==1) + }//if (data[1]==1) + if(data[1]==2) + { + /*****************************/ + /* Test if event initialised */ + /*****************************/ + if(i_Event2Status==1) + { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port B */ + /******************/ + outb(0x74,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 2 */ + /***************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Inhibits the pattern interrupt */ + /*************************************/ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port B */ + /*****************/ + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_Event2InterruptStatus=0; + }// if(i_Event2Status==1) + else + { + printk("\nEvent 2 not initialised\n"); + return -EINVAL; + }//else if(i_Event2Status==1) + }//if(data[1]==2) + + }// if (data[1] == 1 || data[1] == 2) + else + { + printk("\nThe port parameter is in error\n"); + return -EINVAL; + }//else if (data[1] == 1 || data[1] == 2) + break; + default :printk("\nThe option of START/STOP logic does not exist\n"); + return -EINVAL; + }//switch(data[0]) + +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_Initialisation | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1500_Initialisation(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +int i_DummyRead=0; + /******************/ + /* Software reset */ + /******************/ + i_DummyRead=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_DummyRead=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(1,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the master configuration control register */ + /*****************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data path polarity register of port A */ + outb( APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port A means 1 */ + outb(0xFF,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data direction register of port A */ + outb(APCI1500_RW_PORT_A_DATA_DIRECTION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port A: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port A */ + outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data path polarity register of port B */ + outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* A high level of port B means 1 */ + outb(0x7F,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port B */ + outb(APCI1500_RW_PORT_B_DATA_DIRECTION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb( APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port B: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port B */ + outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the data path polarity register of port C */ + /*****************************************************/ + outb( APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port C means 1 */ + outb(0x9,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port C */ + outb(APCI1500_RW_PORT_C_DATA_DIRECTION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs except channel 1 */ + outb(0x0E,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the special IO register of port C */ + outb( APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes it */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 1 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 1 */ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of timer 1 */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 2 */ + /******************************************************/ + outb( APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 2 */ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates Timer 2 interrupt management: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 3 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of Timer 3 */ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates interrupt management of timer 3: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes all interrupts */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ReadMoreDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To be Read | +| UINT *data : Data Pointer + data[0] : 0 Read a single channel + 1 read a port value + data[1] : port value ++----------------------------------------------------------------------------+ +| Output Parameters : -- data[0] :The read status value ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_PortValue=data[1]; + UINT ui_Mask=0; + UINT ui_Channel; + UINT ui_TmpValue=0; + ui_Channel=CR_CHAN(insn->chanspec); + + + switch(data[0]) + { + case 0: + if (ui_Channel >= 0 && ui_Channel <=15) + { + ui_TmpValue=(UINT) inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP); + *data = (ui_TmpValue >> ui_Channel)&0x1 ; + }//if(ui_Channel >= 0 && ui_Channel <=15) + else + { + printk("\nThe channel specification are in error\n"); + return -EINVAL; // "sorry channel spec wrong " + }//else if(ui_Channel >= 0 && ui_Channel <=15) + break; + case 1: + + *data=(UINT)inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP ); + switch (ui_Channel) + { + case 2:ui_Mask=3; + *data=(*data >>(2*ui_PortValue))&ui_Mask; + break; + case 4:ui_Mask=15; + *data=(*data >>(4*ui_PortValue))&ui_Mask; + break; + case 8:ui_Mask=255; + *data=(*data >>(8*ui_PortValue))&ui_Mask; + break; + case 15: break; + + default: + printk("\nSpecified channel cannot be read \n"); + return -EINVAL; // "sorry channel spec wrong " + break; + }//switch(ui_Channel) + break; + default: + printk("\nThe specified functionality does not exist\n"); + return -EINVAL; + }//switch(data[0]) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigDigitalOutputErrorInterrupt + (comedi_device *dev,comedi_subdevice *s comedi_insn + *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures the digital output memory and the digital + output error interrupt | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| data[0] :1:Memory on | +| 0:Memory off | + data[1] :1 Enable the voltage error interrupt +| :0 Disable the voltage error interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +devpriv->b_OutputMemoryStatus=data[0]; +return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +static UINT ui_Temp=0; +UINT ui_Temp1; + +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + + if(!devpriv->b_OutputMemoryStatus ) + { + ui_Temp=0; + + }//if(!devpriv->b_OutputMemoryStatus ) +if(data[3]==0) + { + if(data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outw(data[0],devpriv->i_IobaseAddon+APCI1500_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=(data[0] << (2*data[2]))|ui_Temp; + break; + + + case 4:data[0]=(data[0] << (4*data[2]))|ui_Temp; + break; + + case 8: + data[0]=(data[0] <<(8*data[2]))|ui_Temp; + break; + + case 15:data[0]=data[0]|ui_Temp; + break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outw(data[0],devpriv->i_IobaseAddon+APCI1500_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==0) +else + { + if(data[3]==1) + { + if(data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<i_IobaseAddon+APCI1500_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2*data[2]))^0xffffffff)& ui_Temp; + break; + + + case 4:data[0]=~data[0]&0xf; + ui_Temp1=15; + ui_Temp1=ui_Temp1<<4*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (4*data[2]))^0xffffffff)&ui_Temp; + break; + + case 8:data[0]=~data[0]&0xff; + ui_Temp1=255; + ui_Temp1=ui_Temp1<<8*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (8*data[2]))^0xffffffff)&ui_Temp; + break; + + case 15:break; + + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outw(data[0],devpriv->i_IobaseAddon+APCI1500_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }//if else data[3]==1) + }//if else data[3]==0) + ui_Temp=data[0]; + return (insn->n);; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device + *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)| +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status data[0] : 2 APCI1500_1_8_KHZ +| 1 APCI1500_3_6_KHZ | +| 0 APCI1500_115_KHZ + data[1] : 0 Counter1/Timer1 + 1 Counter2/Timer2 + 2 Counter3/Watchdog + data[2] : 0 Counter + 1 Timer/Watchdog + data[3] : This parameter has | +| two meanings. | +| - If the counter/timer | +| is used as a counter | +| the limit value of | +| the counter is given | +| | +| - If the counter/timer | +| is used as a timer, | +| the divider factor | +| for the output is | +| given. + data[4] : 0 APCI1500_CONTINUOUS + 1 APCI1500_SINGLE + data[5] : 0 Software Trigger + 1 Hardware Trigger + + data[6] :0 Software gate + 1 Hardware gate + data[7] :0 Interrupt Disable + 1 Interrupt Enable ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +int i_TimerCounterMode,i_MasterConfiguration; + + devpriv->tsk_Current=current; + +//Selection of the input clock +if(data[0]==0||data[0]==1||data[0]==2) + { + outw(data[0],devpriv->i_IobaseAddon+APCI1500_CLK_SELECT); + }// if(data[0]==0||data[0]==1||data[0]==2) +else + { + if(data[0]!=3) + { + printk("\nThe option for input clock selection does not exist\n"); + return -EINVAL; + }// if(data[0]!=3) + }//elseif(data[0]==0||data[0]==1||data[0]==2) + //Select the counter/timer +switch(data[1]) + { + case COUNTER1: + //selecting counter or timer + switch(data[2]) + { + case 0: data[2]=APCI1500_COUNTER ; + break; + case 1: data[2]=APCI1500_TIMER; + break; + default:printk("\nThis choice is not a timer nor a counter\n"); + return -EINVAL; + }// switch(data[2]) + + //Selecting single or continuous mode + switch(data[4]) + { + case 0: data[4]= APCI1500_CONTINUOUS; + break; + case 1: data[4]= APCI1500_SINGLE; + break; + default:printk("\nThis option for single/continuous mode does not exist\n"); + return -EINVAL; + }// switch(data[4]) + + + i_TimerCounterMode = data[2]|data[4]|7; + /*************************/ + /* Test the reload value */ + /*************************/ + + if ((data[3]>= 0) && (data[3] <= 65535)) + { + if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + { + + /************************************************/ + /* Selects the mode register of timer/counter 1 */ + /************************************************/ + outb(APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************/ + /* Writes the new mode */ + /***********************/ + outb(i_TimerCounterMode,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 1 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR1_TIME_CST_LOW,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*************************/ + /* Writes the low value */ + /*************************/ + + outb( data[3],devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 1 */ + /****************************************************/ + + outb( APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**************************/ + /* Writes the high value */ + /**************************/ + + data[3]=data[3]>>8; + outb(data[3],devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Reads the register */ + /**********************/ + + i_MasterConfiguration=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /********************************************************/ + /* Enables timer/counter 1 and triggers timer/counter 1 */ + /********************************************************/ + + i_MasterConfiguration = i_MasterConfiguration | 0x40; + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /********************************/ + /* Writes the new configuration */ + /********************************/ + outb(i_MasterConfiguration,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 1 */ + /****************************************/ + + outb( APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Disable timer/counter 1 */ + /***************************/ + + outb(0x0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 1 */ + /****************************************/ + outb( APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Trigger timer/counter 1 */ + /***************************/ + outb(0x2,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + else + { + printk("\nError in selection of interrupt enable or disable\n"); + return -EINVAL; + }//elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + }// if ((data[3]>= 0) && (data[3] <= 65535)) + else + { + printk("\nError in selection of reload value\n"); + return -EINVAL; + }//else if ((data[3]>= 0) && (data[3] <= 65535)) + i_TimerCounterWatchdogInterrupt=data[7]; + i_TimerCounter1Init=1; + break; + + + + case COUNTER2: //selecting counter or timer + switch(data[2]) + { + case 0: data[2]=APCI1500_COUNTER ; + break; + case 1: data[2]=APCI1500_TIMER; + break; + default:printk("\nThis choice is not a timer nor a counter\n"); + return -EINVAL; + }// switch(data[2]) + + //Selecting single or continuous mode + switch(data[4]) + { + case 0: data[4]= APCI1500_CONTINUOUS; + break; + case 1: data[4]= APCI1500_SINGLE; + break; + default:printk("\nThis option for single/continuous mode does not exist\n"); + return -EINVAL; + }// switch(data[4]) + + //Selecting software or hardware trigger + switch(data[5]) + { + case 0: data[5]= APCI1500_SOFTWARE_TRIGGER ; + break; + case 1: data[5]= APCI1500_HARDWARE_TRIGGER ; + break; + default:printk("\nThis choice for software or hardware trigger does not exist\n"); + return -EINVAL; + }// switch(data[5]) + + //Selecting software or hardware gate + switch(data[6]) + { + case 0: data[6]= APCI1500_SOFTWARE_GATE ; + break; + case 1: data[6]= APCI1500_HARDWARE_GATE ; + break; + default:printk("\nThis choice for software or hardware gate does not exist\n"); + return -EINVAL; + }// switch(data[6]) + + + i_TimerCounterMode=data[2]|data[4]|data[5]|data[6]|7; + + /*************************/ + /* Test the reload value */ + /*************************/ + + if ((data[3]>= 0) && (data[3] <= 65535)) + { + if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + { + + /************************************************/ + /* Selects the mode register of timer/counter 2 */ + /************************************************/ + outb( APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************/ + /* Writes the new mode */ + /***********************/ + outb(i_TimerCounterMode,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 2 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR2_TIME_CST_LOW,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*************************/ + /* Writes the low value */ + /*************************/ + + outb( data[3],devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 2 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**************************/ + /* Writes the high value */ + /**************************/ + + data[3]=data[3]>>8; + outb(data[3],devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Reads the register */ + /**********************/ + + i_MasterConfiguration=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /********************************************************/ + /* Enables timer/counter 2 and triggers timer/counter 2 */ + /********************************************************/ + + i_MasterConfiguration = i_MasterConfiguration | 0x20; + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /********************************/ + /* Writes the new configuration */ + /********************************/ + outb(i_MasterConfiguration,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 2 */ + /****************************************/ + + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Disable timer/counter 2 */ + /***************************/ + + outb(0x0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 2 */ + /****************************************/ + outb( APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Trigger timer/counter 1 */ + /***************************/ + outb(0x2,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + else + { + printk("\nError in selection of interrupt enable or disable\n"); + return -EINVAL; + }//elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + }// if ((data[3]>= 0) && (data[3] <= 65535)) + else + { + printk("\nError in selection of reload value\n"); + return -EINVAL; + }//else if ((data[3]>= 0) && (data[3] <= 65535)) + i_TimerCounterWatchdogInterrupt=data[7]; + i_TimerCounter2Init=1; + break; + + + + + case COUNTER3://selecting counter or watchdog + switch(data[2]) + { + case 0: data[2]=APCI1500_COUNTER ; + break; + case 1: data[2]= APCI1500_WATCHDOG; + break; + default:printk("\nThis choice is not a watchdog nor a counter\n"); + return -EINVAL; + }// switch(data[2]) + + //Selecting single or continuous mode + switch(data[4]) + { + case 0: data[4]= APCI1500_CONTINUOUS; + break; + case 1: data[4]= APCI1500_SINGLE; + break; + default:printk("\nThis option for single/continuous mode does not exist\n"); + return -EINVAL; + }// switch(data[4]) + + + + + //Selecting software or hardware gate + switch(data[6]) + { + case 0: data[6]= APCI1500_SOFTWARE_GATE ; + break; + case 1: data[6]= APCI1500_HARDWARE_GATE ; + break; + default:printk("\nThis choice for software or hardware gate does not exist\n"); + return -EINVAL; + }// switch(data[6]) + + + + /*****************************/ + /* Test if used for watchdog */ + /*****************************/ + + if (data[2] == APCI1500_WATCHDOG) + { + /*****************************/ + /* - Enables the output line */ + /* - Enables retrigger */ + /* - Pulses output */ + /*****************************/ + i_TimerCounterMode=data[2]|data[4]|0x54; + }//if (data[2] == APCI1500_WATCHDOG) + else + { + i_TimerCounterMode=data[2]|data[4]|data[6]|7; + }//elseif (data[2] == APCI1500_WATCHDOG) + /*************************/ + /* Test the reload value */ + /*************************/ + + if ((data[3]>= 0) && (data[3] <= 65535)) + { + if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + { + + /************************************************/ + /* Selects the mode register of watchdog/counter 3 */ + /************************************************/ + outb(APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************/ + /* Writes the new mode */ + /***********************/ + outb(i_TimerCounterMode,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of watchdog/counter 3 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR3_TIME_CST_LOW,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*************************/ + /* Writes the low value */ + /*************************/ + + outb( data[3],devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of watchdog/counter 3 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**************************/ + /* Writes the high value */ + /**************************/ + + data[3]=data[3]>>8; + outb(data[3],devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Reads the register */ + /**********************/ + + i_MasterConfiguration=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /********************************************************/ + /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */ + /********************************************************/ + + i_MasterConfiguration = i_MasterConfiguration | 0x10; + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /********************************/ + /* Writes the new configuration */ + /********************************/ + outb(i_MasterConfiguration,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /********************/ + /* Test if COUNTER */ + /********************/ + if(data[2]==APCI1500_COUNTER) + { + + /*************************************/ + /* Selects the command register of */ + /* watchdog/counter 3 */ + /*************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Disable the watchdog/counter 3 and starts it */ + /*************************************************/ + outb(0x0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*************************************/ + /* Selects the command register of */ + /* watchdog/counter 3 */ + /*************************************/ + + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Trigger the watchdog/counter 3 and starts it */ + /*************************************************/ + outb(0x2,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + }//elseif(data[2]==APCI1500_COUNTER) + + + }//if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + else + { + printk("\nError in selection of interrupt enable or disable\n"); + return -EINVAL; + }//elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + }// if ((data[3]>= 0) && (data[3] <= 65535)) + else + { + printk("\nError in selection of reload value\n"); + return -EINVAL; + }//else if ((data[3]>= 0) && (data[3] <= 65535)) + i_TimerCounterWatchdogInterrupt=data[7]; + i_WatchdogCounter3Init=1; + break; + + default:printk("\nThe specified counter\timer option does not exist\n"); + }//switch(data[1]) +i_CounterLogic=data[2]; +return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_StartStopTriggerTimerCounterWatchdog | +| (comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Start / Stop or trigger the timer counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | + data[0] : 0 Counter1/Timer1 + 1 Counter2/Timer2 + 2 Counter3/Watchdog + data[1] : 0 start + 1 stop + 2 Trigger + data[2] : 0 Counter + 1 Timer/Watchdog ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +int i_CommandAndStatusValue; + +switch(data[0]) + { + case COUNTER1: + switch(data[1]) + { + case START: + if( i_TimerCounter1Init==1) + { + if(i_TimerCounterWatchdogInterrupt==1) + { + i_CommandAndStatusValue = 0xC4;//Enable the interrupt + }// if(i_TimerCounterWatchdogInterrupt==1) + else + { + i_CommandAndStatusValue =0xE4;//disable the interrupt + }//elseif(i_TimerCounterWatchdogInterrupt==1) + /**************************/ + /* Starts timer/counter 1 */ + /**************************/ + i_TimerCounter1Enabled=1; + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_TimerCounter1Init==1) + else + { + printk("\nCounter/Timer1 not configured\n"); + return -EINVAL; + } + break; + + case STOP : + + + /**************************/ + /* Stop timer/counter 1 */ + /**************************/ + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_TimerCounter1Enabled=0; + break; + + case TRIGGER: + if( i_TimerCounter1Init==1) + { + if( i_TimerCounter1Enabled==1) + { + /************************/ + /* Set Trigger and gate */ + /************************/ + + i_CommandAndStatusValue = 0x6; + }//if( i_TimerCounter1Enabled==1) + else + { + /***************/ + /* Set Trigger */ + /***************/ + + i_CommandAndStatusValue = 0x2; + }//elseif(i_TimerCounter1Enabled==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_TimerCounter1Init==1) + else + { + printk("\nCounter/Timer1 not configured\n"); + return -EINVAL; + } + break; + + default :printk("\nThe specified option for start/stop/trigger does not exist\n"); + return -EINVAL; + }//switch(data[1]) + break; + + case COUNTER2: + switch(data[1]) + { + case START: + if( i_TimerCounter2Init==1) + { + if(i_TimerCounterWatchdogInterrupt==1) + { + i_CommandAndStatusValue = 0xC4;//Enable the interrupt + }// if(i_TimerCounterWatchdogInterrupt==1) + else + { + i_CommandAndStatusValue =0xE4;//disable the interrupt + }//elseif(i_TimerCounterWatchdogInterrupt==1) + /**************************/ + /* Starts timer/counter 2 */ + /**************************/ + i_TimerCounter2Enabled=1; + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_TimerCounter2Init==1) + else + { + printk("\nCounter/Timer2 not configured\n"); + return -EINVAL; + } + break; + + case STOP : + + + /**************************/ + /* Stop timer/counter 2 */ + /**************************/ + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x00 ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_TimerCounter2Enabled=0; + break; + case TRIGGER: + if( i_TimerCounter2Init==1) + { + if( i_TimerCounter2Enabled==1) + { + /************************/ + /* Set Trigger and gate */ + /************************/ + + i_CommandAndStatusValue = 0x6; + }//if( i_TimerCounter2Enabled==1) + else + { + /***************/ + /* Set Trigger */ + /***************/ + + i_CommandAndStatusValue = 0x2; + }//elseif(i_TimerCounter2Enabled==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_TimerCounter2Init==1) + else + { + printk("\nCounter/Timer2 not configured\n"); + return -EINVAL; + } + break; + default :printk("\nThe specified option for start/stop/trigger does not exist\n"); + return -EINVAL; + }//switch(data[1]) + break; + case COUNTER3: + switch(data[1]) + { + case START: + if( i_WatchdogCounter3Init==1) + { + + if(i_TimerCounterWatchdogInterrupt==1) + { + i_CommandAndStatusValue = 0xC4;//Enable the interrupt + }// if(i_TimerCounterWatchdogInterrupt==1) + else + { + i_CommandAndStatusValue =0xE4;//disable the interrupt + }//elseif(i_TimerCounterWatchdogInterrupt==1) + /**************************/ + /* Starts Watchdog/counter 3 */ + /**************************/ + i_WatchdogCounter3Enabled=1; + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + }// if( i_WatchdogCounter3init==1) + else + { + printk("\nWatchdog/Counter3 not configured\n"); + return -EINVAL; + } + break; + + case STOP : + + + /**************************/ + /* Stop Watchdog/counter 3 */ + /**************************/ + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x00 ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_WatchdogCounter3Enabled=0; + break; + + case TRIGGER: + switch(data[2]) + { + case 0://triggering counter 3 + if( i_WatchdogCounter3Init==1) + { + if( i_WatchdogCounter3Enabled==1) + { + /************************/ + /* Set Trigger and gate */ + /************************/ + + i_CommandAndStatusValue = 0x6; + }//if( i_WatchdogCounter3Enabled==1) + else + { + /***************/ + /* Set Trigger */ + /***************/ + + i_CommandAndStatusValue = 0x2; + }//elseif(i_WatchdogCounter3Enabled==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_WatchdogCounter3Init==1) + else + { + printk("\nCounter3 not configured\n"); + return -EINVAL; + } + break; + case 1 : + //triggering Watchdog 3 + if( i_WatchdogCounter3Init==1) + { + + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x6 ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_WatchdogCounter3Init==1) + else + { + printk("\nWatchdog 3 not configured\n"); + return -EINVAL; + } + break; + default :printk("\nWrong choice of watchdog/counter3\n"); + return -EINVAL; + }//switch(data[2]) + break; + default:printk("\nThe specified option for start/stop/trigger does not exist\n"); + return -EINVAL; + }//switch(data[1]) + break; + default : printk("\nThe specified choice for counter/watchdog/timer does not exist\n"); + return -EINVAL; + }//switch(data[0]) +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ReadCounterTimerWatchdog | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | + data[0] : 0 Counter1/Timer1 + 1 Counter2/Timer2 + 2 Counter3/Watchdog + ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1500_ReadCounterTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + int i_CommandAndStatusValue; +switch(data[0]) + { + case COUNTER1: + //Read counter/timer1 + if( i_TimerCounter1Init==1) + { + if( i_TimerCounter1Enabled==1) + { + /************************/ + /* Set RCC and gate */ + /************************/ + + i_CommandAndStatusValue = 0xC; + }//if( i_TimerCounter1Init==1) + else + { + /***************/ + /* Set RCC */ + /***************/ + + i_CommandAndStatusValue = 0x8; + }//elseif(i_TimerCounter1Init==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************/ + /* Selects the counter register (high) */ + /***************************************/ + outb(APCI1500_R_CPT_TMR1_VALUE_HIGH,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=data[0]<<8; + data[0]=data[0]&0xff00; + outb(APCI1500_R_CPT_TMR1_VALUE_LOW,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=data[0]|inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_TimerCounter1Init==1) + else + { + printk("\nTimer/Counter1 not configured\n"); + return -EINVAL; + }//elseif( i_TimerCounter1Init==1) + break; + case COUNTER2 : + //Read counter/timer2 + if( i_TimerCounter2Init==1) + { + if( i_TimerCounter2Enabled==1) + { + /************************/ + /* Set RCC and gate */ + /************************/ + + i_CommandAndStatusValue = 0xC; + }//if( i_TimerCounter2Init==1) + else + { + /***************/ + /* Set RCC */ + /***************/ + + i_CommandAndStatusValue = 0x8; + }//elseif(i_TimerCounter2Init==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb( APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************/ + /* Selects the counter register (high) */ + /***************************************/ + outb(APCI1500_R_CPT_TMR2_VALUE_HIGH,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=data[0]<<8; + data[0]=data[0]&0xff00; + outb(APCI1500_R_CPT_TMR2_VALUE_LOW,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=data[0]|inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_TimerCounter2Init==1) + else + { + printk("\nTimer/Counter2 not configured\n"); + return -EINVAL; + }//elseif( i_TimerCounter2Init==1) + break; + case COUNTER3: + //Read counter/watchdog2 + if( i_WatchdogCounter3Init==1) + { + if( i_WatchdogCounter3Enabled==1) + { + /************************/ + /* Set RCC and gate */ + /************************/ + + i_CommandAndStatusValue = 0xC; + }//if( i_TimerCounter2Init==1) + else + { + /***************/ + /* Set RCC */ + /***************/ + + i_CommandAndStatusValue = 0x8; + }//elseif(i_WatchdogCounter3Init==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************/ + /* Selects the counter register (high) */ + /***************************************/ + outb( APCI1500_R_CPT_TMR3_VALUE_HIGH,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=data[0]<<8; + data[0]=data[0]&0xff00; + outb(APCI1500_R_CPT_TMR3_VALUE_LOW,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + data[0]=data[0]|inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }//if( i_WatchdogCounter3Init==1) + else + { + printk("\nWatchdogCounter3 not configured\n"); + return -EINVAL; + }//elseif( i_WatchdogCounter3Init==1) + break; + default : + printk("\nThe choice of timer/counter/watchdog does not exist\n"); + return -EINVAL; + }//switch(data[0]) + + +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ReadInterruptMask | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Read the interrupt mask | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | + + ++----------------------------------------------------------------------------+ +| Output Parameters : -- data[0]:The interrupt mask value data[1]:Channel no ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_ReadInterruptMask(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + data[0]=i_InterruptMask; + data[1]=i_InputChannel; + i_InterruptMask=0; + return insn->n; +} +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigureInterrupt | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Configures the interrupt registers | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer | + + ++----------------------------------------------------------------------------+ +| Output Parameters : -- ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_ConfigureInterrupt(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Status; +int i_RegValue; +int i_Constant; +devpriv->tsk_Current=current; +outl(0x0,devpriv->i_IobaseAmcc+0x38); +if(data[0]==1) + { + i_Constant=0xC0; + }//if(data[0]==1) +else + { + if(data[0]==0) + { + i_Constant=0x00; + }//if{data[0]==0) + else + { + printk("\nThe parameter passed to driver is in error for enabling the voltage interrupt\n"); + return -EINVAL; + }//else if(data[0]==0) + }//elseif(data[0]==1) + + + /*****************************************************/ + /* Selects the mode specification register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*********************************************/ + /* Writes the new configuration (APCI1500_OR) */ + /*********************************************/ + i_RegValue =(i_RegValue & 0xF9) | APCI1500_OR; + + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************/ + /* Authorises the interrupt on the board */ + /*****************************************/ + outb(0xC0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the pattern polarity register of port B */ + /***************************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_Constant,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the pattern transition register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_Constant ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************************/ + /* Selects the pattern mask register of port B */ + /***********************************************/ + outb( APCI1500_RW_PORT_B_PATTERN_MASK,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(i_Constant ,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ + outb( APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb( APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port A */ + /***********************************/ + + i_RegValue=(i_RegValue & 0x0F)| 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port B */ + /***********************************/ + + i_RegValue=(i_RegValue & 0x0F)| 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of timer 1*/ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 1 */ + /***********************************/ + + i_RegValue=(i_RegValue & 0x0F)| 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of timer 2*/ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 2 */ + /***********************************/ + + i_RegValue=(i_RegValue & 0x0F)| 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + + /*****************************************************/ + /* Selects the command and status register of timer 3*/ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb( APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 3 */ + /***********************************/ + + i_RegValue=(i_RegValue & 0x0F)| 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + + /***************************/ + /* Enables the PCI interrupt */ + /*****************************/ + outl(0x3000,devpriv->i_IobaseAmcc+0x38); + ui_Status=inl(devpriv->i_IobaseAmcc+0x10); + ui_Status=inl(devpriv->i_IobaseAmcc+0x38); + outl(0x23000,devpriv->i_IobaseAmcc+0x38); + + +return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI1500_Interrupt | +| (int irq , void *d, struct pt_regs *regs) | ++----------------------------------------------------------------------------+ +| Task : Interrupt handler | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | +| struct pt_regs *regs : structure pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static VOID v_APCI1500_Interrupt(int irq,void* d, struct pt_regs *regs) +{ + + comedi_device *dev =d; + UINT ui_InterruptStatus=0; + int i_RegValue=0; + i_InterruptMask=0; + + /***********************************/ + /* Read the board interrupt status */ + /***********************************/ + ui_InterruptStatus=inl(devpriv->i_IobaseAmcc+0x38); + + /***************************************/ + /* Test if board generated a interrupt */ + /***************************************/ + if ((ui_InterruptStatus & 0x800000) == 0x800000) + { + /************************/ + /* Disable all Interrupt*/ + /************************/ + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + //outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Disables the main interrupt on the board */ + /**********************************************/ + //outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) + { + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port A */ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_InterruptMask=i_InterruptMask | 1; + if(i_Logic==APCI1500_OR_PRIORITY) + { + outb(APCI1500_RW_PORT_A_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************************/ + /* Selects the interrupt vector register of port A */ + /***************************************************/ + outb(APCI1500_RW_PORT_A_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + i_InputChannel = 1 + (i_RegValue >> 1); + + }// if(i_Logic==APCI1500_OR_PRIORITY) + else + { + i_InputChannel=0; + }//elseif(i_Logic==APCI1500_OR_PRIORITY) + }// if ((i_RegValue & 0x60) == 0x60) + + /*****************************************************/ + /* Selects the command and status register of port B*/ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) + { + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port B */ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + printk("\n\n\n"); + /****************/ + /* Reads port B */ + /****************/ + i_RegValue=inb((UINT)devpriv->iobase+APCI1500_Z8536_PORT_B); + + i_RegValue = i_RegValue & 0xC0; + /**************************************/ + /* Tests if this is an external error */ + /**************************************/ + + if (i_RegValue) + { + //Disable the interrupt + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outl(0x0,devpriv->i_IobaseAmcc+0x38); + + + if (i_RegValue & 0x80) + { + i_InterruptMask = i_InterruptMask | 0x40; + }//if (i_RegValue & 0x80) + + if (i_RegValue & 0x40) + { + i_InterruptMask = i_InterruptMask | 0x80; + }//if (i_RegValue & 0x40) + }// if (i_RegValue) + else + { + i_InterruptMask = i_InterruptMask | 2; + }// if (i_RegValue) + }//if ((i_RegValue & 0x60) == 0x60) + + /*****************************************************/ + /* Selects the command and status register of timer 1*/ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) + { + /*****************************************************/ + /* Selects the command and status register of timer 1 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 1*/ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_InterruptMask = i_InterruptMask | 4; + } // if ((i_RegValue & 0x60) == 0x60) + /*****************************************************/ + /* Selects the command and status register of timer 2*/ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) + { + /*****************************************************/ + /* Selects the command and status register of timer 2 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 2*/ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_InterruptMask = i_InterruptMask | 8; + } // if ((i_RegValue & 0x60) == 0x60) + + /*****************************************************/ + /* Selects the command and status register of timer 3*/ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) + { + /*****************************************************/ + /* Selects the command and status register of timer 3 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 3*/ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + if(i_CounterLogic==APCI1500_COUNTER) + { + i_InterruptMask = i_InterruptMask | 0x10; + }//if(i_CounterLogic==APCI1500_COUNTER) + else + { + i_InterruptMask =i_InterruptMask | 0x20; + } + } // if ((i_RegValue & 0x60) == 0x60) + + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + /***********************/ + /* Enable all Interrupts */ + /***********************/ + + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + }// if ((ui_InterruptStatus & 0x800000) == 0x800000) + else + { + printk("\nInterrupt from unknown source\n"); + + }//else if ((ui_InterruptStatus & 0x800000) == 0x800000) +return; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_Reset(comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_Reset(comedi_device *dev) +{ +int i_DummyRead=0; +i_TimerCounter1Init=0; +i_TimerCounter2Init=0; +i_WatchdogCounter3Init=0; +i_Event1Status=0; +i_Event2Status=0; +i_TimerCounterWatchdogInterrupt=0; +i_Logic=0; +i_CounterLogic=0; +i_InterruptMask=0; +i_InputChannel=0;; + i_TimerCounter1Enabled=0; + i_TimerCounter2Enabled=0; +i_WatchdogCounter3Enabled=0; + + + /******************/ + /* Software reset */ + /******************/ + i_DummyRead=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + i_DummyRead=inb(devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(1,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the master configuration control register */ + /*****************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0xF4,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data path polarity register of port A */ + outb( APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port A means 1 */ + outb(0xFF,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data direction register of port A */ + outb(APCI1500_RW_PORT_A_DATA_DIRECTION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port A: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port A */ + outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data path polarity register of port B */ + outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* A high level of port B means 1 */ + outb(0x7F,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port B */ + outb(APCI1500_RW_PORT_B_DATA_DIRECTION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb( APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port B: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port B */ + outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the data path polarity register of port C */ + /*****************************************************/ + outb( APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port C means 1 */ + outb(0x9,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port C */ + outb(APCI1500_RW_PORT_C_DATA_DIRECTION,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs except channel 1 */ + outb(0x0E,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the special IO register of port C */ + outb( APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes it */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 1 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 1 */ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of timer 1 */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 2 */ + /******************************************************/ + outb( APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 2 */ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates Timer 2 interrupt management: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 3 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of Timer 3 */ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates interrupt management of timer 3: */ + outb(0xE0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes all interrupts */ + outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + //reset all the digital outputs +outw(0x0,devpriv->i_IobaseAddon+APCI1500_DIGITAL_OP); +/*******************************/ +/* Disable the board interrupt */ +/*******************************/ + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ +outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ +outb(0,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ +outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ +outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ +outb( APCI1500_RW_PORT_B_COMMAND_AND_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ +outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ + /* Selects the command and status register of timer 1*/ + /*****************************************************/ +outb(APCI1500_RW_CPT_TMR1_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ +outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ + /* Selects the command and status register of timer 2*/ + /*****************************************************/ +outb(APCI1500_RW_CPT_TMR2_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ +outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ +/* Selects the command and status register of timer 3*/ +/*****************************************************/ +outb(APCI1500_RW_CPT_TMR3_CMD_STATUS,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ +outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); +return 0; +} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/comedi/drivers/addi-data/hwdrv_apci1500.h b/comedi/drivers/addi-data/hwdrv_apci1500.h new file mode 100644 index 00000000..479a0ead --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1500.h @@ -0,0 +1,126 @@ +/********* Definitions for APCI-1500 card *****/ + +// Card Specific information +#define APCI1500_BOARD_VENDOR_ID 0x10e8 +#define APCI1500_ADDRESS_RANGE 4 + + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI1500_DIGITAL_OP 2 +#define APCI1500_DIGITAL_IP 0 +#define APCI1500_AND 2 +#define APCI1500_OR 4 +#define APCI1500_OR_PRIORITY 6 +#define APCI1500_CLK_SELECT 0 +#define COUNTER1 0 +#define COUNTER2 1 +#define COUNTER3 2 +#define APCI1500_COUNTER 0x20 +#define APCI1500_TIMER 0 +#define APCI1500_WATCHDOG 0 +#define APCI1500_SINGLE 0 +#define APCI1500_CONTINUOUS 0x80 +#define APCI1500_DISABLE 0 +#define APCI1500_ENABLE 1 +#define APCI1500_SOFTWARE_TRIGGER 0x4 +#define APCI1500_HARDWARE_TRIGGER 0x10 +#define APCI1500_SOFTWARE_GATE 0 +#define APCI1500_HARDWARE_GATE 0x8 +#define START 0 +#define STOP 1 +#define TRIGGER 2 + /**************************/ + /* Zillog I/O enumeration */ + /**************************/ + enum + { + APCI1500_Z8536_PORT_C, + APCI1500_Z8536_PORT_B, + APCI1500_Z8536_PORT_A, + APCI1500_Z8536_CONTROL_REGISTER + }; + + /******************************/ + /* Z8536 CIO Internal Address */ + /******************************/ + + enum + { + APCI1500_RW_MASTER_INTERRUPT_CONTROL, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + APCI1500_RW_PORT_A_INTERRUPT_CONTROL, + APCI1500_RW_PORT_B_INTERRUPT_CONTROL, + APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR, + APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, + APCI1500_RW_PORT_C_DATA_DIRECTION, + APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, + + APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + APCI1500_RW_CPT_TMR1_CMD_STATUS, + APCI1500_RW_CPT_TMR2_CMD_STATUS, + APCI1500_RW_CPT_TMR3_CMD_STATUS, + APCI1500_RW_PORT_A_DATA, + APCI1500_RW_PORT_B_DATA, + APCI1500_RW_PORT_C_DATA, + + APCI1500_R_CPT_TMR1_VALUE_HIGH, + APCI1500_R_CPT_TMR1_VALUE_LOW, + APCI1500_R_CPT_TMR2_VALUE_HIGH, + APCI1500_R_CPT_TMR2_VALUE_LOW, + APCI1500_R_CPT_TMR3_VALUE_HIGH, + APCI1500_R_CPT_TMR3_VALUE_LOW, + APCI1500_RW_CPT_TMR1_TIME_CST_HIGH, + APCI1500_RW_CPT_TMR1_TIME_CST_LOW, + APCI1500_RW_CPT_TMR2_TIME_CST_HIGH, + APCI1500_RW_CPT_TMR2_TIME_CST_LOW, + APCI1500_RW_CPT_TMR3_TIME_CST_HIGH, + APCI1500_RW_CPT_TMR3_TIME_CST_LOW, + APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION, + APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION, + APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION, + APCI1500_R_CURRENT_VECTOR, + + APCI1500_RW_PORT_A_SPECIFICATION, + APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, + APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, + APCI1500_RW_PORT_A_DATA_DIRECTION, + APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL, + APCI1500_RW_PORT_A_PATTERN_POLARITY, + APCI1500_RW_PORT_A_PATTERN_TRANSITION, + APCI1500_RW_PORT_A_PATTERN_MASK, + + APCI1500_RW_PORT_B_SPECIFICATION, + APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, + APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, + APCI1500_RW_PORT_B_DATA_DIRECTION, + APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL, + APCI1500_RW_PORT_B_PATTERN_POLARITY, + APCI1500_RW_PORT_B_PATTERN_TRANSITION, + APCI1500_RW_PORT_B_PATTERN_MASK + }; + + /*----------DIGITAL INPUT----------------*/ +static int i_APCI1500_Initialisation(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + static int i_APCI1500_ConfigDigitalInputEvent(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +static int i_APCI1500_StartStopInputEvent(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +static int i_APCI1500_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +/*---------- DIGITAL OUTPUT------------*/ +static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +static int i_APCI1500_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +/*----------TIMER----------------*/ + static int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +static int i_APCI1500_ReadCounterTimerWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +static int i_APCI1500_ReadInterruptMask(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +/*----------INTERRUPT HANDLER------*/ +static void v_APCI1500_Interrupt(int irq, void *d, struct pt_regs *regs); +static int i_APCI1500_ConfigureInterrupt(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +/*----------RESET---------------*/ +static int i_APCI1500_Reset(comedi_device *dev) ; + \ No newline at end of file diff --git a/comedi/drivers/addi-data/hwdrv_apci1516.c b/comedi/drivers/addi-data/hwdrv_apci1516.c new file mode 100644 index 00000000..45501fe6 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1516.c @@ -0,0 +1,484 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci1516.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 31.10.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1516 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci1516.h" + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_Read1DigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1516_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_TmpValue=0; + UINT ui_Channel; + ui_Channel=CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <=7) + { + ui_TmpValue=(UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP); + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> ui_Channel)&0x1 ; + }//if(ui_Channel >= 0 && ui_Channel <=7) + else + { + //comedi_error(dev," \n chan spec wrong\n"); + return -EINVAL; // "sorry channel spec wrong " + }//else if(ui_Channel >= 0 && ui_Channel <=7) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ReadMoreDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + + UINT ui_PortValue=data[0]; + UINT ui_Mask=0; + UINT ui_NoOfChannels; + + ui_NoOfChannels=CR_CHAN(insn->chanspec); + + *data=(UINT)inw(devpriv->iobase + APCI1516_DIGITAL_IP ); + switch (ui_NoOfChannels) + { + case 2:ui_Mask=3; + *data=(*data >>(2*ui_PortValue))&ui_Mask; + break; + case 4:ui_Mask=15; + *data=(*data >>(4*ui_PortValue))&ui_Mask; + break; + case 7:break; + + default: + printk("\nWrong parameters\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + }//switch(ui_NoOfChannels) + + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ConfigDigitalOutput (comedi_device *dev, + comedi_subdevice *s comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| data[0] :1:Memory on | +| 0:Memory off | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1516_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){ + devpriv->b_OutputMemoryStatus=data[0]; +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_Temp,ui_Temp1; +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if(devpriv->b_OutputMemoryStatus ) + { + ui_Temp=inw(devpriv->iobase+APCI1516_DIGITAL_OP); + + }//if(devpriv->b_OutputMemoryStatus ) + else + { + ui_Temp=0; + }//if(devpriv->b_OutputMemoryStatus ) +if(data[3]==0) + { + if(data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outw(data[0],devpriv->iobase+APCI1516_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=(data[0] << (2*data[2]))|ui_Temp; + break; + + + case 4:data[0]=(data[0] << (4*data[2]))|ui_Temp; + break; + + case 7:data[0]=data[0]|ui_Temp; + break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outw(data[0],devpriv->iobase+APCI1516_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==0) +else + { + if(data[3]==1) + { + if(data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<iobase+APCI1516_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2*data[2]))^0xff)& ui_Temp; + break; + + + case 4:data[0]=~data[0]&0xf; + ui_Temp1=15; + ui_Temp1=ui_Temp1<<4*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (4*data[2]))^0xff)&ui_Temp; + break; + + case 7: break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outw(data[0],devpriv->iobase+APCI1516_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }//if else data[3]==1) + }//if else data[3]==0) + return (insn->n);; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ReadDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + +UINT ui_Temp; +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel +ui_Temp=data[0]; +*data=inw(devpriv->iobase+APCI1516_DIGITAL_OP_RW); +if(ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + }//if(ui_Temp==0) +else + { + if(ui_Temp==1) + { + switch( ui_NoOfChannel) + { + + case 2:*data=(*data >>(2*data[1]))&3; + break; + + + case 4:*data=(*data >>(4*data[1]))&15; + break; + + case 7: break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + }//if(ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + }//elseif(ui_Temp==1) + }//elseif(ui_Temp==0) +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ConfigWatchdog(comedi_device *dev, + comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1516_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +if(data[0]==0) + { + //Disable the watchdog + outw(0x0,devpriv->i_IobaseAddon+ APCI1516_WATCHDOG_ENABLEDISABLE); + //Loading the Reload value + outw(data[1],devpriv->i_IobaseAddon+APCI1516_WATCHDOG_RELOAD_VALUE); + data[1]=data[1]>>16; + outw(data[1],devpriv->i_IobaseAddon+APCI1516_WATCHDOG_RELOAD_VALUE+2); + }//if(data[0]==0) +else + { + printk("\nThe input parameters are wrong\n"); + return -EINVAL; + }//elseif(data[0]==0) + +return insn->n; +} + + /* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_StartStopWriteWatchdog | +| (comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1516_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + switch(data[0]) + { + case 0://stop the watchdog + outw(0x0,devpriv->i_IobaseAddon+ APCI1516_WATCHDOG_ENABLEDISABLE);//disable the watchdog + break; + case 1://start the watchdog + outw(0x0001,devpriv->i_IobaseAddon+ APCI1516_WATCHDOG_ENABLEDISABLE); + break; + case 2://Software trigger + outw(0x0201,devpriv->i_IobaseAddon+ APCI1516_WATCHDOG_ENABLEDISABLE); + break; + default:printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }// switch(data[0]) +return insn->n; +} +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ReadWatchdog | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1516_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) + { + data[0]= inw(devpriv->i_IobaseAddon+APCI1516_WATCHDOG_STATUS)&0x1; +return insn->n; +} +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_Reset(comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_Reset(comedi_device *dev) +{ + outw(0x0 ,devpriv->iobase+APCI1516_DIGITAL_OP);//RESETS THE DIGITAL OUTPUTS + outw(0x0,devpriv->i_IobaseAddon+ APCI1516_WATCHDOG_ENABLEDISABLE); + outw(0x0,devpriv->i_IobaseAddon+APCI1516_WATCHDOG_RELOAD_VALUE); + outw(0x0,devpriv->i_IobaseAddon+APCI1516_WATCHDOG_RELOAD_VALUE+2); + return 0; +} + + diff --git a/comedi/drivers/addi-data/hwdrv_apci1516.h b/comedi/drivers/addi-data/hwdrv_apci1516.h new file mode 100644 index 00000000..28c6f1f1 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1516.h @@ -0,0 +1,51 @@ +/********* Definitions for APCI-1516 card *****/ + +// Card Specific information +#define APCI1516_BOARD_VENDOR_ID 0x15B8 +#define APCI1516_ADDRESS_RANGE 8 + + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI1516_DIGITAL_OP 4 +#define APCI1516_DIGITAL_OP_RW 4 +#define APCI1516_DIGITAL_IP 0 + + + + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_WATCHDOG 2 +#define APCI1516_DIGITAL_OP_WATCHDOG 0 +#define APCI1516_WATCHDOG_ENABLEDISABLE 12 +#define APCI1516_WATCHDOG_RELOAD_VALUE 4 +#define APCI1516_WATCHDOG_STATUS 16 + + +// Hardware Layer functions for Apci1516 + + +//Digital Input +INT i_APCI1516_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI1516_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + + + +//Digital Output +int i_APCI1516_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI1516_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI1516_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) ; + + +// TIMER +// timer value is passed as u seconds +int i_APCI1516_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI1516_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI1516_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +//reset +INT i_APCI1516_Reset(comedi_device *dev); + diff --git a/comedi/drivers/addi-data/hwdrv_apci1564.c b/comedi/drivers/addi-data/hwdrv_apci1564.c new file mode 100644 index 00000000..b4a55f23 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -0,0 +1,930 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci1564.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 31.10.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1564 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include +#include "hwdrv_apci1564.h" + +//Global variables +UINT ui_InterruptStatus_1564=0 ; +UINT ui_InterruptData,ui_Type; + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ConfigDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures the digital input Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 1 Enable Digital Input Interrupt | +| 0 Disable Digital Input Interrupt | +| data[1] : 0 ADDIDATA Interrupt OR LOGIC | +| : 1 ADDIDATA Interrupt AND LOGIC | +| data[2] : Interrupt mask for the mode 1 | +| data[3] : Interrupt mask for the mode 2 | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ConfigDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + devpriv->tsk_Current=current; + /*******************************/ + /* Set the digital input logic */ + /*******************************/ + if ( data[0] == ADDIDATA_ENABLE) + { + data[2]=data[2]<<4; + data[3]=data[3]<<4; + outl (data[2] , devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); + outl (data[3] , devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_INTERRUPT_MODE2); + if (data[1] == ADDIDATA_OR) + { + outl(0x4 ,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); + } // if (data[1] == ADDIDATA_OR) + else + { + outl(0x6 ,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); + } // else if (data[1] == ADDIDATA_OR) + } // if (data[0] == ADDIDATA_ENABLE) + else + { + outl (0x0, devpriv->i_IobaseAmcc +APCI1564_DIGITAL_IP +APCI1564_DIGITAL_IP_INTERRUPT_MODE1); + outl (0x0, devpriv->i_IobaseAmcc +APCI1564_DIGITAL_IP +APCI1564_DIGITAL_IP_INTERRUPT_MODE2); + outl(0x0 ,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +APCI1564_DIGITAL_IP_IRQ); + } // else if (data[0] == ADDIDATA_ENABLE) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_Read1DigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_TmpValue=0; + UINT ui_Channel; + + ui_Channel=CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <=31) + { + ui_TmpValue=(UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP ); + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> ui_Channel)&0x1 ; + } // if (ui_Channel >= 0 && ui_Channel <=31) + else + { + comedi_error(dev,"Not a valid channel number !!! \n"); + return -EINVAL; // "sorry channel spec wrong " + } //else if (ui_Channel >= 0 && ui_Channel <=31) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadMoreDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To be Read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_PortValue=data[0]; + UINT ui_Mask=0; + UINT ui_NoOfChannels; + + ui_NoOfChannels=CR_CHAN(insn->chanspec); + if (data[1]==0) + { + *data=(UINT)inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP ); + switch (ui_NoOfChannels) + { + case 2: ui_Mask=3; + *data=(*data >>(2*ui_PortValue))&ui_Mask; + break; + case 4: ui_Mask=15; + *data=(*data >>(4*ui_PortValue))&ui_Mask; + break; + case 8: ui_Mask=255; + *data=(*data >>(8*ui_PortValue))&ui_Mask; + break; + case 16:ui_Mask=65535; + *data=(*data >>(16*ui_PortValue))&ui_Mask; + break; + case 31:break; + default: + comedi_error(dev,"Not a valid Channel number !!!\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + } // switch (ui_NoOfChannels) + } // if (data[1]==0) + else + { + if (data[1]==1) + { + *data=ui_InterruptStatus_1564; + } // if (data[1]==1) + } // else if (data[1]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ConfigDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[1] : 1 Enable VCC Interrupt | +| 0 Disable VCC Interrupt | +| data[2] : 1 Enable CC Interrupt | +| 0 Disable CC Interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + ULONG ul_Command = 0; + + if ((data[0]!=0) && (data[0]!=1)) + { + comedi_error(dev,"Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } // if ((data[0]!=0) && (data[0]!=1)) + if (data[0]) + { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE ; + } // if (data[0]) + else + { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } // else if (data[0]) + if (data[1] == ADDIDATA_ENABLE) + { + ul_Command = ul_Command | 0x1; + } // if (data[1] == ADDIDATA_ENABLE) + else + { + ul_Command = ul_Command & 0xFFFFFFFE; + } // else if (data[1] == ADDIDATA_ENABLE) + if (data[2] == ADDIDATA_ENABLE) + { + ul_Command = ul_Command | 0x2; + } // if (data[2] == ADDIDATA_ENABLE) + else + { + ul_Command = ul_Command & 0xFFFFFFFD; + } // else if (data[2] == ADDIDATA_ENABLE) + outl( ul_Command , devpriv->i_IobaseAmcc+APCI1564_DIGITAL_OP+APCI1564_DIGITAL_OP_INTERRUPT); + ui_InterruptData=inl( devpriv->i_IobaseAmcc+APCI1564_DIGITAL_OP+APCI1564_DIGITAL_OP_INTERRUPT); + devpriv->tsk_Current=current; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) { + UINT ui_Temp,ui_Temp1; + UINT ui_NoOfChannel; + + ui_NoOfChannel=CR_CHAN(insn->chanspec); + if (devpriv->b_OutputMemoryStatus ) + { + ui_Temp=inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_RW); + } // if (devpriv->b_OutputMemoryStatus ) + else + { + ui_Temp=0; + } // else if (devpriv->b_OutputMemoryStatus ) + if (data[3]==0) + { + if (data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outl(data[0],devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==0) + else + { + if (data[1]==1) + { + switch (ui_NoOfChannel) + { + case 2: data[0]=(data[0] << (2*data[2]))|ui_Temp; + break; + case 4: data[0]=(data[0] << (4*data[2]))|ui_Temp; + break; + case 8: data[0]=(data[0] <<(8*data[2]))|ui_Temp; + break; + case 16: data[0]=(data[0] <<(16*data[2]))|ui_Temp; + break; + case 31: data[0]=data[0]|ui_Temp; + break; + default: comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } // switch (ui_NoOfChannels) + outl(data[0],devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + } // else if (data[1]==1) + } // else if (data[1]==0) + }//if(data[3]==0) + else + { + if (data[3]==1) + { + if (data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==0) + else + { + if (data[1]==1) + { + switch (ui_NoOfChannel) + { + case 2: data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2*data[2]))^0xffffffff)& ui_Temp; + break; + case 4: data[0]=~data[0]&0xf; + ui_Temp1=15; + ui_Temp1=ui_Temp1<<4*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (4*data[2]))^0xffffffff)&ui_Temp; + break; + case 8: data[0]=~data[0]&0xff; + ui_Temp1=255; + ui_Temp1=ui_Temp1<<8*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (8*data[2]))^0xffffffff)&ui_Temp; + break; + case 16: data[0]=~data[0]&0xffff; + ui_Temp1=65535; + ui_Temp1=ui_Temp1<<16*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (16*data[2]))^0xffffffff)&ui_Temp; + break; + case 31: break; + default: comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + }//switch(ui_NoOfChannels) + outl(data[0],devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + } // else if (data[1]==1) + } // else if (data[1]==0) + } // if (data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } // else if (data[3]==1) + } // else if (data[3]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + + ui_NoOfChannel=CR_CHAN(insn->chanspec); + ui_Temp=data[0]; + *data=inl(devpriv->i_IobaseAmcc+APCI1564_DIGITAL_OP+APCI1564_DIGITAL_OP_RW); + if (ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + } // if (ui_Temp==0) + else + { + if (ui_Temp==1) + { + switch (ui_NoOfChannel) + { + case 2: + *data=(*data >>(2*data[1]))&3; + break; + + case 4: + *data=(*data >>(4*data[1]))&15; + break; + + case 8: + *data=(*data >>(8*data[1]))&255; + break; + + case 16: + *data=(*data >>(16*data[1]))&65535; + break; + + case 31: break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + break; + } // switch(ui_NoOfChannels) + } // if (ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // else if (ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ConfigTimerCounterWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Configure As Timer | +| 1 Configure As Counter | +| 2 Configure As Watchdog | +| data[1] : 1 Enable Interrupt | +| 0 Disable Interrupt | +| data[2] : Time Unit | +| data[3] : Reload Value | +| data[4] : Timer Mode | +| data[5] : Timer Counter Watchdog Number| + data[6] : Counter Direction ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ConfigTimerCounterWatchdog (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + ULONG ul_Command1 = 0; + devpriv->tsk_Current=current; + if (data[0]==ADDIDATA_WATCHDOG) + { + devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; + + //Disable the watchdog + outl(0x0,devpriv->i_IobaseAmcc+ APCI1564_DIGITAL_OP_WATCHDOG+ APCI1564_TCW_PROG); + //Loading the Reload value + outl(data[3],devpriv->i_IobaseAmcc+APCI1564_DIGITAL_OP_WATCHDOG+APCI1564_TCW_RELOAD_VALUE); + } // if (data[0]==ADDIDATA_WATCHDOG) + else if (data[0]==ADDIDATA_TIMER) + { + //First Stop The Timer + ul_Command1 =inl(devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG); + ul_Command1 =ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1,devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG);//Stop The Timer + + devpriv->b_TimerSelectMode =ADDIDATA_TIMER; + if (data[1]==1) + { + outl(0x02,devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG);//Enable TIMER int & DISABLE ALL THE OTHER int SOURCES + outl(0x0,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); + outl(0x0,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_IRQ); + outl(0x0,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_IRQ); + outl(0x0,devpriv->iobase+APCI1564_COUNTER1 + APCI1564_TCW_IRQ); + outl(0x0,devpriv->iobase+APCI1564_COUNTER2 + APCI1564_TCW_IRQ); + outl(0x0,devpriv->iobase+APCI1564_COUNTER3 + APCI1564_TCW_IRQ); + outl(0x0,devpriv->iobase+APCI1564_COUNTER4 + APCI1564_TCW_IRQ); + } // if (data[1]==1) + else + { + outl(0x0,devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG);//disable Timer interrupt + } // else if (data[1]==1) + + // Loading Timebase + + outl(data[2],devpriv->i_IobaseAmcc+APCI1564_TIMER+APCI1564_TCW_TIMEBASE); + + //Loading the Reload value + outl(data[3],devpriv->i_IobaseAmcc+APCI1564_TIMER+APCI1564_TCW_RELOAD_VALUE); + + ul_Command1 =inl(devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; + outl(ul_Command1,devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG);//mode 2 + } // else if (data[0]==ADDIDATA_TIMER) + else if (data[0]==ADDIDATA_COUNTER) + { + devpriv->b_TimerSelectMode =ADDIDATA_COUNTER; + devpriv->b_ModeSelectRegister=data[5]; + + //First Stop The Counter + ul_Command1 =inl(devpriv->iobase+((data[5]-1)*0x20)+APCI1564_TCW_PROG); + ul_Command1 =ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1,devpriv->iobase+((data[5]-1)*0x20)+APCI1564_TCW_PROG);//Stop The Timer + + /************************/ + /* Set the reload value */ + /************************/ + outl(data[3] , devpriv->iobase+((data[5]-1)*0x20)+APCI1564_TCW_RELOAD_VALUE); + + /******************************/ + /* Set the mode : */ + /* - Disable the hardware */ + /* - Disable the counter mode */ + /* - Disable the warning */ + /* - Disable the reset */ + /* - Disable the timer mode */ + /* - Enable the counter mode */ + /******************************/ + ul_Command1 = (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL | (ULONG) ((ULONG) data[4] << 16UL); + outl(ul_Command1 , devpriv->iobase+((data[5]-1)*0x20)+APCI1564_TCW_PROG); + + // Enable or Disable Interrupt + ul_Command1= (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1); + outl(ul_Command1 , devpriv->iobase+((data[5]-1)*0x20)+APCI1564_TCW_PROG); + + /*****************************/ + /* Set the Up/Down selection */ + /*****************************/ + ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18); + outl(ul_Command1 , devpriv->iobase+((data[5]-1)*0x20)+APCI1564_TCW_PROG); + } // else if (data[0]==ADDIDATA_COUNTER) + else + { + printk(" Invalid subdevice."); + } // else if (data[0]==ADDIDATA_WATCHDOG) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Timer | +| 1 Counter | +| 2 Watchdog | | data[1] : 1 Start | +| 0 Stop | +| 2 Trigger | +| Clear (Only Counter) | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + ULONG ul_Command1 = 0; + if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + { + switch (data[1]) + { + case 0: //stop the watchdog + outl(0x0,devpriv->i_IobaseAmcc+ APCI1564_DIGITAL_OP_WATCHDOG+ APCI1564_TCW_PROG );//disable the watchdog + break; + case 1: //start the watchdog + outl(0x0001,devpriv->i_IobaseAmcc+ APCI1564_DIGITAL_OP_WATCHDOG+ APCI1564_TCW_PROG); + break; + case 2: //Software trigger + outl(0x0201,devpriv->i_IobaseAmcc+ APCI1564_DIGITAL_OP_WATCHDOG+ APCI1564_TCW_PROG); + break; + default: printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } // switch (data[1]) + } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + { + if (data[1]==1) + { + ul_Command1=inl(devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG); + ul_Command1=(ul_Command1& 0xFFFFF9FFUL) | 0x1UL; + + //Enable the Timer + outl(ul_Command1,devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG); + } // if (data[1]==1) + else if(data[1]==0) + { + //Stop The Timer + + ul_Command1=inl(devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG); + ul_Command1 =ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1,devpriv->i_IobaseAmcc+ APCI1564_TIMER+ APCI1564_TCW_PROG); + } // else if(data[1]==0) + } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) + { + ul_Command1=inl(devpriv->iobase+((devpriv->b_ModeSelectRegister-1)*0x20)+APCI1564_TCW_PROG); + if (data[1] == 1) + { + //Start the Counter subdevice + ul_Command1= (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; + } // if (data[1] == 1) + else if (data[1] == 0) + { + // Stops the Counter subdevice + ul_Command1 = 0; + + } // else if (data[1] == 0) + else if (data[1] == 2) + { + // Clears the Counter subdevice + ul_Command1= (ul_Command1 & 0xFFFFF9FFUL)|0x400; + } // else if (data[1] == 3) + outl(ul_Command1 , devpriv->iobase+((devpriv->b_ModeSelectRegister-1)*0x20)+APCI1564_TCW_PROG); + } // if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadTimerCounterWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | + ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ReadTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + ULONG ul_Command1 = 0; + + if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + { + // Stores the status of the Watchdog + data[0]= inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_TRIG_STATUS)&0x1; + data[1]= inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG); + } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + { + // Stores the status of the Timer + data[0]= inl(devpriv->i_IobaseAmcc+APCI1564_TIMER+APCI1564_TCW_TRIG_STATUS)&0x1; + + // Stores the Actual value of the Timer + data[1]= inl(devpriv->i_IobaseAmcc + APCI1564_TIMER); + } // else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) + { + // Read the Counter Actual Value. + data[0] = inl(devpriv->iobase+((devpriv->b_ModeSelectRegister-1)*0x20)+APCI1564_TCW_SYNC_ENABLEDISABLE); + ul_Command1 = inl(devpriv->iobase+((devpriv->b_ModeSelectRegister-1)*0x20)+APCI1564_TCW_TRIG_STATUS); + + /***********************************/ + /* Get the software trigger status */ + /***********************************/ + data[1]= (BYTE) ((ul_Command1 >> 1) & 1); + + /***********************************/ + /* Get the hardware trigger status */ + /***********************************/ + data[2]= (BYTE) ((ul_Command1 >> 2) & 1); + + /*********************************/ + /* Get the software clear status */ + /*********************************/ + data[3]= (BYTE) ((ul_Command1 >> 3) & 1); + + /***************************/ + /* Get the overflow status */ + /***************************/ + data[4]= (BYTE) ((ul_Command1 >> 0) & 1); + } // else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) + else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) + { + printk ("\n Invalid Subdevice !!!\n"); + } // else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadInterruptStatus | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task :Reads the interrupt status register | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1564_ReadInterruptStatus(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + *data=ui_Type; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI1564_Interrupt | +| (int irq , void *d, struct pt_regs *regs) | ++----------------------------------------------------------------------------+ +| Task : Interrupt handler for the interruptible digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | +| struct pt_regs *regs : structure pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static VOID v_APCI1564_Interrupt(int irq,void* d, struct pt_regs *regs) +{ + comedi_device *dev =d; + UINT ui_DO, ui_DI; + UINT ui_Timer; + UINT ui_C1, ui_C2, ui_C3, ui_C4; + ULONG ul_Command2=0; + ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ) & 0x01; + ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_IRQ) & 0x01; + ui_Timer = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER+ APCI1564_TCW_IRQ) & 0x01; + ui_C1=inl(devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_IRQ ) & 0x1; + ui_C2=inl(devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_IRQ ) & 0x1; + ui_C3=inl(devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_IRQ ) & 0x1; + ui_C4=inl(devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_IRQ ) & 0x1; + if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) + { + printk("\nInterrupt from unknown source\n"); + }// if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) + + if (ui_DI == 1) + { + ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); + outl(0x0 ,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); + ui_InterruptStatus_1564=inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); + ui_InterruptStatus_1564=ui_InterruptStatus_1564 & 0X000FFFF0; + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + outl(ui_DI ,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ);//enable the interrupt + return; + } + + if (ui_DO == 1) + { + // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. + ui_Type=inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3; + //Disable the Interrupt + outl(0x0,devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_INTERRUPT); + + //Sends signal to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + } // if (ui_DO) + + if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER)) + { + // Disable Timer Interrupt + ul_Command2=inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); + outl(0x0 , devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + // Enable Timer Interrupt + + outl(ul_Command2 , devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); + } // if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER)) + + + if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) + { + // Disable Counter Interrupt + ul_Command2=inl(devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG); + outl(0x0 , devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + // Enable Counter Interrupt + outl(ul_Command2 , devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG); + } // if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) + + if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + { + // Disable Counter Interrupt + ul_Command2=inl(devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG); + outl(0x0 , devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + // Enable Counter Interrupt + outl(ul_Command2 , devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG); + } // if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + + if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + { + // Disable Counter Interrupt + ul_Command2=inl(devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG); + outl(0x0 , devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + // Enable Counter Interrupt + outl(ul_Command2 , devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG); + } // if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + + if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + { + // Disable Counter Interrupt + ul_Command2=inl(devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG); + outl(0x0 , devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + + // Enable Counter Interrupt + outl(ul_Command2 , devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG); + } // if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + return; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_Reset(comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1564_Reset(comedi_device *dev) +{ + outl(0x0 ,devpriv->i_IobaseAmcc+APCI1564_DIGITAL_IP_IRQ);//disable the interrupts + inl(devpriv->i_IobaseAmcc+APCI1564_DIGITAL_IP_INTERRUPT_STATUS);//Reset the interrupt status register + outl (0x0 , devpriv->i_IobaseAmcc+APCI1564_DIGITAL_IP_INTERRUPT_MODE1);//Disable the and/or interrupt + outl (0x0 , devpriv->i_IobaseAmcc+APCI1564_DIGITAL_IP_INTERRUPT_MODE2); + devpriv->b_DigitalOutputRegister=0; + ui_Type=0; + outl(0x0,devpriv->i_IobaseAmcc+APCI1564_DIGITAL_OP);//Resets the output channels + outl(0x0,devpriv->i_IobaseAmcc+APCI1564_DIGITAL_OP_INTERRUPT);//Disables the interrupt. + outl(0x0,devpriv->i_IobaseAmcc+APCI1564_DIGITAL_OP_WATCHDOG+APCI1564_TCW_RELOAD_VALUE); + outl(0x0,devpriv->i_IobaseAmcc+APCI1564_TIMER); + outl(0x0 , devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); + + outl(0x0 , devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG); + outl(0x0 , devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG); + outl(0x0 , devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG); + outl(0x0 , devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG); + return 0; +} diff --git a/comedi/drivers/addi-data/hwdrv_apci1564.h b/comedi/drivers/addi-data/hwdrv_apci1564.h new file mode 100644 index 00000000..447223fa --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci1564.h @@ -0,0 +1,91 @@ +/********* Definitions for APCI-1564 card *****/ + +#define APCI1564_BOARD_VENDOR_ID 0x15B8 +#define APCI1564_ADDRESS_RANGE 128 + +//DIGITAL INPUT-OUTPUT DEFINE +// Input defines +#define APCI1564_DIGITAL_IP 0x04 +#define APCI1564_DIGITAL_IP_INTERRUPT_MODE1 4 +#define APCI1564_DIGITAL_IP_INTERRUPT_MODE2 8 +#define APCI1564_DIGITAL_IP_IRQ 16 + +// Output defines +#define APCI1564_DIGITAL_OP 0x18 +#define APCI1564_DIGITAL_OP_RW 0 +#define APCI1564_DIGITAL_OP_INTERRUPT 4 +#define APCI1564_DIGITAL_OP_IRQ 12 + + +//Digital Input IRQ Function Selection +#define ADDIDATA_OR 0 +#define ADDIDATA_AND 1 + +//Digital Input Interrupt Status +#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS 12 + +//Digital Output Interrupt Status +#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS 8 + +//Digital Input Interrupt Enable Disable. +#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE 0x4 +#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB + +//Digital Output Interrupt Enable Disable. +#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1 +#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE +#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2 +#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_TIMER 0 +#define ADDIDATA_COUNTER 1 +#define ADDIDATA_WATCHDOG 2 +#define APCI1564_DIGITAL_OP_WATCHDOG 0x28 +#define APCI1564_TIMER 0x48 +#define APCI1564_COUNTER1 0x0 +#define APCI1564_COUNTER2 0x20 +#define APCI1564_COUNTER3 0x40 +#define APCI1564_COUNTER4 0x60 +#define APCI1564_TCW_SYNC_ENABLEDISABLE 0 +#define APCI1564_TCW_RELOAD_VALUE 4 +#define APCI1564_TCW_TIMEBASE 8 +#define APCI1564_TCW_PROG 12 +#define APCI1564_TCW_TRIG_STATUS 16 +#define APCI1564_TCW_IRQ 20 +#define APCI1564_TCW_WARN_TIMEVAL 24 +#define APCI1564_TCW_WARN_TIMEBASE 28 + + +// Hardware Layer functions for Apci1564 + +//DI +// for di read +INT i_APCI1564_ConfigDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI1564_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI1564_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +//DO +int i_APCI1564_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI1564_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI1564_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI1564_ReadInterruptStatus(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +// TIMER +// timer value is passed as u seconds +INT i_APCI1564_ConfigTimerCounterWatchdog (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI1564_StartStopWriteTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI1564_ReadTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +// INTERRUPT +static VOID v_APCI1564_Interrupt(int irq, void *d, struct pt_regs *regs) ; + +// RESET +INT i_APCI1564_Reset(comedi_device *dev); diff --git a/comedi/drivers/addi-data/hwdrv_apci2016.c b/comedi/drivers/addi-data/hwdrv_apci2016.c new file mode 100644 index 00000000..d8af1168 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci2016.c @@ -0,0 +1,407 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci2016.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 31.10.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-2016 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci2016.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_ConfigDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 1 Digital Memory On | +| 0 Digital Memory Off | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + if ((data[0]!=0) && (data[0]!=1)) + { + comedi_error(dev,"Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } // if ((data[0]!=0) && (data[0]!=1)) + if (data[0]) + { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE ; + } // if (data[0] + else + { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } // else if (data[0] + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_NoOfChannel; + UINT ui_Temp,ui_Temp1; + ui_NoOfChannel=CR_CHAN(insn->chanspec); + if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) + { + comedi_error(dev,"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); + return -EINVAL; + } // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) + if (devpriv->b_OutputMemoryStatus ) + { + ui_Temp=inw(devpriv->iobase+APCI2016_DIGITAL_OP); + } // if (devpriv->b_OutputMemoryStatus ) + else + { + ui_Temp=0; + } // else if (devpriv->b_OutputMemoryStatus ) + if ((data[1]!=0) && (data[1]!=1)) + { + comedi_error(dev,"Invalid Data[1] value !!!, Data[1] should be 0 or 1\n"); + return -EINVAL; + } // if ((data[1]!=0) && (data[1]!=1)) + + if (data[3]==0) + { + if (data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outw(data[0],devpriv->iobase+APCI2016_DIGITAL_OP); + } // if (data[1]==0) + else + { + if (data[1]==1) + { + switch (ui_NoOfChannel) + { + case 2: data[0]=(data[0] << (2*data[2]))|ui_Temp; + break; + case 4: data[0]=(data[0] << (4*data[2]))|ui_Temp; + break; + case 8: data[0]=(data[0] << (8*data[2]))|ui_Temp; + break; + case 15: data[0]=data[0]|ui_Temp; + break; + default: comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + }//switch(ui_NoOfChannels) + outw(data[0],devpriv->iobase+APCI2016_DIGITAL_OP); + }// if (data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + } // else if (data[1]==1) + } // else if (data[1]==0) + } // if (data[3]==0) + else + { + if (data[3]==1) + { + if (data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<iobase+APCI2016_DIGITAL_OP); + } // if (data[1]==0) + else + { + if (data[1]==1) + { + switch (ui_NoOfChannel) + { + case 2: data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2*data[2]))^0xffff)& ui_Temp; + break; + case 4: data[0]=~data[0]&0xf; + ui_Temp1=15; + ui_Temp1=ui_Temp1<<4*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (4*data[2]))^0xffff)&ui_Temp; + break; + case 8: data[0]=~data[0]&0xff; + ui_Temp1=255; + ui_Temp1=ui_Temp1<<8*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (8*data[2]))^0xffff)&ui_Temp; + break; + case 15: break; + default: comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + }//switch(ui_NoOfChannels) + outw(data[0],devpriv->iobase+APCI2016_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }//if else data[3]==1) + }//if else data[3]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_BitsDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_BitsDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel=CR_CHAN(insn->chanspec); + if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) + { + comedi_error(dev,"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); + return -EINVAL; + } // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) + if ((data[0]!=0) && (data[0]!=1)) + { + comedi_error(dev,"Invalid Data[0] value !!!, Data[0] should be 0 or 1\n"); + return -EINVAL; + } // if ((data[0]!=0) && (data[0]!=1)) + ui_Temp=data[0]; + *data=inw(devpriv->iobase+APCI2016_DIGITAL_OP_RW); + if (ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + } // if (ui_Temp==0) + else + { + if (ui_Temp==1) + { + switch (ui_NoOfChannel) + { + case 2: *data=(*data >>(2*data[1]))&3; + break; + + case 4: *data=(*data >>(4*data[1]))&15; + break; + + case 8: *data=(*data >>(8*data[1]))&255; + break; + + case 15: break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + }//switch(ui_NoOfChannel) + } // if (ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // if (ui_Temp==0) + return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_ConfigWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure | +| comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + + if (data[0]==0) + { + //Disable the watchdog + outw(0x0,devpriv->i_IobaseAddon+ APCI2016_WATCHDOG_ENABLEDISABLE); + //Loading the Reload value + outw(data[1],devpriv->i_IobaseAddon+APCI2016_WATCHDOG_RELOAD_VALUE); + data[1]=data[1]>>16; + outw(data[1],devpriv->i_IobaseAddon+APCI2016_WATCHDOG_RELOAD_VALUE+2); + } + else + { + printk("\nThe input parameters are wrong\n"); + } + return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_StartStopWriteWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure | +| comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + + switch(data[0]) + { + case 0://stop the watchdog + outw(0x0,devpriv->i_IobaseAddon+ APCI2016_WATCHDOG_ENABLEDISABLE);//disable the watchdog + break; + case 1://start the watchdog + outw(0x0001,devpriv->i_IobaseAddon+ APCI2016_WATCHDOG_ENABLEDISABLE); + break; + case 2://Software trigger + outw(0x0201,devpriv->i_IobaseAddon+ APCI2016_WATCHDOG_ENABLEDISABLE); + break; + default:printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }// switch(data[0]) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_ReadWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure | +| comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + udelay(5); + data[0]= inw(devpriv->i_IobaseAddon+APCI2016_WATCHDOG_STATUS)&0x1; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_Reset(comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2016_Reset(comedi_device *dev) +{ + outw(0x0,devpriv->iobase+APCI2016_DIGITAL_OP); // Resets the digital output channels + outw(0x0,devpriv->i_IobaseAddon+ APCI2016_WATCHDOG_ENABLEDISABLE); + outw(0x0,devpriv->i_IobaseAddon+APCI2016_WATCHDOG_RELOAD_VALUE); + outw(0x0,devpriv->i_IobaseAddon+APCI2016_WATCHDOG_RELOAD_VALUE+2); + return 0; +} \ No newline at end of file diff --git a/comedi/drivers/addi-data/hwdrv_apci2016.h b/comedi/drivers/addi-data/hwdrv_apci2016.h new file mode 100644 index 00000000..2d1c8f2f --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci2016.h @@ -0,0 +1,53 @@ +/********* Definitions for APCI-2016 card *****/ + +#define APCI2016_BOARD_VENDOR_ID 0x15B8 +#define APCI2016_ADDRESS_RANGE 8 + + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI2016_DIGITAL_OP 0x04 +#define APCI2016_DIGITAL_OP_RW 4 + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_WATCHDOG 2 +#define APCI2016_DIGITAL_OP_WATCHDOG 0 +#define APCI2016_WATCHDOG_ENABLEDISABLE 12 +#define APCI2016_WATCHDOG_RELOAD_VALUE 4 +#define APCI2016_WATCHDOG_STATUS 16 + + +// Hardware Layer functions for Apci2016 + +//DO +int i_APCI2016_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) ; + +int i_APCI2016_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +int i_APCI2016_BitsDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +// TIMER +// timer value is passed as u seconds + + +int i_APCI2016_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) ; + +int i_APCI2016_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +int i_APCI2016_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +// Interrupt functions..... + +// VOID v_APCI2016_Interrupt(int irq, void *d, struct pt_regs *regs) ; + + //VOID v_APCI2016_Interrupt(int irq, void *d, struct pt_regs *regs); +// RESET +INT i_APCI2016_Reset(comedi_device *dev); diff --git a/comedi/drivers/addi-data/hwdrv_apci2032.c b/comedi/drivers/addi-data/hwdrv_apci2032.c new file mode 100644 index 00000000..a22a1d7a --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci2032.c @@ -0,0 +1,561 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci2032.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 31.10.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-2032 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "hwdrv_apci2032.h" +UINT ui_InterruptData,ui_Type; +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ConfigDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[1] : 1 Enable VCC Interrupt | +| 0 Disable VCC Interrupt | +| data[2] : 1 Enable CC Interrupt | +| 0 Disable CC Interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2032_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + ULONG ul_Command = 0; + devpriv->tsk_Current=current; + +if ( (data[0]!=0) && (data[0]!=1) ) + { + comedi_error(dev,"Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + }//if ( (data[0]!=0) && (data[0]!=1) ) + if (data[0]) + { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE ; + }// if (data[0]) + else + { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + }//else if (data[0]) + + + + if (data[1] == ADDIDATA_ENABLE) + { + ul_Command = ul_Command | 0x1; + }//if (data[1] == ADDIDATA_ENABLE) + else + { + ul_Command = ul_Command & 0xFFFFFFFE; + }//elseif (data[1] == ADDIDATA_ENABLE) + if (data[2] == ADDIDATA_ENABLE) + { + ul_Command = ul_Command | 0x2; + }//if (data[2] == ADDIDATA_ENABLE) + else + { + ul_Command = ul_Command & 0xFFFFFFFD; + }//elseif (data[2] == ADDIDATA_ENABLE) + outl( ul_Command , devpriv->iobase+APCI2032_DIGITAL_OP_INTERRUPT); + ui_InterruptData=inl( devpriv->iobase+APCI2032_DIGITAL_OP_INTERRUPT); +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2032_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_Temp,ui_Temp1; +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if(devpriv->b_OutputMemoryStatus ) + { + ui_Temp=inl(devpriv->iobase+APCI2032_DIGITAL_OP); + + }//if(devpriv->b_OutputMemoryStatus ) + else + { + ui_Temp=0; + }//if(devpriv->b_OutputMemoryStatus ) +if(data[3]==0) + { + if(data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outl(data[0],devpriv->iobase+APCI2032_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=(data[0] << (2*data[2]))|ui_Temp; + break; + + + case 4:data[0]=(data[0] << (4*data[2]))|ui_Temp; + break; + + case 8: + data[0]=(data[0] <<(8*data[2]))|ui_Temp; + break; + + case 16: + data[0]=(data[0] <<(16*data[2]))|ui_Temp; + break; + case 31:data[0]=data[0]|ui_Temp; + break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outl(data[0],devpriv->iobase+APCI2032_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==0) +else + { + if(data[3]==1) + { + if(data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<iobase+APCI2032_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2*data[2]))^0xffffffff)& ui_Temp; + break; + + + case 4:data[0]=~data[0]&0xf; + ui_Temp1=15; + ui_Temp1=ui_Temp1<<4*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (4*data[2]))^0xffffffff)&ui_Temp; + break; + + case 8:data[0]=~data[0]&0xff; + ui_Temp1=255; + ui_Temp1=ui_Temp1<<8*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (8*data[2]))^0xffffffff)&ui_Temp; + break; + + case 16:data[0]=~data[0]&0xffff; + ui_Temp1=65535; + ui_Temp1=ui_Temp1<<16*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (16*data[2]))^0xffffffff)&ui_Temp; + break; + + case 31: break; + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outl(data[0],devpriv->iobase+APCI2032_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }//if else data[3]==1) + }//if else data[3]==0) + return (insn->n);; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ReadDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2032_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel=CR_CHAN(insn->chanspec); + ui_Temp=data[0]; + *data=inl(devpriv->iobase+APCI2032_DIGITAL_OP_RW); + if (ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + } //if (ui_Temp==0) + else + { + if (ui_Temp==1) + { + switch( ui_NoOfChannel) + { + + case 2: + *data=(*data >>(2*data[1]))&3; + break; + + + case 4: + *data=(*data >>(4*data[1]))&15; + break; + + case 8: + *data=(*data >>(8*data[1]))&255; + break; + + case 16: + *data=(*data >>(16*data[1]))&65535; + break; + + case 31: break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + }//switch(ui_NoOfChannels) + }//if (ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + }//elseif (ui_Temp==1) + } +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI2032_ConfigWatchdog(comedi_device + *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)| +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI2032_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +if(data[0]==0) + { + //Disable the watchdog + outl(0x0,devpriv->iobase+APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_PROG); + //Loading the Reload value + outl(data[1],devpriv->iobase+APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_RELOAD_VALUE); + } +else + { + printk("\nThe input parameters are wrong\n"); + return -EINVAL; + } + +return insn->n; +} + + + + + + /* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_StartStopWriteWatchdog | +| (comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2032_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + switch(data[0]) + { + case 0://stop the watchdog + outl(0x0,devpriv->iobase +APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_PROG );//disable the watchdog + break; + case 1://start the watchdog + outl(0x0001,devpriv->iobase+APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_PROG); + break; + case 2://Software trigger + outl(0x0201,devpriv->iobase+APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_PROG); + break; + default:printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } +return insn->n; +} + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ReadWatchdog | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2032_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) + { + + data[0]= inl(devpriv->iobase+APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_TRIG_STATUS )&0x1; +return insn->n; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : void v_APCI2032_Interrupt | +| (int irq , void *d, struct pt_regs *regs) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | +| struct pt_regs *regs : structure pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + void v_APCI2032_Interrupt(int irq, void *d, struct pt_regs *regs) +{ + comedi_device *dev = d; + unsigned int ui_DO; + + ui_DO=inl(devpriv->iobase+APCI2032_DIGITAL_OP_IRQ)&0x1;//Check if VCC OR CC interrupt has occured. + + if(ui_DO==0) + { + printk("\nInterrupt from unKnown source\n"); + }// if(ui_DO==0) + if (ui_DO) + { + // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. + ui_Type=inl(devpriv->iobase+ APCI2032_DIGITAL_OP_INTERRUPT_STATUS)&0x3; + outl(0x0,devpriv->iobase+APCI2032_DIGITAL_OP+APCI2032_DIGITAL_OP_INTERRUPT); + if (ui_Type==1) + { + //Sends signal to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + }// if (ui_Type==1) + else + { + if (ui_Type==2) + { + // Sends signal to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + }//if (ui_Type==2) + }//else if (ui_Type==1) + } //if(ui_DO) + + return; + + } + + + + + + + + + + + + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ReadInterruptStatus | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task :Reads the interrupt status register | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2032_ReadInterruptStatus(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + *data=ui_Type; + return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_Reset(comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task :Resets the registers of the card | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2032_Reset(comedi_device *dev) +{ +devpriv->b_DigitalOutputRegister=0; +ui_Type=0; +outl(0x0,devpriv->iobase+APCI2032_DIGITAL_OP);//Resets the output channels +outl(0x0,devpriv->iobase+APCI2032_DIGITAL_OP_INTERRUPT);//Disables the interrupt. +outl(0x0,devpriv->iobase+APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_PROG);//disable the watchdog +outl(0x0,devpriv->iobase+APCI2032_DIGITAL_OP_WATCHDOG+APCI2032_TCW_RELOAD_VALUE);//reload=0 +return 0; +} + + diff --git a/comedi/drivers/addi-data/hwdrv_apci2032.h b/comedi/drivers/addi-data/hwdrv_apci2032.h new file mode 100644 index 00000000..0e642866 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci2032.h @@ -0,0 +1,62 @@ +/********* Definitions for APCI-2032 card *****/ + +// Card Specific information +#define APCI2032_BOARD_VENDOR_ID 0x15B8 +#define APCI2032_ADDRESS_RANGE 63 + + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI2032_DIGITAL_OP 0 +#define APCI2032_DIGITAL_OP_RW 0 +#define APCI2032_DIGITAL_OP_INTERRUPT 4 +#define APCI2032_DIGITAL_OP_IRQ 12 + +//Digital Output Interrupt Status +#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS 8 + +//Digital Output Interrupt Enable Disable. +#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1 +#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE +#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2 +#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_WATCHDOG 2 +#define APCI2032_DIGITAL_OP_WATCHDOG 16 +#define APCI2032_TCW_RELOAD_VALUE 4 +#define APCI2032_TCW_TIMEBASE 8 +#define APCI2032_TCW_PROG 12 +#define APCI2032_TCW_TRIG_STATUS 16 +#define APCI2032_TCW_IRQ 20 + + + + +// Hardware Layer functions for Apci2032 + + +//DO +int i_APCI2032_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI2032_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI2032_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI2032_ReadInterruptStatus(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +// TIMER +// timer value is passed as u seconds +INT i_APCI2032_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI2032_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI2032_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +// Interrupt functions..... + +void v_APCI2032_Interrupt(int irq, void *d, struct pt_regs *regs) ; + +//Reset functions + int i_APCI2032_Reset(comedi_device *dev); diff --git a/comedi/drivers/addi-data/hwdrv_apci2200.c b/comedi/drivers/addi-data/hwdrv_apci2200.c new file mode 100644 index 00000000..d530b0bb --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci2200.c @@ -0,0 +1,492 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci2200.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Karl Andrade | Date : 18.12.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-2200 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci2200.h" + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_Read1DigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI2200_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_TmpValue=0; + UINT ui_Channel; + ui_Channel=CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <=7) + { + ui_TmpValue=(UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP); + *data = (ui_TmpValue >> ui_Channel)&0x1 ; + }//if(ui_Channel >= 0 && ui_Channel <=7) + else + { + printk("\nThe specified channel does not exist\n"); + return -EINVAL; // "sorry channel spec wrong " + }//else if(ui_Channel >= 0 && ui_Channel <=7) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ReadMoreDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + + UINT ui_PortValue=data[0]; + UINT ui_Mask=0; + UINT ui_NoOfChannels; + + ui_NoOfChannels=CR_CHAN(insn->chanspec); + + *data=(UINT)inw(devpriv->iobase + APCI2200_DIGITAL_IP ); + switch (ui_NoOfChannels) + { + case 2:ui_Mask=3; + *data=(*data >>(2*ui_PortValue))&ui_Mask; + break; + case 4:ui_Mask=15; + *data=(*data >>(4*ui_PortValue))&ui_Mask; + break; + case 7:break; + + default: + printk("\nWrong parameters\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + }//switch(ui_NoOfChannels) + + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ConfigDigitalOutput (comedi_device *dev, + comedi_subdevice *s comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| data[0] :1:Memory on | +| 0:Memory off | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2200_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){ + devpriv->b_OutputMemoryStatus=data[0]; +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_Temp,ui_Temp1; +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if(devpriv->b_OutputMemoryStatus ) + { + ui_Temp=inw(devpriv->iobase+APCI2200_DIGITAL_OP); + + }//if(devpriv->b_OutputMemoryStatus ) + else + { + ui_Temp=0; + }//if(devpriv->b_OutputMemoryStatus ) +if(data[3]==0) + { + if(data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outw(data[0],devpriv->iobase+APCI2200_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=(data[0] << (2*data[2]))|ui_Temp; + break; + + + case 4:data[0]=(data[0] << (4*data[2]))|ui_Temp; + break; + + case 8: data[0]=(data[0] << (8*data[2]))|ui_Temp; + break; + case 15: data[0]=data[0]|ui_Temp; + break; + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outw(data[0],devpriv->iobase+APCI2200_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==0) +else + { + if(data[3]==1) + { + if(data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<iobase+APCI2200_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2*data[2]))^0xffff)& ui_Temp; + break; + + + case 4:data[0]=~data[0]&0xf; + ui_Temp1=15; + ui_Temp1=ui_Temp1<<4*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (4*data[2]))^0xffff)&ui_Temp; + break; + + case 8: data[0]=~data[0]&0xff; + ui_Temp1=255; + ui_Temp1=ui_Temp1<<8*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (8*data[2]))^0xffff)&ui_Temp; + break; + case 15: break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + + outw(data[0],devpriv->iobase+APCI2200_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }//if else data[3]==1) + }//if else data[3]==0) + return (insn->n);; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ReadDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + +UINT ui_Temp; +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel +ui_Temp=data[0]; +*data=inw(devpriv->iobase+APCI2200_DIGITAL_OP); +if(ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + }//if(ui_Temp==0) +else + { + if(ui_Temp==1) + { + switch( ui_NoOfChannel) + { + + case 2:*data=(*data >>(2*data[1]))&3; + break; + + + case 4:*data=(*data >>(4*data[1]))&15; + break; + + case 8: *data=(*data >>(8*data[1]))&255; + break; + + case 15: break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + + }//switch(ui_NoOfChannels) + }//if(ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + }//elseif(ui_Temp==1) + }//elseif(ui_Temp==0) +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ConfigWatchdog(comedi_device *dev, + comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2200_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +if(data[0]==0) + { + //Disable the watchdog + outw(0x0,devpriv->iobase+APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); + //Loading the Reload value + outw(data[1],devpriv->iobase+APCI2200_WATCHDOG + APCI2200_WATCHDOG_RELOAD_VALUE); + data[1]=data[1]>>16; + outw(data[1],devpriv->iobase+APCI2200_WATCHDOG + APCI2200_WATCHDOG_RELOAD_VALUE+2); + }//if(data[0]==0) +else + { + printk("\nThe input parameters are wrong\n"); + return -EINVAL; + }//elseif(data[0]==0) + +return insn->n; +} + + /* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_StartStopWriteWatchdog | +| (comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2200_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + switch(data[0]) + { + case 0://stop the watchdog + outw(0x0,devpriv->iobase+APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);//disable the watchdog + break; + case 1://start the watchdog + outw(0x0001,devpriv->iobase+APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); + break; + case 2://Software trigger + outw(0x0201,devpriv->iobase+APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); + break; + default:printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }// switch(data[0]) +return insn->n; +} +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ReadWatchdog | +| (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s, :pointer to subdevice structure + comedi_insn *insn :pointer to insn structure | +| lsampl_t *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2200_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) + { + data[0]= inw(devpriv->iobase+APCI2200_WATCHDOG +APCI2200_WATCHDOG_STATUS)&0x1; +return insn->n; +} +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_Reset(comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_Reset(comedi_device *dev) +{ + outw(0x0 ,devpriv->iobase+APCI2200_DIGITAL_OP);//RESETS THE DIGITAL OUTPUTS + outw(0x0,devpriv->iobase+APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); + outw(0x0,devpriv->iobase+APCI2200_WATCHDOG +APCI2200_WATCHDOG_RELOAD_VALUE); + outw(0x0,devpriv->iobase+APCI2200_WATCHDOG +APCI2200_WATCHDOG_RELOAD_VALUE+2); + return 0; +} + + diff --git a/comedi/drivers/addi-data/hwdrv_apci2200.h b/comedi/drivers/addi-data/hwdrv_apci2200.h new file mode 100644 index 00000000..a71d1668 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci2200.h @@ -0,0 +1,48 @@ +/********* Definitions for APCI-2200 card *****/ + +// Card Specific information +#define APCI2200_BOARD_VENDOR_ID 0x15b8 +#define APCI2200_ADDRESS_RANGE 64 + + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI2200_DIGITAL_OP 4 +#define APCI2200_DIGITAL_IP 0 + + + + +// TIMER COUNTER WATCHDOG DEFINES + +#define APCI2200_WATCHDOG 0x08 +#define APCI2200_WATCHDOG_ENABLEDISABLE 12 +#define APCI2200_WATCHDOG_RELOAD_VALUE 4 +#define APCI2200_WATCHDOG_STATUS 16 + + +// Hardware Layer functions for Apci2200 + + +//Digital Input +INT i_APCI2200_ReadMoreDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI2200_Read1DigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + + + +//Digital Output +int i_APCI2200_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI2200_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI2200_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) ; + + +// TIMER +int i_APCI2200_ConfigWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI2200_StartStopWriteWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI2200_ReadWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + +//reset +INT i_APCI2200_Reset(comedi_device *dev); + diff --git a/comedi/drivers/addi-data/hwdrv_apci3120.c b/comedi/drivers/addi-data/hwdrv_apci3120.c new file mode 100644 index 00000000..effd7b64 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -0,0 +1,2441 @@ + + + +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : hwdrv_apci3120.c | Version : 2.96 Redhat Linux | + | | kernel-2.4.2 | + +-------------------------------+---------------------------------------+ + | Author : | Date : | + +-----------------------------------------------------------------------+ + | Description :APCI3120 Module . Hardware abstraction Layer for APCI3120| + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + + + + + +#include "hwdrv_apci3120.h" +static UINT ui_Temp=0; + +// FUNCTION DEFINITIONS + +/* ++----------------------------------------------------------------------------+ +| ANALOG INPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev,| +| comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Calls card specific function | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + + + +int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, + lsampl_t *data) +{ + UINT i; + + if((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE)) + return -1 ; + + // Check for Conversion time to be added ?? + devpriv->ui_EocEosConversionTime=data[2]; + + if(data[0] == APCI3120_EOS_MODE) + { + + //Test the number of the channel + for(i=0;i=this_board->i_NbrAiChannel) + { + printk("bad channel list\n"); + return -2; + } + } + + devpriv->b_InterruptMode= APCI3120_EOS_MODE; + + if(data[1]) + { + devpriv->b_EocEosInterrupt=APCI3120_ENABLE; + } + else devpriv->b_EocEosInterrupt=APCI3120_DISABLE; + // Copy channel list and Range List to devpriv + + devpriv->ui_AiNbrofChannels= data[3]; + for(i=0;i< devpriv->ui_AiNbrofChannels;i++) + { + devpriv->ui_AiChannelList[i]=data[4+i]; + } + + + } + else // EOC + { + devpriv->b_InterruptMode=APCI3120_EOC_MODE; + if(data[1]) + { + devpriv->b_EocEosInterrupt=APCI3120_ENABLE; + } + else + { + devpriv->b_EocEosInterrupt=APCI3120_DISABLE; + } + } + + return insn->n; +} + + + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnReadAnalogInput(comedi_device *dev, | +| comedi_subdevice *s,comedi_insn *insn, lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : card specific function | +| Reads analog input in synchronous mode | +| EOC and EOS is selected as per configured | +| if no conversion time is set uses default conversion | +| time 10 microsec. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnReadAnalogInput(comedi_device *dev, comedi_subdevice *s, + comedi_insn *insn, lsampl_t *data) +{ + USHORT us_ConvertTiming,us_TmpValue,i; + BYTE b_Tmp; + + // fix convertion time to 10 us + if(!devpriv->ui_EocEosConversionTime) + { + printk("No timer0 Value using 10 us\n"); + us_ConvertTiming=10; + } + else us_ConvertTiming =(USHORT) (devpriv->ui_EocEosConversionTime/1000);// nano to useconds + + // this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); + + // Clear software registers + devpriv->b_TimerSelectMode=0; + devpriv->b_ModeSelectRegister=0; + devpriv->us_OutputRegister=0; + devpriv->b_DigitalOutputRegister=0; + + if(insn->unused[0]==222)// second insn read + { + + for(i=0;i< insn->n;i++) + { + data[i]=devpriv->ui_AiReadData[i]; + } + + } + else + { + devpriv->tsk_Current=current; // Save the current process task structure + //Testing if board have the new Quartz and calculate the time value + //to set in the timer + + us_TmpValue=(USHORT) inw(devpriv->iobase+APCI3120_RD_STATUS); + if((us_TmpValue & 0x00B0)==0x00B0) + { + us_ConvertTiming=(us_ConvertTiming * 2) -2; + } + else + { + us_ConvertTiming=((us_ConvertTiming * 12926)/10000) -1; + + } + + us_TmpValue=(USHORT)devpriv->b_InterruptMode; + + switch(us_TmpValue) + { + + case APCI3120_EOC_MODE: + + + + // Testing the interrupt flag and set the EOC bit + // Clears the FIFO + inw(devpriv->iobase+APCI3120_RESET_FIFO); + + + // Initialize the sequence array + + //if (!i_APCI3120_SetupChannelList(dev,s,1,chanlist,0)) return -EINVAL; + + if (!i_APCI3120_SetupChannelList(dev,s,1,&insn->chanspec,0)) return -EINVAL; + + //Initialize Timer 0 mode 4 + devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode & 0xFC) |APCI3120_TIMER_0_MODE_4; + outb(devpriv->b_TimerSelectMode,devpriv->iobase+APCI3120_TIMER_CRT1); + + // Reset the scan bit and Disables the EOS, DMA, EOC interrupt + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_SCAN; + + if(devpriv->b_EocEosInterrupt==APCI3120_ENABLE) + { + + //Disables the EOS,DMA and enables the EOC interrupt + devpriv->b_ModeSelectRegister=(devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT) | APCI3120_ENABLE_EOC_INT; + inw(devpriv->iobase); + + } + else + { + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER; + } + + outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + // Sets gate 0 + devpriv->us_OutputRegister=(devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR) | APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister,devpriv->iobase+APCI3120_WR_ADDRESS); + + // Select Timer 0 + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + + + //Set the convertion time + outw(us_ConvertTiming,devpriv->iobase+APCI3120_TIMER_VALUE); + + us_TmpValue=(USHORT) inw(dev->iobase+APCI3120_RD_STATUS); + + + if(devpriv->b_EocEosInterrupt==APCI3120_DISABLE) + { + + do + { + // Waiting for the end of conversion + us_TmpValue=inw(devpriv->iobase+APCI3120_RD_STATUS); + }while((us_TmpValue & APCI3120_EOC)==APCI3120_EOC); + + //Read the result in FIFO and put it in insn data pointer + us_TmpValue=inw(devpriv->iobase+0); + *data=us_TmpValue; + + inw(devpriv->iobase+APCI3120_RESET_FIFO); + } + + break; + + + case APCI3120_EOS_MODE: + + inw(devpriv->iobase); + // Clears the FIFO + inw(devpriv->iobase+APCI3120_RESET_FIFO); + // clear PA PR and disable timer 0 + + devpriv->us_OutputRegister=(devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR) | APCI3120_DISABLE_TIMER0; + + outw(devpriv->us_OutputRegister,devpriv->iobase+APCI3120_WR_ADDRESS); + + + if (!i_APCI3120_SetupChannelList(dev,s,devpriv->ui_AiNbrofChannels,devpriv->ui_AiChannelList,0)) return -EINVAL; + + //Initialize Timer 0 mode 2 + devpriv->b_TimerSelectMode = (devpriv->b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2; + outb(devpriv->b_TimerSelectMode,devpriv->iobase+APCI3120_TIMER_CRT1); + + + //Select Timer 0 + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + + //Set the convertion time + outw(us_ConvertTiming,devpriv->iobase+APCI3120_TIMER_VALUE); + + //Set the scan bit + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_ENABLE_SCAN; + outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + //If Interrupt function is loaded + if(devpriv->b_EocEosInterrupt==APCI3120_ENABLE) + { + //Disables the EOC,DMA and enables the EOS interrupt + devpriv->b_ModeSelectRegister=(devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) | APCI3120_ENABLE_EOS_INT; + inw(devpriv->iobase); + + + } + else + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER; + + outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + inw(devpriv->iobase+APCI3120_RD_STATUS); + + //Sets gate 0 + + devpriv->us_OutputRegister=devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister,devpriv->iobase+APCI3120_WR_ADDRESS); + + //Start conversion + outw(0,devpriv->iobase+APCI3120_START_CONVERSION); + + //Waiting of end of convertion if interrupt is not installed + if(devpriv->b_EocEosInterrupt==APCI3120_DISABLE) + { + //Waiting the end of convertion + do + { + us_TmpValue=inw(devpriv->iobase+APCI3120_RD_STATUS); + } + while((us_TmpValue & APCI3120_EOS)!=APCI3120_EOS); + + for(i=0;i< devpriv->ui_AiNbrofChannels;i++) + { + //Read the result in FIFO and write them in shared memory + us_TmpValue=inw(devpriv->iobase); + data[i]=(UINT) us_TmpValue; + + } + + devpriv->b_InterruptMode = APCI3120_EOC_MODE; // Restore defaults. + } + break; + + default: + printk("inputs wrong\n"); + + } + devpriv->ui_EocEosConversionTime=0;// re initializing the variable; + } + + return insn->n; + +} + + + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_StopCyclicAcquisition(comedi_device *dev,| +| comedi_subdevice *s)| +| | ++----------------------------------------------------------------------------+ +| Task : Stops Cyclic acquisition | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| | ++----------------------------------------------------------------------------+ +| Return Value :0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_StopCyclicAcquisition(comedi_device *dev,comedi_subdevice *s) +{ + // Disable A2P Fifo write and AMWEN signal + outw(0,devpriv->i_IobaseAddon + 4); + + //Disable Bus Master ADD ON + outw(APCI3120_ADD_ON_AGCSTS_LOW,devpriv->i_IobaseAddon+0); + outw(0,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_AGCSTS_HIGH,devpriv->i_IobaseAddon+0); + outw(0,devpriv->i_IobaseAddon+2); + + //Disable BUS Master PCI + outl(0,devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR ); + + //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR)&(~AINT_WRITE_COMPL), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); // stop amcc irqs + //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR)&(~EN_A2P_TRANSFERS), devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR); // stop DMA + + + //Disable ext trigger + i_APCI3120_ExttrigDisable(dev); + + devpriv->us_OutputRegister=0; + //stop counters + outw(devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1,dev->iobase+APCI3120_WR_ADDRESS); + + outw(APCI3120_DISABLE_ALL_TIMER,dev->iobase+APCI3120_WR_ADDRESS); + + //DISABLE_ALL_INTERRUPT + outb(APCI3120_DISABLE_ALL_INTERRUPT,dev->iobase+APCI3120_WRITE_MODE_SELECT); + //Flush FIFO + inb(dev->iobase+APCI3120_RESET_FIFO); + inw(dev->iobase+APCI3120_RD_STATUS); + devpriv->ui_AiActualScan=0; + devpriv->ui_AiActualScanPosition=0; + s->async->cur_chan=0; + devpriv->ui_AiBufferPtr=0; + devpriv->b_AiContinuous=0; + devpriv->ui_DmaActualBuffer=0; + + devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; + devpriv->b_InterruptMode=APCI3120_EOC_MODE; + devpriv->b_EocEosInterrupt=APCI3120_DISABLE; + i_APCI3120_Reset(dev); + //printk("Stopped cyclic acquisition\n"); + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_CommandTestAnalogInput(comedi_device *dev| +| ,comedi_subdevice *s,comedi_cmd *cmd) | +| | ++----------------------------------------------------------------------------+ +| Task : Test validity for a command for cyclic anlog input | +| acquisition | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_cmd *cmd | ++----------------------------------------------------------------------------+ +| Return Value :0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_CommandTestAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) + { + int err=0; + int tmp;// divisor1,divisor2; + + // step 1: make sure trigger sources are trivially valid + + tmp=cmd->start_src; + cmd->start_src &= TRIG_NOW|TRIG_EXT; + if(!cmd->start_src || tmp!=cmd->start_src)err++; + + tmp=cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER|TRIG_FOLLOW; + if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++; + + tmp=cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + if(!cmd->convert_src || tmp!=cmd->convert_src)err++; + + tmp=cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++; + + tmp=cmd->stop_src; + cmd->stop_src &= TRIG_COUNT|TRIG_NONE; + if(!cmd->stop_src || tmp!=cmd->stop_src)err++; + + if(err) return 1; + + + //step 2: make sure trigger sources are unique and mutually compatible + + if(cmd->start_src!=TRIG_NOW && cmd->start_src!=TRIG_EXT) + { + err++; + } + + + if(cmd->scan_begin_src!=TRIG_TIMER && + cmd->scan_begin_src!=TRIG_FOLLOW) err++; + + if(cmd->convert_src!=TRIG_TIMER ) err++; + + if(cmd->scan_end_src!=TRIG_COUNT) + { + cmd->scan_end_src=TRIG_COUNT; + err++; + } + + if(cmd->stop_src!=TRIG_NONE && + cmd->stop_src!=TRIG_COUNT ) err++; + + if(err) return 2; + + + // step 3: make sure arguments are trivially compatible + + if(cmd->start_arg!=0) + { + cmd->start_arg=0; + err++; + } + + if(cmd->scan_begin_src==TRIG_TIMER) // Test Delay timing + { + if(cmd->scan_begin_argui_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_argui_MinAcquisitiontimeNs)) + { + cmd->convert_arg=this_board->ui_MinAcquisitiontimeNs; + err++; + } + } + else + { + if(cmd->convert_argui_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_argconvert_arg*cmd->scan_end_arg) + { + cmd->scan_begin_arg=cmd->convert_arg*cmd->scan_end_arg; + err++; + } + } + + if(err)return 4; + + + return 0; + } + + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_CommandAnalogInput(comedi_device *dev, | +| comedi_subdevice *s) | +| | ++----------------------------------------------------------------------------+ +| Task : Does asynchronous acquisition | +| Determines the mode 1 or 2. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + int i_APCI3120_CommandAnalogInput(comedi_device *dev,comedi_subdevice *s) +{ + comedi_cmd *cmd=&s->async->cmd; + + //loading private structure with cmd structure inputs + devpriv->ui_AiFlags=cmd->flags; + devpriv->ui_AiNbrofChannels=cmd->chanlist_len; + devpriv->ui_AiScanLength=cmd->scan_end_arg; + devpriv->pui_AiChannelList=cmd->chanlist; + devpriv->AiData=s->async->data; + devpriv->ui_AiDataLength=s->async->data_len; + + if (cmd->stop_src==TRIG_COUNT) + { + devpriv->ui_AiNbrofScans=cmd->stop_arg; + } + else + { + devpriv->ui_AiNbrofScans=0; + } + + devpriv->ui_AiTimer0=0; // variables changed to timer0,timer1 + devpriv->ui_AiTimer1=0; + if ((devpriv->ui_AiNbrofScans==0)||(devpriv->ui_AiNbrofScans==-1)) + devpriv->b_AiContinuous=1; // user want neverending analog acquisition + // stopped using cancel + + if(cmd->start_src==TRIG_EXT) + devpriv->b_ExttrigEnable = APCI3120_ENABLE; + else + devpriv->b_ExttrigEnable = APCI3120_DISABLE; + + if(cmd->scan_begin_src==TRIG_FOLLOW) + { + // mode 1 or 3 + if (cmd->convert_src==TRIG_TIMER) + { + // mode 1 + + devpriv->ui_AiTimer0=cmd->convert_arg;// timer constant in nano seconds + //return this_board->i_hwdrv_CommandAnalogInput(1,dev,s); + return i_APCI3120_CyclicAnalogInput(1,dev,s); + } + + } + if((cmd->scan_begin_src==TRIG_TIMER)&&(cmd->convert_src==TRIG_TIMER)) + { + // mode 2 + devpriv->ui_AiTimer1=cmd->scan_begin_arg; + devpriv->ui_AiTimer0=cmd->convert_arg;// variable changed timer2 to timer0 + //return this_board->i_hwdrv_CommandAnalogInput(2,dev,s); + return i_APCI3120_CyclicAnalogInput(2,dev,s); + } + return -1; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_CyclicAnalogInput(int mode, | +| comedi_device * dev,comedi_subdevice * s) | ++----------------------------------------------------------------------------+ +| Task : This is used for analog input cyclic acquisition | +| Performs the command operations. | +| If DMA is configured does DMA initialization | +| otherwise does the acquisition with EOS interrupt. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,comedi_subdevice * s) +{ + float f_DelayValue,f_ConvertValue; + BYTE b_Tmp; + UINT ui_Tmp,ui_DelayTiming=0,ui_TimerValue1=0,dmalen0=0,dmalen1=0,ui_TimerValue2=0,ui_TimerValue0,ui_ConvertTiming; + USHORT us_TmpValue; + + devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE; + //Flush FIFO + inb(dev->iobase+APCI3120_RESET_FIFO); + inw(dev->iobase+APCI3120_RD_STATUS); + + + // clear software registers + + devpriv->b_TimerSelectMode=0; + devpriv->b_DigitalOutputRegister=0; + devpriv->us_OutputRegister=0; + devpriv->b_ModeSelectRegister=0; + + /****************************/ + /* Clear Timer Write TC INT */ + /****************************/ + + outl(APCI3120_CLEAR_WRITE_TC_INT,devpriv->i_IobaseAmcc+ APCI3120_AMCC_OP_REG_INTCSR); + + /************************************/ + /* Clears the timer status register */ + /************************************/ + inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); + + + /**************************/ + /* Disables All Timer */ + /* Sets PR and PA to 0 */ + /**************************/ + + devpriv->us_OutputRegister = devpriv->us_OutputRegister &APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 &APCI3120_CLEAR_PA_PR ; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + + + devpriv->ui_AiActualScan=0; + devpriv->ui_AiActualScanPosition=0; + s->async->cur_chan=0; + devpriv->ui_AiBufferPtr=0; + devpriv->ui_DmaActualBuffer=0; + + + + + ui_TimerValue2 = devpriv->ui_AiNbrofScans-2; // value for timer2 minus -2 has to be done .....dunno y?? + ui_ConvertTiming=devpriv->ui_AiTimer0; + + if(mode==2) ui_DelayTiming = devpriv->ui_AiTimer1; + + + // initialise sequence ram + + if (!i_APCI3120_SetupChannelList(dev, s, devpriv->ui_AiNbrofChannels, devpriv->pui_AiChannelList, 0)) + return -EINVAL; + + us_TmpValue=(USHORT) inw(dev->iobase+APCI3120_RD_STATUS); + if((us_TmpValue & 0x00B0)==0x00B0) + { + f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2); + ui_TimerValue0=(UINT)f_ConvertValue; + if (mode==2) + { + f_DelayValue = (((float)ui_DelayTiming * 0.00002) - 2); + ui_TimerValue1 = (UINT) f_DelayValue; + } + } + else + { + f_ConvertValue=(((float)ui_ConvertTiming * 0.0012926) - 1); + ui_TimerValue0=(UINT)f_ConvertValue; + if (mode == 2) + { + f_DelayValue = (((float)ui_DelayTiming * 0.000012926) - 1); + ui_TimerValue1 = (UINT) f_DelayValue; + } + } + + if(devpriv->b_ExttrigEnable==APCI3120_ENABLE) + { + i_APCI3120_ExttrigEnable(dev); // activate EXT trigger + } + switch(mode) + { + case 1: + // init timer0 in mode 2 + devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode& 0xFC) | APCI3120_TIMER_0_MODE_2; + outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); + + //Select Timer 0 + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); + + //Set the convertion time + outw(((USHORT)ui_TimerValue0),dev->iobase+APCI3120_TIMER_VALUE); + break; + + case 2: + // init timer1 in mode 2 + devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode& 0xF3) | APCI3120_TIMER_1_MODE_2; + outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); + + //Select Timer 1 + b_Tmp=((devpriv->b_DigitalOutputRegister) & 0xF0) | APCI3120_SELECT_TIMER_1_WORD; + outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); + + //Set the convertion time + outw(((USHORT)ui_TimerValue1),dev->iobase+APCI3120_TIMER_VALUE); + + // init timer0 in mode 2 + devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode& 0xFC) | APCI3120_TIMER_0_MODE_2; + outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); + + //Select Timer 0 + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); + + //Set the convertion time + outw(((USHORT)ui_TimerValue0),dev->iobase+APCI3120_TIMER_VALUE); + break; + + } + // ##########common for all modes################# + + //disable the scan bit + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN; + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + + // If DMA is disabled + if(devpriv->us_UseDma==APCI3120_DISABLE) + { + // disable EOC and enable EOS + devpriv->b_InterruptMode=APCI3120_EOS_MODE; + devpriv->b_EocEosInterrupt=APCI3120_ENABLE; + + devpriv->b_ModeSelectRegister = (devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) | APCI3120_ENABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + + + if (!devpriv->b_AiContinuous) + { + // configure Timer2 For counting EOS + //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) + devpriv->us_OutputRegister=devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2 ; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + + // DISABLE TIMER INTERRUPT + devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF; + outb(devpriv->b_ModeSelectRegister,dev->iobase + APCI3120_WRITE_MODE_SELECT); + + //(1) Init timer 2 in mode 0 and write timer value + devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_0; + outb(devpriv->b_TimerSelectMode,dev->iobase+APCI3120_TIMER_CRT1); + + //Writing LOW WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); + outw(LOWORD(ui_TimerValue2),dev->iobase+APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp,dev->iobase+APCI3120_TIMER_CRT0); + outw(HIWORD(ui_TimerValue2),dev->iobase+APCI3120_TIMER_VALUE); + + //(2) Reset FC_TIMER BIT Clearing timer status register + inb(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); + // enable timer counter and disable watch dog + devpriv->b_ModeSelectRegister=(devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_COUNTER) & APCI3120_DISABLE_WATCHDOG; + // select EOS clock input for timer 2 + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_TIMER2_SELECT_EOS; + // Enable timer2 interrupt + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT; + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + devpriv->b_Timer2Mode=APCI3120_COUNTER; + devpriv->b_Timer2Interrupt=APCI3120_ENABLE; + } + } + else + { + // If DMA Enabled + inw(dev->iobase+0);// reset EOC bit + devpriv->b_InterruptMode=APCI3120_DMA_MODE; + + // disable EOC and EOS interrupt + devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT; + + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + + + dmalen0=devpriv->ui_DmaBufferSize[0]; + dmalen1=devpriv->ui_DmaBufferSize[1]; + + if (!devpriv->b_AiContinuous) + { + + if (dmalen0>(devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2)) + { // must we fill full first buffer? + dmalen0=devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2; + } + else + if (dmalen1>(devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2-dmalen0)) // and must we fill full second buffer when first is once filled? + dmalen1=devpriv->ui_AiNbrofScans*devpriv->ui_AiScanLength*2-dmalen0; + } + + if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) + { + // don't we want wake up every scan? + if (dmalen0>(devpriv->ui_AiScanLength*2)) + { + dmalen0=devpriv->ui_AiScanLength*2; + if (devpriv->ui_AiScanLength&1) dmalen0+=2; + } + if (dmalen1>(devpriv->ui_AiScanLength*2)) + { + dmalen1=devpriv->ui_AiScanLength*2; + if (devpriv->ui_AiScanLength&1) dmalen1-=2; + if (dmalen1<4) dmalen1=4; + } + } + else + { // isn't output buff smaller that our DMA buff? + if (dmalen0>(devpriv->ui_AiDataLength)) + { + dmalen0=devpriv->ui_AiDataLength; + } + if (dmalen1>(devpriv->ui_AiDataLength)) + { + dmalen1=devpriv->ui_AiDataLength; + } + } + devpriv->ui_DmaBufferUsesize[0]=dmalen0; + devpriv->ui_DmaBufferUsesize[1]=dmalen1; + + + //Initialize DMA + + // Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS register + //1 + ui_Tmp=AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO ; + outl(ui_Tmp,devpriv->i_IobaseAmcc+AMCC_OP_REG_AGCSTS); + + // changed since 16 bit interface for add on + outw(APCI3120_ADD_ON_AGCSTS_LOW,devpriv->i_IobaseAddon+0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_AGCSTS_HIGH,devpriv->i_IobaseAddon+0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH,devpriv->i_IobaseAddon+2); + //2 No change + // A2P FIFO MANAGEMENT + // A2P fifo reset & transfer control enable + outl(APCI3120_A2P_FIFO_MANAGEMENT,devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR ); + + //3 + //beginning address of dma buf + //The 32 bit address of dma buffer is converted into two 16 bit addresses + // Can done by using _attach and put into into an array + // array used may be for differnet pages + + // DMA Start Adress Low + outw(APCI3120_ADD_ON_MWAR_LOW,devpriv->i_IobaseAddon+0); + outw((devpriv->ul_DmaBufferHw[0]& 0xFFFF),devpriv->i_IobaseAddon+2); + + // DMA Start Adress High + outw(APCI3120_ADD_ON_MWAR_HIGH,devpriv->i_IobaseAddon+0); + + // outw((devpriv->ul_DmaBufferHw[0]/65536),devpriv->i_IobaseAddon+2); + outw((devpriv->ul_DmaBufferHw[0]/65536),devpriv->i_IobaseAddon+2); + + //4 + // amount of bytes to be transfered set transfer count + // used ADDON MWTC register + //commented testing outl(devpriv->ui_DmaBufferUsesize[0], devpriv->i_IobaseAddon+AMCC_OP_REG_AMWTC); + // Nbr of acquisition LOW + + outw(APCI3120_ADD_ON_MWTC_LOW,devpriv->i_IobaseAddon + 0); + outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF),devpriv->i_IobaseAddon + 2); + + // Nbr of acquisition HIGH + outw(APCI3120_ADD_ON_MWTC_HIGH,devpriv->i_IobaseAddon + 0); + outw((devpriv->ui_DmaBufferUsesize[0]/65536),devpriv->i_IobaseAddon + 2); + + //5 + // To configure A2P FIFO + // testing outl( FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); + + //6 + //ENABLE A2P FIFO WRITE AND ENABLE AMWEN + // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 + outw(3,devpriv->i_IobaseAddon + 4); + + //7 + //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) + outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2| APCI3120_ENABLE_WRITE_TC_INT), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); + + } + + if ((devpriv->us_UseDma==APCI3120_DISABLE) && !devpriv->b_AiContinuous) + { + // set gate 2 to start conversion + devpriv->us_OutputRegister = devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + } + + + switch(mode) + { + case 1: + // set gate 0 to start conversion + devpriv->us_OutputRegister = devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + break; + case 2: + // set gate 0 and gate 1 + devpriv->us_OutputRegister= devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1; + devpriv->us_OutputRegister= devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + break; + + } + + return 0; + +} + + + + + +/* ++----------------------------------------------------------------------------+ +| INTERNAL FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_Reset(comedi_device *dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Hardware reset function | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_Reset(comedi_device *dev) +{ + unsigned int i; + unsigned short us_TmpValue; + devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; + devpriv->b_EocEosInterrupt=APCI3120_DISABLE; + devpriv->b_InterruptMode=APCI3120_EOC_MODE; + devpriv->ui_EocEosConversionTime=0; // set eoc eos conv time to 0 + devpriv->b_OutputMemoryStatus =0; + + // variables used in timer subdevice + devpriv->b_Timer2Mode=0; + devpriv->b_Timer2Interrupt=0; + devpriv->b_ExttrigEnable=0; // Disable ext trigger + + /* Disable all interrupts, watchdog for the anolog output */ + devpriv->b_ModeSelectRegister=0; + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + + // Disables all counters, ext trigger and clears PA, PR + devpriv->us_OutputRegister=0; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + + //Code to set the all anolog o/p channel to 0v + //8191 is decimal value for zero(0 v)volt in bipolar mode(default) + outw(8191|APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase+APCI3120_ANALOG_OUTPUT_1);//channel 1 + outw(8191|APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase+APCI3120_ANALOG_OUTPUT_1);//channel 2 + outw(8191|APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase+APCI3120_ANALOG_OUTPUT_1);//channel 3 + outw(8191|APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase+APCI3120_ANALOG_OUTPUT_1);//channel 4 + + outw(8191|APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase+APCI3120_ANALOG_OUTPUT_2);//channel 5 + outw(8191|APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase+APCI3120_ANALOG_OUTPUT_2);//channel 6 + outw(8191|APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase+APCI3120_ANALOG_OUTPUT_2);//channel 7 + outw(8191|APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase+APCI3120_ANALOG_OUTPUT_2);//channel 8 + + // Reset digital output to L0W + + outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT); + udelay(10); + + inw(dev->iobase+0); //make a dummy read + inb(dev->iobase+APCI3120_RESET_FIFO); // flush FIFO + inw(dev->iobase+APCI3120_RD_STATUS); // flush A/D status register + + //code to reset the RAM sequence + for (i=0;i<16;i++) + { + us_TmpValue = i<<8; //select the location + outw(us_TmpValue,dev->iobase+APCI3120_SEQ_RAM_ADDRESS); + } + return 0; +} + + + + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_SetupChannelList(comedi_device * dev, | +| comedi_subdevice * s, int n_chan,unsigned int *chanlist| +| ,char check) | +| | ++----------------------------------------------------------------------------+ +| Task :This function will first check channel list is ok or not| +|and then initialize the sequence RAM with the polarity, Gain,Channel number | +|If the last argument of function "check"is 1 then it only checks the channel| +|list is ok or not. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device * dev | +| comedi_subdevice * s | +| int n_chan | + unsigned int *chanlist + char check ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_SetupChannelList(comedi_device * dev, comedi_subdevice * s, int n_chan, unsigned int *chanlist,char check) +{ + unsigned int i;//, differencial=0, bipolar=0; + unsigned int gain; + unsigned short us_TmpValue; + /* correct channel and range number check itself comedi/range.c */ + if (n_chan<1) + { + if (!check) comedi_error(dev,"range/channel list is empty!"); + return 0; + } + + // All is ok, so we can setup channel/range list + if (check) return 1; + + //Code to set the PA and PR...Here it set PA to 0.. + devpriv->us_OutputRegister=devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR; + devpriv->us_OutputRegister= ((n_chan-1) & 0xf)<<8; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + + for (i=0; iiobase+APCI3120_SEQ_RAM_ADDRESS); + } + return 1; // we can serve this with scan logic +} + + + + + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_ExttrigEnable(comedi_device * dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Enable the external trigger | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device * dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_ExttrigEnable(comedi_device * dev) +{ + devpriv->us_OutputRegister|=APCI3120_ENABLE_EXT_TRIGGER; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + return 0; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_ExttrigDisable(comedi_device * dev) | +| | ++----------------------------------------------------------------------------+ +| Task : Disables the external trigger | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device * dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_ExttrigDisable(comedi_device * dev) +{ + devpriv->us_OutputRegister&=~APCI3120_ENABLE_EXT_TRIGGER; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + return 0; +} + + + + + + +/* ++----------------------------------------------------------------------------+ +| INTERRUPT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + + +/* ++----------------------------------------------------------------------------+ +| Function name : void v_APCI3120_Interrupt(int irq, void *d, | +| struct pt_regs *regs) | +| | +| | ++----------------------------------------------------------------------------+ +| Task :Interrupt handler for APCI3120 | +| When interrupt occurs this gets called. | +| First it finds which interrupt has been generated and | +| handles corresponding interrupt | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq | +| void *d | +| struct pt_regs *regs | +| | ++----------------------------------------------------------------------------+ +| Return Value : void | +| | ++----------------------------------------------------------------------------+ +*/ + + + void v_APCI3120_Interrupt(int irq, void *d, struct pt_regs *regs) +{ + comedi_device *dev = d; + USHORT int_daq; + + unsigned int int_amcc,ui_Check,i; + USHORT us_TmpValue; + BYTE b_DummyRead; + + comedi_subdevice *s = dev->subdevices + 0; + ui_Check=1; + + int_daq=inw(dev->iobase+APCI3120_RD_STATUS) & 0xf000; // get IRQ reasons + int_amcc=inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); // get AMCC INT register + + + + if ((!int_daq)&&(!(int_amcc&ANY_S593X_INT))) + { + comedi_error(dev,"IRQ from unknow source"); + return; + } + + outl(int_amcc|0x00ff0000, devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR);// shutdown IRQ reasons in AMCC + + int_daq = (int_daq >> 12) & 0xF; + + + if(devpriv->b_ExttrigEnable == APCI3120_ENABLE) + { + //Disable ext trigger + i_APCI3120_ExttrigDisable(dev); + devpriv->b_ExttrigEnable = APCI3120_DISABLE; + } + + //clear the timer 2 interrupt + inb(devpriv->i_IobaseAmcc+ APCI3120_TIMER_STATUS_REGISTER); + + if (int_amcc&MASTER_ABORT_INT) + comedi_error(dev,"AMCC IRQ - MASTER DMA ABORT!"); + if (int_amcc&TARGET_ABORT_INT) + comedi_error(dev,"AMCC IRQ - TARGET DMA ABORT!"); + + // Ckeck if EOC interrupt + if(((int_daq & 0x8) == 0) && (devpriv->b_InterruptMode==APCI3120_EOC_MODE)) + { + if(devpriv->b_EocEosInterrupt==APCI3120_ENABLE) + { + + // Read the AI Value + + devpriv->ui_AiReadData[0]=(UINT)inw(devpriv->iobase+0); + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + } + else + { + //Disable EOC Interrupt + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT; + outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + } + } + + + // Check If EOS interrupt + if( (int_daq & 0x2) && (devpriv->b_InterruptMode==APCI3120_EOS_MODE) ) + { + + if(devpriv->b_EocEosInterrupt==APCI3120_ENABLE)// enable this in without DMA ??? + { + + if(devpriv->b_AiCyclicAcquisition==APCI3120_ENABLE) + { + ui_Check=0; + i_APCI3120_InterruptHandleEos(dev); + devpriv->ui_AiActualScan++; + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_ENABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + } + else + { + ui_Check=0; + for(i=0;i< devpriv->ui_AiNbrofChannels;i++) + { + us_TmpValue=inw(devpriv->iobase+0); + devpriv->ui_AiReadData[i]=(UINT) us_TmpValue; + } + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + devpriv->b_InterruptMode=APCI3120_EOC_MODE; + + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + + } + + } + else + { + devpriv->b_ModeSelectRegister= devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; //Default settings + devpriv->b_InterruptMode=APCI3120_EOC_MODE; + } + + } + + //Timer2 interrupt + if(int_daq & 0x1) + { + + switch(devpriv->b_Timer2Mode) + { + case APCI3120_COUNTER: + + devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; + devpriv->b_ModeSelectRegister= devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister,dev->iobase+APCI3120_WRITE_MODE_SELECT); + + // stop timer 2 + devpriv->us_OutputRegister=devpriv->us_OutputRegister & APCI3120_DISABLE_ALL_TIMER; + outw(devpriv->us_OutputRegister,dev->iobase+APCI3120_WR_ADDRESS); + + //stop timer 0 and timer 1 + i_APCI3120_StopCyclicAcquisition(dev,s); + devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; + comedi_done(dev,s); + break; + + + case APCI3120_TIMER: + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + break; + + case APCI3120_WATCHDOG: + + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + break; + + default : + + // disable Timer Interrupt + + devpriv->b_ModeSelectRegister = devpriv-> b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT; + + outb(devpriv->b_ModeSelectRegister, dev->iobase+ APCI3120_WRITE_MODE_SELECT); + + + + + } + + b_DummyRead= inb(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); + + } + + + if ((int_daq & 0x4) &&(devpriv->b_InterruptMode == APCI3120_DMA_MODE)) + { + + //DPRINTK("\n interrupt is DMA\n"); + if(devpriv->b_AiCyclicAcquisition==APCI3120_ENABLE) + { + + /****************************/ + /* Clear Timer Write TC INT */ + /****************************/ + + outl(APCI3120_CLEAR_WRITE_TC_INT,devpriv->i_IobaseAmcc+ APCI3120_AMCC_OP_REG_INTCSR); + + /************************************/ + /* Clears the timer status register */ + /************************************/ + inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); + v_APCI3120_InterruptDma(irq,d,regs); // do some data transfer + } + else + { + outw(devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1,dev->iobase+APCI3120_WR_ADDRESS); + } + + } + + return; +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InterruptHandleEos(comedi_device *dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : This function handles EOS interrupt. | +| This function copies the acquired data(from FIFO) | +| to Comedi buffer. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InterruptHandleEos(comedi_device *dev) +{ + int n_chan,i; + sampl_t *data; + comedi_subdevice *s=dev->subdevices+0; + comedi_async *async = s->async; + data=async->data+async->buf_int_ptr;//new samples added from here onwards + n_chan=devpriv->ui_AiNbrofChannels; + for(i=0;iiobase+0); + } + async->buf_int_count+=n_chan*sizeof(sampl_t); + async->buf_int_ptr+=n_chan*sizeof(sampl_t); + comedi_eos(dev,s); + if (s->async->buf_int_ptr>=s->async->data_len) // for buffer rool over + { + /* buffer rollover */ + s->async->buf_int_ptr=0; + comedi_eobuf(dev,s); + } + return 0; +} + + + + + + +/* ++----------------------------------------------------------------------------+ +| Function name : void v_APCI3120_InterruptDma(int irq, void *d, | +| struct pt_regs *regs) | +| | ++----------------------------------------------------------------------------+ +| Task : This is a handler for the DMA interrupt | +| This function copies the data to Comedi Buffer. | +| For continuous DMA it reinitializes the DMA operation. | +| For single mode DMA it stop the acquisition. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq, void *d, struct pt_regs *regs | +| | ++----------------------------------------------------------------------------+ +| Return Value : void | +| | ++----------------------------------------------------------------------------+ +*/ + + void v_APCI3120_InterruptDma(int irq, void *d, struct pt_regs *regs) +{ + comedi_device *dev = d; + comedi_subdevice *s = dev->subdevices + 0; + sampl_t *ptr; + unsigned int next_dma_buf, samplesinbuf,m; + unsigned long low_word,high_word,var; + UINT ui_Tmp; + samplesinbuf=devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]-inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MWTC); + //rt_printk("\nSamples in buffer=%d \n", samplesinbuf); + if (samplesinbufui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) + { + comedi_error(dev,"Interrupted DMA transfer!"); + } + if (samplesinbuf & 1) + { + comedi_error(dev,"Odd count of bytes in DMA ring!"); + i_APCI3120_StopCyclicAcquisition(dev,s); + devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; + comedi_error_done(dev,s); + return; + } + samplesinbuf=samplesinbuf>>1; // number of received samples + if (devpriv->b_DmaDoubleBuffer) + { + // switch DMA buffers if is used double buffering + next_dma_buf=1-devpriv->ui_DmaActualBuffer; + ui_Tmp=AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO ; + outl(ui_Tmp,devpriv->i_IobaseAddon+AMCC_OP_REG_AGCSTS); + // changed since 16 bit interface for add on + outw(APCI3120_ADD_ON_AGCSTS_LOW,devpriv->i_IobaseAddon+0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_AGCSTS_HIGH,devpriv->i_IobaseAddon+0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH ,devpriv->i_IobaseAddon+2); // 0x1000 is out putted in windows driver + + // A2P FIFO MANAGEMENT + // A2P fifo reset & transfer control enable + outl(APCI3120_A2P_FIFO_MANAGEMENT,devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR ); + var=devpriv->ul_DmaBufferHw[next_dma_buf]; + low_word=var & 0xffff; + var=devpriv->ul_DmaBufferHw[next_dma_buf]; + high_word=var /65536; + outw(APCI3120_ADD_ON_MWAR_LOW,devpriv->i_IobaseAddon+0); + outw(low_word,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_MWAR_HIGH,devpriv->i_IobaseAddon+0); + outw(high_word,devpriv->i_IobaseAddon+2); + var=devpriv->ui_DmaBufferUsesize[next_dma_buf]; + low_word=var & 0xffff; + var=devpriv->ui_DmaBufferUsesize[next_dma_buf]; + high_word=var /65536; + outw(APCI3120_ADD_ON_MWTC_LOW,devpriv->i_IobaseAddon+0); + outw(low_word,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_MWTC_HIGH,devpriv->i_IobaseAddon+0); + outw(high_word,devpriv->i_IobaseAddon+2); + // To configure A2P FIFO + // ENABLE A2P FIFO WRITE AND ENABLE AMWEN + // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 + outw(3,devpriv->i_IobaseAddon + 4); + //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) + outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2| APCI3120_ENABLE_WRITE_TC_INT), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); + + } + + ptr=(sampl_t *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer]; + + + if(s->async->buf_int_ptr+samplesinbuf*sizeof(sampl_t)>=devpriv->ui_AiDataLength) + { + m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(sampl_t); + v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,m); + s->async->buf_int_count+=m*sizeof(sampl_t); + ptr+=m*sizeof(sampl_t); + samplesinbuf-=m; + s->async->buf_int_ptr=0; + comedi_eobuf(dev,s); + } + + if (samplesinbuf) + { + v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,samplesinbuf); + + s->async->buf_int_count+=samplesinbuf*sizeof(sampl_t); + s->async->buf_int_ptr+=samplesinbuf*sizeof(sampl_t); + if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) + { + comedi_bufcheck(dev,s); + } + } + if (!devpriv->b_AiContinuous) + if ( devpriv->ui_AiActualScan>=devpriv->ui_AiNbrofScans ) + { + // all data sampled + i_APCI3120_StopCyclicAcquisition(dev,s); + devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; + //DPRINTK("\n Single DMA completed..\n"); + comedi_done(dev,s); + return; + } + + if (devpriv->b_DmaDoubleBuffer) + { // switch dma buffers + devpriv->ui_DmaActualBuffer=1-devpriv->ui_DmaActualBuffer; + + } + else + { + // restart DMA if is not used double buffering + //ADDED REINITIALISE THE DMA + ui_Tmp=AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO ; + outl(ui_Tmp,devpriv->i_IobaseAddon+AMCC_OP_REG_AGCSTS); + + // changed since 16 bit interface for add on + outw(APCI3120_ADD_ON_AGCSTS_LOW,devpriv->i_IobaseAddon+0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_AGCSTS_HIGH,devpriv->i_IobaseAddon+0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH ,devpriv->i_IobaseAddon+2); // + // A2P FIFO MANAGEMENT + // A2P fifo reset & transfer control enable + outl(APCI3120_A2P_FIFO_MANAGEMENT,devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR ); + + var=devpriv->ul_DmaBufferHw[0]; + low_word=var & 0xffff; + var=devpriv->ul_DmaBufferHw[0]; + high_word=var/65536; + outw(APCI3120_ADD_ON_MWAR_LOW,devpriv->i_IobaseAddon+0); + outw(low_word,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_MWAR_HIGH,devpriv->i_IobaseAddon+0); + outw(high_word,devpriv->i_IobaseAddon+2); + + var=devpriv->ui_DmaBufferUsesize[0]; + low_word=var & 0xffff;//changed + var=devpriv->ui_DmaBufferUsesize[0]; + high_word=var/65536; + outw(APCI3120_ADD_ON_MWTC_LOW,devpriv->i_IobaseAddon+0); + outw(low_word,devpriv->i_IobaseAddon+2); + outw(APCI3120_ADD_ON_MWTC_HIGH,devpriv->i_IobaseAddon+0); + outw(high_word,devpriv->i_IobaseAddon+2); + + + // To configure A2P FIFO + //ENABLE A2P FIFO WRITE AND ENABLE AMWEN + // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 + outw(3,devpriv->i_IobaseAddon + 4); + //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) + outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2| APCI3120_ENABLE_WRITE_TC_INT), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); + } +} + + +/* ++----------------------------------------------------------------------------+ +| Function name :void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device| +|*dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n) | +| | ++----------------------------------------------------------------------------+ +| Task : This function copies the data from DMA buffer to the | +| Comedi buffer | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| sampl_t *dma | +| sampl_t *data,int n | ++----------------------------------------------------------------------------+ +| Return Value : void | +| | ++----------------------------------------------------------------------------+ +*/ + +void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n) +{ + int i,j,m; + + j=s->async->cur_chan; + m=devpriv->ui_AiActualScanPosition; + for(i=0;i=devpriv->ui_AiNbrofChannels) + { + m+=j; + j=0; + if(m>=devpriv->ui_AiScanLength) + { + m=0; + devpriv->ui_AiActualScan++; + if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) + comedi_eos(dev,s); + } + } + } + devpriv->ui_AiActualScanPosition=m; + s->async->cur_chan=j; + +} + + + + + + +/* ++----------------------------------------------------------------------------+ +| TIMER SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnConfigTimer(comedi_device *dev, | +| comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task :Configure Timer 2 | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | +| | +| data[0]= TIMER configure as timer | +| = WATCHDOG configure as watchdog | +| data[1] = Timer constant | +| data[2] = Timer2 interrupt (1)enable or(0) disable | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + +int i_APCI3120_InsnConfigTimer(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + + UINT ui_Timervalue2; + USHORT us_TmpValue; + BYTE b_Tmp; + + + if(!data[1]) comedi_error(dev,"config:No timer constant !"); + + devpriv->b_Timer2Interrupt=(BYTE)data[2]; // save info whether to enable or disable interrupt + + ui_Timervalue2=data[1]/1000; // convert nano seconds to u seconds + + //this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(BYTE)data[0]); + us_TmpValue=(USHORT) inw(devpriv->iobase+APCI3120_RD_STATUS); + + //Testing if board have the new Quartz and calculate the time value to set in the timer + if((us_TmpValue & 0x00B0)==0x00B0) + { + //Calculate the time value to set in the timer + ui_Timervalue2=ui_Timervalue2 / 50; + } + else + { + //Calculate the time value to set in the timer + ui_Timervalue2=ui_Timervalue2 / 70; + } + + //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) + devpriv->us_OutputRegister=devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2 ; + outw(devpriv->us_OutputRegister,devpriv->iobase+APCI3120_WR_ADDRESS); + + // Disable TIMER Interrupt + devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF; + + // Disable Eoc and Eos Interrupts + devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister,devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + if(data[0]==APCI3120_TIMER)//initialize timer + { + + //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT ; + //outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + //Set the Timer 2 in mode 2(Timer) + devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2; + outb(devpriv->b_TimerSelectMode,devpriv->iobase + APCI3120_TIMER_CRT1); + + //Configure the timer 2 for writing the LOW WORD of timer is Delay value + //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0 + //you can set the digital output and configure the timer 2,and if you don't make this, digital output + //are erase (Set to 0) + + //Writing LOW WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + outw(LOWORD(ui_Timervalue2),devpriv->iobase+APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + outw(HIWORD(ui_Timervalue2),devpriv->iobase+APCI3120_TIMER_VALUE); + // timer2 in Timer mode enabled + devpriv->b_Timer2Mode=APCI3120_TIMER; + + } + else // Initialize Watch dog + { + + + //Set the Timer 2 in mode 5(Watchdog) + + devpriv->b_TimerSelectMode=(devpriv->b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_5; + outb(devpriv->b_TimerSelectMode,devpriv->iobase + APCI3120_TIMER_CRT1); + + //Configure the timer 2 for writing the LOW WORD of timer is Delay value + //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0 + //you can set the digital output and configure the timer 2,and if you don't make this, digital output + //are erase (Set to 0) + + //Writing LOW WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + outw(LOWORD(ui_Timervalue2),devpriv->iobase+APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + outw(HIWORD(ui_Timervalue2),devpriv->iobase+APCI3120_TIMER_VALUE); + //watchdog enabled + devpriv->b_Timer2Mode=APCI3120_WATCHDOG; + + } + + + return insn->n; + +} + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnWriteTimer(comedi_device *dev, | +| comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : To start and stop the timer | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | +| | +| data[0] = 1 (start) | +| data[0] = 0 (stop ) | +| data[0] = 2 (write new value) | +| data[1]= new value | +| | +| devpriv->b_Timer2Mode = 0 DISABLE | +| 1 Timer | +| 2 Watch dog | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + +int i_APCI3120_InsnWriteTimer(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) +{ + + UINT ui_Timervalue2=0; + USHORT us_TmpValue; + BYTE b_Tmp; + + + + + if((devpriv->b_Timer2Mode!=APCI3120_WATCHDOG) && (devpriv->b_Timer2Mode!=APCI3120_TIMER)) + { + comedi_error(dev,"\nwrite:timer2 not configured "); + return -EINVAL; + } + + if(data[0]==2) // write new value + { + if(devpriv->b_Timer2Mode!=APCI3120_TIMER) + { + comedi_error(dev,"write :timer2 not configured in TIMER MODE"); + return -EINVAL; + } + + if(data[1]) ui_Timervalue2=data[1]; + else ui_Timervalue2=0; + } + + + //this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2); + + switch(data[0]) + { + case APCI3120_START: + + // Reset FC_TIMER BIT + inb(devpriv->iobase+APCI3120_TIMER_STATUS_REGISTER); + if(devpriv->b_Timer2Mode==APCI3120_TIMER) //start timer + { + //Enable Timer + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & 0x0B; + } + else //start watch dog + { + //Enable WatchDog + devpriv->b_ModeSelectRegister=(devpriv->b_ModeSelectRegister & 0x0B) | APCI3120_ENABLE_WATCHDOG; + } + + //enable disable interrupt + if((devpriv->b_Timer2Interrupt)==APCI3120_ENABLE) + { + + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT ; + // save the task structure to pass info to user + devpriv->tsk_Current=current; + } + else + { + + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT; + } + outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + + if(devpriv->b_Timer2Mode==APCI3120_TIMER) //start timer + { + //For Timer mode is Gate2 must be activated **timer started + devpriv->us_OutputRegister=devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2; + outw(devpriv->us_OutputRegister,devpriv->iobase+APCI3120_WR_ADDRESS); + } + + break; + + case APCI3120_STOP: + if(devpriv->b_Timer2Mode==APCI3120_TIMER) + { + //Disable timer + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_TIMER_COUNTER; + } + else + { + //Disable WatchDog + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_WATCHDOG; + } + // Disable timer interrupt + devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT; + + // Write above states to register + outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + // Reset Gate 2 + devpriv->us_OutputRegister=devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT ; + outw(devpriv->us_OutputRegister,devpriv->iobase+APCI3120_WR_ADDRESS); + + // Reset FC_TIMER BIT + inb(devpriv->iobase+APCI3120_TIMER_STATUS_REGISTER); + + // Disable timer + //devpriv->b_Timer2Mode=APCI3120_DISABLE; + + break; + + case 2: //write new value to Timer + if( devpriv->b_Timer2Mode!=APCI3120_TIMER) + { + comedi_error(dev,"write :timer2 not configured in TIMER MODE"); + return -EINVAL; + } + // ui_Timervalue2=data[1]; // passed as argument + us_TmpValue=(USHORT) inw(devpriv->iobase+APCI3120_RD_STATUS); + + //Testing if board have the new Quartz and calculate the time value to set in the timer + if((us_TmpValue & 0x00B0)==0x00B0) + { + //Calculate the time value to set in the timer + ui_Timervalue2=ui_Timervalue2 / 50; + } + else + { + //Calculate the time value to set in the timer + ui_Timervalue2=ui_Timervalue2 / 70; + } + //Writing LOW WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + outw(LOWORD(ui_Timervalue2),devpriv->iobase+APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + outw(HIWORD(ui_Timervalue2),devpriv->iobase+APCI3120_TIMER_VALUE); + + break; + default: + return -EINVAL;// Not a valid input + } + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_InsnReadTimer(comedi_device *dev, | +| comedi_subdevice *s,comedi_insn *insn, lsampl_t *data) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : read the Timer value | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| for Timer: data[0]= Timer constant | +| | +| for watchdog: data[0]=0 (still running) | +| data[0]=1 (run down) | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3120_InsnReadTimer(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, lsampl_t *data) +{ + BYTE b_Tmp; + USHORT us_TmpValue,us_TmpValue_2,us_StatusValue; + + if((devpriv->b_Timer2Mode!=APCI3120_WATCHDOG) && (devpriv->b_Timer2Mode!=APCI3120_TIMER)) + { + comedi_error(dev,"\nread:timer2 not configured "); + } + + + //this_board->i_hwdrv_InsnReadTimer(dev,data); + if(devpriv->b_Timer2Mode==APCI3120_TIMER) + { + + //Read the LOW WORD of Timer 2 register + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + us_TmpValue=inw(devpriv->iobase+APCI3120_TIMER_VALUE); + + //Read the HIGH WORD of Timer 2 register + b_Tmp=((devpriv->b_DigitalOutputRegister<<4) & 0xF0) | APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp,devpriv->iobase+APCI3120_TIMER_CRT0); + us_TmpValue_2=inw(devpriv->iobase+APCI3120_TIMER_VALUE); + + // combining both words + data[0]=(UINT) ( (us_TmpValue)|((us_TmpValue_2)<<16)); + + } + else // Read watch dog status + { + + us_StatusValue= inw(devpriv->iobase+APCI3120_RD_STATUS); + us_StatusValue=((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1; + if(us_StatusValue==1) + { + // RESET FC_TIMER BIT + inb(devpriv->iobase+APCI3120_TIMER_STATUS_REGISTER); + } + data[0]= us_StatusValue;// when data[0] = 1 then the watch dog has rundown + } + return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| DIGITAL INPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnReadDigitalInput(comedi_device *dev, | +| comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Reads the value of the specified Digital input channel| +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + + + +int i_APCI3120_InsnReadDigitalInput(comedi_device *dev,comedi_subdevice + *s, comedi_insn *insn,lsampl_t *data) + { + UINT ui_Chan,ui_TmpValue; + + ui_Chan = CR_CHAN(insn->chanspec); // channel specified + //this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); + if(ui_Chan >= 0 && ui_Chan <= 3) + { + ui_TmpValue=(UINT) inw(devpriv->iobase + APCI3120_RD_STATUS); + + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> (ui_Chan + 8)) & 1; + //return 0; + } + else + { + // comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } + return insn->n; + + } + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev, | +|comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Reads the value of the Digital input Port i.e.4channels| +| value is returned in data[0] | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +{ + UINT ui_TmpValue; + ui_TmpValue=(UINT) inw(devpriv->iobase+APCI3120_RD_STATUS); + /***** state of 4 channels in the 11, 10, 9, 8 bits of status reg + rotated right 8 times to bring them to last four bits + ANDed with oxf for value. + *****/ + *data=(ui_TmpValue >>8) & 0xf; + //this_board->i_hwdrv_InsnBitsDigitalInput(dev,data); + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| DIGITAL OUTPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnConfigDigitalOutput(comedi_device | +| *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task :Configure the output memory ON or OFF | +| | ++----------------------------------------------------------------------------+ +| Input Parameters :comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + + +int i_APCI3120_InsnConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +{ + + if ( (data[0]!=0) && (data[0]!=1) ) + { + comedi_error(dev,"Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } + if(data[0]) + { + devpriv->b_OutputMemoryStatus = APCI3120_ENABLE; + + } + else + { + devpriv->b_OutputMemoryStatus = APCI3120_DISABLE; + + } + if(!devpriv->b_OutputMemoryStatus ) + { + ui_Temp=0; + + }//if(!devpriv->b_OutputMemoryStatus ) + + return insn->n; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev, | +| comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : write diatal output port | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | + data[0] Value to be written + data[1] :1 Set digital o/p ON + data[1] 2 Set digital o/p OFF with memory ON ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + +int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev,comedi_subdevice + *s, comedi_insn *insn,lsampl_t *data) +{ + + + if ((data[0] > this_board->i_DoMaxdata) || (data[0]<0)) + { + + comedi_error(dev,"Data is not valid !!! \n"); + return -EINVAL; + } + + + switch(data[1]) + { + case 1 :data[0]=(data[0]<<4)|ui_Temp; + break; + + case 2 :data[0]=data[0]<<4; + break; + default :printk("\nThe parameter passed is in error \n"); + return -EINVAL; + }// switch(data[1]) + outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT); + ui_Temp=data[0]&0xF0; + + return insn->n; + +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev,| +|comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Write digiatl output | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | + data[0] Value to be written + data[1] :1 Set digital o/p ON + data[1] 2 Set digital o/p OFF with memory ON ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + +int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev,comedi_subdevice + *s,comedi_insn *insn,lsampl_t *data) +{ + + UINT ui_Temp1; + + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + + if ( (data[0]!=0) && (data[0]!=1) ) + { + comedi_error(dev,"Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } + if ( (ui_NoOfChannel > (this_board->i_NbrDoChannel-1)) || (ui_NoOfChannel < 0) ) + { + comedi_error(dev,"This board doesn't have specified channel !!! \n"); + return -EINVAL; + } + + + + switch(data[1]) + { + case 1 :data[0]=(data[0] << ui_NoOfChannel); + data[0]=(data[0]<<4)|ui_Temp; + break; + + case 2 : + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<iobase + APCI3120_DIGITAL_OUTPUT); + ui_Temp=data[0] & 0xf0; + return (insn->n); + +} + + + + + + +/* ++----------------------------------------------------------------------------+ +| ANALOG OUTPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev,| +|comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Write analog output | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_insn *insn | +| lsampl_t *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev,comedi_subdevice + *s, comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Range,ui_Channel; + USHORT us_TmpValue; + + ui_Range = CR_RANGE(insn->chanspec); + ui_Channel = CR_CHAN(insn->chanspec); + + //this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]); + if(ui_Range) // if 1 then unipolar + { + + if(data[0]!=0) + data[0]=((((ui_Channel & 0x03)<<14) & 0xC000) | (1<<13) | (data[0]+8191)); + else + data[0]=((((ui_Channel & 0x03)<<14) & 0xC000) | (1<<13) | 8192); + + } + else // if 0 then bipolar + { + data[0]= ((((ui_Channel & 0x03)<<14) & 0xC000) | (0<<13) | data[0]); + + } + + + + //out put n values at the given channel. + // rt_printk("\nwaiting for DA_READY BIT"); + do //Waiting of DA_READY BIT + { + us_TmpValue=((USHORT) inw(devpriv->iobase+APCI3120_RD_STATUS)) & 0x0001; + } while(us_TmpValue!=0x0001); + + if(ui_Channel<=3) + // for channel 0-3 out at the register 1 (wrDac1-8) + // data[i] typecasted to ushort since word write is to be done + outw((USHORT)data[0],devpriv->iobase+ APCI3120_ANALOG_OUTPUT_1); + else + // for channel 4-7 out at the register 2 (wrDac5-8) + //data[i] typecasted to ushort since word write is to be done + outw((USHORT)data[0],devpriv->iobase+ APCI3120_ANALOG_OUTPUT_2); + + return insn->n; +} + + diff --git a/comedi/drivers/addi-data/hwdrv_apci3120.h b/comedi/drivers/addi-data/hwdrv_apci3120.h new file mode 100644 index 00000000..c653d712 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci3120.h @@ -0,0 +1,260 @@ + +// hwdrv_apci3120.h + + +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : hwdrv_apci3120.h | Version : 2.96 Redhat Linux | + | | kernel-2.4.2 | + +-------------------------------+---------------------------------------+ + | Author : | Date : | + +-----------------------------------------------------------------------+ + | Description :Header file for apci3120 hardware abstraction layer | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + + + + + +// comedi related defines + +//ANALOG INPUT RANGE +comedi_lrange range_apci3120_ai={ 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1) + } +}; + +// ANALOG OUTPUT RANGE +comedi_lrange range_apci3120_ao= { 2, { + BIP_RANGE(10), + UNI_RANGE(10) + } +}; + +#define APCI3120_BIPOLAR_RANGES 4 // used for test on mixture of BIP/UNI ranges + + +#define APCI3120_BOARD_VENDOR_ID 0x10E8 +#define APCI3120_ADDRESS_RANGE 16 + +#define APCI3120_DISABLE 0 +#define APCI3120_ENABLE 1 + +#define APCI3120_START 1 +#define APCI3120_STOP 0 + +#define APCI3120_EOC_MODE 1 +#define APCI3120_EOS_MODE 2 +#define APCI3120_DMA_MODE 3 + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI3120_DIGITAL_OUTPUT 0x0D +#define APCI3120_RD_STATUS 0x02 +#define APCI3120_RD_FIFO 0x00 + +// digital output insn_write ON /OFF selection +#define APCI3120_SET4DIGITALOUTPUTON 1 +#define APCI3120_SET4DIGITALOUTPUTOFF 0 + +// analog output SELECT BIT +#define APCI3120_ANALOG_OP_CHANNEL_1 0x0000 +#define APCI3120_ANALOG_OP_CHANNEL_2 0x4000 +#define APCI3120_ANALOG_OP_CHANNEL_3 0x8000 +#define APCI3120_ANALOG_OP_CHANNEL_4 0xC000 +#define APCI3120_ANALOG_OP_CHANNEL_5 0x0000 +#define APCI3120_ANALOG_OP_CHANNEL_6 0x4000 +#define APCI3120_ANALOG_OP_CHANNEL_7 0x8000 +#define APCI3120_ANALOG_OP_CHANNEL_8 0xC000 + +// Enable external trigger bit in nWrAddress +#define APCI3120_ENABLE_EXT_TRIGGER 0x8000 + +//ANALOG OUTPUT AND INPUT DEFINE +#define APCI3120_UNIPOLAR 0x80 //$$ RAM sequence polarity BIT +#define APCI3120_BIPOLAR 0x00 //$$ RAM sequence polarity BIT +#define APCI3120_ANALOG_OUTPUT_1 0x08 // (ADDRESS ) +#define APCI3120_ANALOG_OUTPUT_2 0x0A // (ADDRESS ) +#define APCI3120_1_GAIN 0x00 //$$ RAM sequence Gain Bits for gain 1 +#define APCI3120_2_GAIN 0x10 //$$ RAM sequence Gain Bits for gain 2 +#define APCI3120_5_GAIN 0x20 //$$ RAM sequence Gain Bits for gain 5 +#define APCI3120_10_GAIN 0x30 //$$ RAM sequence Gain Bits for gain 10 +#define APCI3120_SEQ_RAM_ADDRESS 0x06 //$$ EARLIER NAMED APCI3120_FIFO_ADDRESS +#define APCI3120_RESET_FIFO 0x0C //(ADDRESS) +#define APCI3120_TIMER_0_MODE_2 0x01 //$$ Bits for timer mode +#define APCI3120_TIMER_0_MODE_4 0x2 +#define APCI3120_SELECT_TIMER_0_WORD 0x00 +#define APCI3120_ENABLE_TIMER0 0x1000 //$$Gatebit 0 in nWrAddress +#define APCI3120_CLEAR_PR 0xF0FF +#define APCI3120_CLEAR_PA 0xFFF0 +#define APCI3120_CLEAR_PA_PR (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA) + +// nWrMode_Select +#define APCI3120_ENABLE_SCAN 0x8 //$$ bit in nWrMode_Select +#define APCI3120_DISABLE_SCAN (~APCI3120_ENABLE_SCAN) +#define APCI3120_ENABLE_EOS_INT 0x2 //$$ bit in nWrMode_Select + +#define APCI3120_DISABLE_EOS_INT (~APCI3120_ENABLE_EOS_INT) +#define APCI3120_ENABLE_EOC_INT 0x1 +#define APCI3120_DISABLE_EOC_INT (~APCI3120_ENABLE_EOC_INT) +#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT) +#define APCI3120_DISABLE_ALL_INTERRUPT (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT) + +//status register bits +#define APCI3120_EOC 0x8000 +#define APCI3120_EOS 0x2000 + +// software trigger dummy register +#define APCI3120_START_CONVERSION 0x02 //(ADDRESS) + +//TIMER DEFINE +#define APCI3120_QUARTZ_A 70 +#define APCI3120_QUARTZ_B 50 +#define APCI3120_TIMER 1 +#define APCI3120_WATCHDOG 2 +#define APCI3120_TIMER_DISABLE 0 +#define APCI3120_TIMER_ENABLE 1 +#define APCI3120_ENABLE_TIMER2 0x4000 //$$ gatebit 2 in nWrAddress +#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2) +#define APCI3120_ENABLE_TIMER_INT 0x04 //$$ ENAIRQ_FC_Bit in nWrModeSelect +#define APCI3120_DISABLE_TIMER_INT (~APCI3120_ENABLE_TIMER_INT) +#define APCI3120_WRITE_MODE_SELECT 0x0E // (ADDRESS) +#define APCI3120_SELECT_TIMER_0_WORD 0x00 +#define APCI3120_SELECT_TIMER_1_WORD 0x01 +#define APCI3120_TIMER_1_MODE_2 0x4 + +//$$ BIT FOR MODE IN nCsTimerCtr1 +#define APCI3120_TIMER_2_MODE_0 0x0 +#define APCI3120_TIMER_2_MODE_2 0x10 +#define APCI3120_TIMER_2_MODE_5 0x30 + +//$$ BIT FOR MODE IN nCsTimerCtr0 +#define APCI3120_SELECT_TIMER_2_LOW_WORD 0x02 +#define APCI3120_SELECT_TIMER_2_HIGH_WORD 0x03 + +#define APCI3120_TIMER_CRT0 0x0D //(ADDRESS for cCsTimerCtr0) +#define APCI3120_TIMER_CRT1 0x0C //(ADDRESS for cCsTimerCtr1) + +#define APCI3120_TIMER_VALUE 0x04 //ADDRESS for nCsTimerWert +#define APCI3120_TIMER_STATUS_REGISTER 0x0D //ADDRESS for delete timer 2 interrupt +#define APCI3120_RD_STATUS 0x02 //ADDRESS +#define APCI3120_WR_ADDRESS 0x00 //ADDRESS +#define APCI3120_ENABLE_WATCHDOG 0x20 //$$BIT in nWrMode_Select +#define APCI3120_DISABLE_WATCHDOG (~APCI3120_ENABLE_WATCHDOG) +#define APCI3120_ENABLE_TIMER_COUNTER 0x10 //$$BIT in nWrMode_Select +#define APCI3120_DISABLE_TIMER_COUNTER (~APCI3120_ENABLE_TIMER_COUNTER) +#define APCI3120_FC_TIMER 0x1000 //bit in status register +#define APCI3120_ENABLE_TIMER0 0x1000 +#define APCI3120_ENABLE_TIMER1 0x2000 +#define APCI3120_ENABLE_TIMER2 0x4000 +#define APCI3120_DISABLE_TIMER0 (~APCI3120_ENABLE_TIMER0) +#define APCI3120_DISABLE_TIMER1 (~APCI3120_ENABLE_TIMER1) +#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2) + +#define APCI3120_TIMER2_SELECT_EOS 0xC0 // ADDED on 20-6 +#define APCI3120_COUNTER 3 // on 20-6 +#define APCI3120_DISABLE_ALL_TIMER ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 )// on 20-6 + + + + +#define MAX_ANALOGINPUT_CHANNELS 32 + +typedef struct +{ + BYTE b_Type ; /* EOC or EOS */ + BYTE b_InterruptFlag ; /* Interrupt use or not */ + UINT ui_ConvertTiming ; /* Selection of the convertion time */ + BYTE b_NbrOfChannel ; /* Number of channel to read */ + UINT ui_ChannelList[MAX_ANALOGINPUT_CHANNELS] ; /* Number of the channel to be read */ + UINT ui_RangeList[MAX_ANALOGINPUT_CHANNELS] ; /* Gain of each channel */ + +}str_AnalogReadInformation; + + + + + + +// Function Declaration For APCI-3120 + +// Internal functions +int i_APCI3120_SetupChannelList(comedi_device * dev, comedi_subdevice * s, int n_chan, unsigned int *chanlist,char check); +int i_APCI3120_ExttrigEnable(comedi_device * dev); +int i_APCI3120_ExttrigDisable(comedi_device * dev); +int i_APCI3120_StopCyclicAcquisition(comedi_device *dev,comedi_subdevice *s); +int i_APCI3120_Reset(comedi_device *dev); +int i_APCI3120_CyclicAnalogInput(int mode, comedi_device * dev,comedi_subdevice * s); +// Interrupt functions +void v_APCI3120_Interrupt(int irq, void *d, struct pt_regs *regs) ; +void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device *dev,comedi_subdevice *s,sampl_t *dma,sampl_t *data,int n); +int i_APCI3120_InterruptHandleEos(comedi_device *dev); +void v_APCI3120_InterruptDma(int irq, void *d, struct pt_regs *regs) ; + + + + +// TIMER + +int i_APCI3120_InsnConfigTimer(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI3120_InsnWriteTimer(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); +int i_APCI3120_InsnReadTimer(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn, lsampl_t *data); + + +//DI +// for di read + + +int i_APCI3120_InsnBitsDigitalInput(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); +int i_APCI3120_InsnReadDigitalInput(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); + +//DO +//int i_APCI3120_WriteDigitalOutput(comedi_device *dev, BYTE data); +int i_APCI3120_InsnConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI3120_InsnBitsDigitalOutput(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); +int i_APCI3120_InsnWriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + + + +//AO +//int i_APCI3120_Write1AnalogValue(comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data ); +int i_APCI3120_InsnWriteAnalogOutput(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); + + +//AI HArdware layer + +int i_APCI3120_InsnConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI3120_InsnReadAnalogInput(comedi_device *dev, comedi_subdevice *s,comedi_insn *insn, lsampl_t *data); +int i_APCI3120_CommandTestAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) ; +int i_APCI3120_CommandAnalogInput(comedi_device *dev,comedi_subdevice *s); +//int i_APCI3120_CancelAnalogInput(comedi_device * dev, comedi_subdevice * s); +int i_APCI3120_StopCyclicAcquisition(comedi_device *dev,comedi_subdevice *s); + diff --git a/comedi/drivers/addi-data/hwdrv_apci3200.c b/comedi/drivers/addi-data/hwdrv_apci3200.c new file mode 100644 index 00000000..e099ca87 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -0,0 +1,2414 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci3200.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 10.12.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-3200 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci3200.h" +INT i_CJCAvailable=1; +INT i_CJCPolarity=0; +INT i_CJCGain=0; +INT i_InterruptFlag=0; +INT i_ADDIDATAPolarity; +INT i_ADDIDATAGain; +INT i_AutoCalibration=0; //: auto calibration +INT i_ADDIDATAConversionTime; +INT i_ADDIDATAConversionTimeUnit; +INT i_ADDIDATAType; +INT i_ChannelNo; +INT i_ChannelCount=0; +INT i_ScanType; +INT i_FirstChannel; +INT i_LastChannel; +INT i_Sum=0; +INT i_Offset; +UINT ui_Channel_num=0; +static int i_Count=0; +INT i_Initialised=0; +UINT ui_InterruptChannelValue[96]; //Buffer +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read for Port + Channel Numberfor single channel +| UINT data[0] : 0: Read single channel + 1: Read port value + data[1] Port number ++----------------------------------------------------------------------------+ +| Output Parameters : -- data[0] :Read status value ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI3200_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp=0; + UINT ui_NoOfChannel=0; + ui_NoOfChannel=CR_CHAN(insn->chanspec); + ui_Temp=data[0]; + *data=inl(devpriv->i_IobaseReserved); + + if (ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + } //if (ui_Temp==0) + else + { + if (ui_Temp==1) + { + if(data[1] < 0 || data[1] >1) + { + printk("\nThe port number is in error\n"); + return -EINVAL; + }//if(data[1] < 0 || data[1] >1) + switch( ui_NoOfChannel) + { + + case 2: + *data=(*data >>(2*data[1]))&0x3; + break; + case 3: + *data=(*data & 15 ); + break; + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + }//switch(ui_NoOfChannels) + }//if (ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + }//elseif (ui_Temp==1) + } +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ConfigDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| data[0] :1 Memory enable + 0 Memory Disable ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + +if ( (data[0]!=0) && (data[0]!=1) ) + { + comedi_error(dev,"Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + }//if ( (data[0]!=0) && (data[0]!=1) ) + if (data[0]) + { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE ; + }// if (data[0]) + else + { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + }//else if (data[0]) +return insn->n; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : writes To the digital Output Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| data[0] :Value to output + data[1] : 0 o/p single channel + 1 o/p port + data[2] : port no + data[3] :0 set the digital o/p on + 1 set the digital o/p off ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_Temp=0,ui_Temp1=0; +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if(devpriv->b_OutputMemoryStatus ) + { + ui_Temp=inl(devpriv->i_IobaseAddon); + + }//if(devpriv->b_OutputMemoryStatus ) + else + { + ui_Temp=0; + }//if(devpriv->b_OutputMemoryStatus ) +if(data[3]==0) + { + if(data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outl(data[0],devpriv->i_IobaseAddon); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2:data[0]=(data[0] << (2 * data[2]))|ui_Temp; + break; + case 3:data[0]=(data[0]|ui_Temp); + break; + }//switch(ui_NoOfChannels) + + outl(data[0],devpriv->i_IobaseAddon); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==0) +else + { + if(data[3]==1) + { + if(data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<i_IobaseAddon); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + switch( ui_NoOfChannel) + { + + case 2: data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2 * data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2 * data[2]))^0xf)& ui_Temp; + + break; + case 3: + break; + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + }//switch(ui_NoOfChannels) + + outl(data[0],devpriv->i_IobaseAddon); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }//if else data[3]==1) + }//if else data[3]==0) +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | + data[0] :0 read single channel + 1 read port value + data[1] port no + ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel=CR_CHAN(insn->chanspec); + ui_Temp=data[0]; + *data=inl(devpriv->i_IobaseAddon); + if (ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + } // if (ui_Temp==0) + else + { + if (ui_Temp==1) + { + if(data[1] <0 ||data[1] >1) + { + printk("\nThe port selection is in error\n"); + return -EINVAL; + }//if(data[1] <0 ||data[1] >1) + switch (ui_NoOfChannel) + { + case 2: + *data=(*data >>(2*data[1]))&3; + break; + + case 3:break; + + + default: + comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + break; + } // switch(ui_NoOfChannels) + } // if (ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // else if (ui_Temp==0) + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3200_ConfigAnalogInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Analog Input Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] +| 0:Normal AI | +| 1:RTD | +| 2:THERMOCOUPLE | +| data[1] : Gain To Use | +| | +| data[2] : Polarity +| 0:Bipolar | +| 1:Unipolar | +| | +| data[3] : Offset Range +| | +| data[4] : Coupling +| 0:DC Coupling | +| 1:AC Coupling | +| | +| data[5] :Differential/Single +| 0:Single | +| 1:Differential | +| | +| data[6] :TimerReloadValue +| | +| data[7] :ConvertingTimeUnit +| | +| data[8] :0 Analog voltage measurement + 1 Resistance measurement + 2 Temperature measurement +| data[9] :Interrupt +| 0:Disable +| 1:Enable + data[10] :Type of Thermocouple +| data[11] : 0: single channel + Module Number +| +| data[12] +| 0:Single Read +| 1:Read more channel + 2:Single scan +| 3:Continous Scan + data[13] :Number of channels to read +| data[14] :RTD connection type + :0:RTD not used + 1:RTD 2 wire connection + 2:RTD 3 wire connection + 3:RTD 4 wire connection +| | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_ConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + + UINT ul_Config = 0,ul_Temp=0 ; + UINT ui_ChannelNo=0; + UINT ui_Dummy=0; + INT i_err=0; + if(data[0]!=0 && data[0]!=1 && data[0]!=2) + { + printk("\nThe selection of acquisition type is in error\n"); + i_err++; + }//if(data[0]!=0 && data[0]!=1 && data[0]!=2) + if(data[0]==1) + { + if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4) + { + printk("\n Error in selection of RTD connection type\n"); + i_err++; + }//if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4) + }//if(data[0]==1 ) + if(data[1]<0 || data[1]>7) + { + printk("\nThe selection of gain is in error\n"); + i_err++; + } // if(data[1]<0 || data[1]>7) + if(data[2]!=0 && data[2]!=1) + { + printk("\nThe selection of polarity is in error\n"); + i_err++; + }//if(data[2]!=0 && data[2]!=1) + if(data[3]!=0) + { + printk("\nThe selection of offset range is in error\n"); + i_err++; + }// if(data[3]!=0) + if(data[4]!=0 && data[4]!=1) + { + printk("\nThe selection of coupling is in error\n"); + i_err++; + }//if(data[4]!=0 && data[4]!=1) + if(data[5]!=0 && data[5]!=1) + { + printk("\nThe selection of single/differential mode is in error\n"); + i_err++; + }//if(data[5]!=0 && data[5]!=1) + if(data[8]!=0 && data[8]!=1 && data[2]!=2) + { + printk("\nError in selection of functionality\n"); + }//if(data[8]!=0 && data[8]!=1 && data[2]!=2) + if(data[12]==0 || data[12]==1) + { + if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 ) + { + printk("\nThe selection of conversion time reload value is in error\n"); + i_err++; + }// if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 ) + if(data[7]!=2) + { + printk("\nThe selection of conversion time unit is in error\n"); + i_err++; + }// if(data[7]!=2) + } + if(data[9]!=0 && data[9]!=1) + { + printk("\nThe selection of interrupt enable is in error\n"); + i_err++; + }//if(data[9]!=0 && data[9]!=1) + if(data[11] < 0 || data[11] > 4) + { + printk("\nThe selection of module is in error\n"); + i_err++; + }//if(data[11] <0 || data[11]>1) + if(data[12] < 0 || data[12] > 3) + { + printk("\nThe selection of singlechannel/scan selection is in error\n"); + i_err++; + }//if(data[12] < 0 || data[12]> 3) + if(data[13] <0 ||data[13] >16) + { + printk("\nThe selection of number of channels is in error\n"); + i_err++; + }// if(data[13] <0 ||data[13] >15) + + + i_ChannelCount=data[13]; + i_ScanType=data[12]; + i_ADDIDATAPolarity = data[2]; + i_ADDIDATAGain=data[1]; + i_ADDIDATAConversionTime=data[6]; + i_ADDIDATAConversionTimeUnit=data[7]; + i_ADDIDATAType=data[0]; + while(i_InterruptFlag==1) + { + udelay(1); + } + + ui_ChannelNo = CR_CHAN(insn->chanspec); // get the channel + i_ChannelNo=ui_ChannelNo; + ui_Channel_num =ui_ChannelNo; + if(data[5]==0) + { + if(ui_ChannelNo<0 || ui_ChannelNo>15) + { + printk("\nThe Selection of the channel is in error\n"); + i_err++; + }// if(ui_ChannelNo<0 || ui_ChannelNo>15) + }//if(data[5]==0) + else + { + if(data[14]==2) + { + if(ui_ChannelNo<0 || ui_ChannelNo>3) + { + printk("\nThe Selection of the channel is in error\n"); + i_err++; + }// if(ui_ChannelNo<0 || ui_ChannelNo>3) + }//if(data[14]==2) + else + { + if(ui_ChannelNo<0 || ui_ChannelNo>7) + { + printk("\nThe Selection of the channel is in error\n"); + i_err++; + }// if(ui_ChannelNo<0 || ui_ChannelNo>7) + }//elseif(data[14]==2) + }//elseif(data[5]==0) + if(data[12]==0 || data[12]==1) + { + switch(data[5]) + { + case 0: + if(ui_ChannelNo >=0 && ui_ChannelNo <=3) + { + i_Offset=0; + }//if(ui_ChannelNo >=0 && ui_ChannelNo <=3) + if(ui_ChannelNo >=4 && ui_ChannelNo <=7) + { + i_Offset=64; + }//if(ui_ChannelNo >=4 && ui_ChannelNo <=7) + if(ui_ChannelNo >=8 && ui_ChannelNo <=11) + { + i_Offset=128; + }//if(ui_ChannelNo >=8 && ui_ChannelNo <=11) + if(ui_ChannelNo >=12 && ui_ChannelNo <=15) + { + i_Offset=192; + }//if(ui_ChannelNo >=12 && ui_ChannelNo <=15) + break; + case 1: + if(data[14]==2) + { + if(ui_ChannelNo ==0 ) + { + i_Offset=0; + }//if(ui_ChannelNo ==0 ) + if(ui_ChannelNo ==1) + { + i_Offset=64; + }// if(ui_ChannelNo ==1) + if(ui_ChannelNo ==2 ) + { + i_Offset=128; + }//if(ui_ChannelNo ==2 ) + if(ui_ChannelNo ==3) + { + i_Offset=192; + }//if(ui_ChannelNo ==3) + i_ChannelNo=0; + ui_ChannelNo=0; + break; + }//if(data[14]==2) + if(ui_ChannelNo >=0 && ui_ChannelNo <=1) + { + i_Offset=0; + }//if(ui_ChannelNo >=0 && ui_ChannelNo <=1) + if(ui_ChannelNo >=2 && ui_ChannelNo <=3) + { + i_ChannelNo=i_ChannelNo-2; + ui_ChannelNo=ui_ChannelNo-2; + i_Offset=64; + }//if(ui_ChannelNo >=2 && ui_ChannelNo <=3) + if(ui_ChannelNo >=4 && ui_ChannelNo <=5) + { + i_ChannelNo=i_ChannelNo-4; + ui_ChannelNo=ui_ChannelNo-4; + i_Offset=128; + }//if(ui_ChannelNo >=4 && ui_ChannelNo <=5) + if(ui_ChannelNo >=6 && ui_ChannelNo <=7) + { + i_ChannelNo=i_ChannelNo-6; + ui_ChannelNo=ui_ChannelNo-6; + i_Offset=192; + }//if(ui_ChannelNo >=6 && ui_ChannelNo <=7) + break; + + default: printk("\n This selection of polarity does not exist\n"); + i_err++; + }//switch(data[2]) + }//if(data[12]==0 || data[12]==1) + else + { + switch(data[11]) + { + case 1:i_Offset=0; + break; + case 2:i_Offset=64; + break; + case 3:i_Offset=128; + break; + case 4:i_Offset=192; + break; + default: + printk("\nError in module selection\n"); + i_err++; + }// switch(data[11]) + }// elseif(data[12]==0 || data[12]==1) + if(i_err) + { + i_APCI3200_Reset(dev); + return -EINVAL; + } + if(i_ScanType!=1) + { + i_Count=0; + i_Sum=0; + }//if(i_ScanType!=1) + + + + ul_Config = data[1] |(data[2] << 6) |(data[5]<< 7) |(data[3] << 8) |(data[4] << 9); + + + + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + /*********************************/ + /* Write the channel to configure*/ + /*********************************/ + outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4); + + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + /**************************/ + /* Reset the configuration */ + /**************************/ + outl(0 , devpriv->iobase+i_Offset + 0x0); + + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + + /***************************/ + /* Write the configuration */ + /***************************/ + outl(ul_Config , devpriv->iobase+i_Offset + 0x0); + + /***************************/ + /*Reset the calibration bit*/ + /***************************/ + ul_Temp = inl(devpriv->iobase+i_Offset + 12); + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+i_Offset + 12); + if(data[9]==1) + { + devpriv->tsk_Current=current; + i_InterruptFlag=1; + }// if(data[9]==1) + else + { + i_InterruptFlag=0; + }//else if(data[9]==1) + i_Initialised=1; + if(i_ScanType==1) + { + i_Sum=i_Sum+1; + insn->unused[0]=0; + i_APCI3200_ReadAnalogInput(dev,s,insn,&ui_Dummy); + } +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadAnalogInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : Digital Value Of Input | +| data[1] : Calibration Offset Value | +| data[2] : Calibration Gain Value + data[3] : CJC value + data[4] : CJC offset value + data[5] : CJC gain value ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_ReadAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_DummyValue=0; + int i_ConvertCJCCalibration; + int i=0; + + + if(i_Initialised==0) + { + printk("\nThe channel is not initialised\n"); + i_APCI3200_Reset(dev); + return -EINVAL; + }//if(i_Initialised==0); + + + switch(insn->unused[0]) + { + case 0: + + i_APCI3200_Read1AnalogInputChannel(dev,s,insn,&ui_DummyValue); + ui_InterruptChannelValue[i_Count+0]=ui_DummyValue; + + if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) + { + i_APCI3200_ReadCJCValue(dev,&ui_DummyValue); + ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue; + }//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) + else + { + ui_InterruptChannelValue[i_Count + 3]=0; + }//elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) + if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) + { + i_APCI3200_ReadCalibrationOffsetValue(dev,&ui_DummyValue); + ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue; + i_APCI3200_ReadCalibrationGainValue(dev,&ui_DummyValue); + ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue; + }//if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) + if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1)) + { + /**********************************************************/ + /*Test if the Calibration channel must be read for the CJC*/ + /**********************************************************/ + /**********************************/ + /*Test if the polarity is the same*/ + /**********************************/ + if(i_CJCPolarity!=i_ADDIDATAPolarity) + { + i_ConvertCJCCalibration=1; + }//if(i_CJCPolarity!=i_ADDIDATAPolarity) + else + { + if(i_CJCGain==i_ADDIDATAGain) + { + i_ConvertCJCCalibration=0; + }//if(i_CJCGain==i_ADDIDATAGain) + else + { + i_ConvertCJCCalibration=1; + }//elseif(i_CJCGain==i_ADDIDATAGain) + }//elseif(i_CJCPolarity!=i_ADDIDATAPolarity) + if(i_ConvertCJCCalibration==1) + { + i_APCI3200_ReadCJCCalOffset(dev,&ui_DummyValue); + ui_InterruptChannelValue[i_Count+4]=ui_DummyValue; + i_APCI3200_ReadCJCCalGain(dev,&ui_DummyValue); + ui_InterruptChannelValue[i_Count+5]=ui_DummyValue; + }//if(i_ConvertCJCCalibration==1) + else + { + ui_InterruptChannelValue[i_Count+4]=0; + ui_InterruptChannelValue[i_Count+5]=0; + }//elseif(i_ConvertCJCCalibration==1) + }//if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) + if(i_ScanType!=1) + { + i_Count=0; + }//if(i_ScanType!=1) + else + { + i_Count=i_Count +6; + }//else if(i_ScanType!=1) + if((i_ScanType==1) &&(i_InterruptFlag==1)) + { + i_Count=i_Count-6; + } + if(i_ScanType==0) + { + data[0]= ui_InterruptChannelValue[0]; + data[1]= ui_InterruptChannelValue[1]; + data[2]= ui_InterruptChannelValue[2]; + data[3]= ui_InterruptChannelValue[3]; + data[4]= ui_InterruptChannelValue[4]; + data[5]= ui_InterruptChannelValue[5]; + + + } + break; + case 1 : + for(i=0;in;i++) + { + data[i]=ui_InterruptChannelValue[i]; + } + + i_Count=0; + i_Sum=0; + if(i_ScanType==1) + { + i_Initialised=0; + i_InterruptFlag=0; + } + break; + default:printk("\nThe parameters passed are in error\n"); + i_APCI3200_Reset(dev); + return -EINVAL; + }//switch(insn->unused[0]) +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_Read1AnalogInputChannel | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannel : Channel No to read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : Digital Value read | +| ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_Read1AnalogInputChannel(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){ +UINT ui_EOC=0; +UINT ui_ChannelNo=0; +UINT ui_CommandRegister=0; + + ui_ChannelNo=i_ChannelNo; + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + /*********************************/ + /* Write the channel to configure*/ + /*********************************/ + outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); + +/*******************************/ +/* Set the convert timing unit */ +/*******************************/ +while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); +outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); +/**************************/ +/* Set the convert timing */ +/**************************/ +while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); +outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + +/**************************************************************************/ +/* Set the start end stop index to the selected channel and set the start */ +/**************************************************************************/ + + +ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000; + + /*********************************/ + /*Test if the interrupt is enable*/ + /*********************************/ + + if (i_InterruptFlag == ADDIDATA_ENABLE) + { + /************************/ + /* Enable the interrupt */ + /************************/ + ui_CommandRegister = ui_CommandRegister | 0x00100000; + }//if (i_InterruptFlag == ADDIDATA_ENABLE) + + /******************************/ + /* Write the command register */ + /******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); + /*****************************/ + /*Test if interrupt is enable*/ + /*****************************/ +if (i_InterruptFlag == ADDIDATA_DISABLE) + { + do + { + /*************************/ + /*Read the EOC Status bit*/ + /*************************/ + + ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + + /***************************************/ + /* Read the digital value of the input */ + /***************************************/ + + + data[0] = inl (devpriv->iobase+i_Offset + 28); + + + }// if (i_InterruptFlag == ADDIDATA_DISABLE) +return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadCalibrationOffsetValue | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read calibration offset value of the selected channel| ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : Calibration offset Value | +| ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCalibrationOffsetValue(comedi_device *dev,UINT *data) +{ + UINT ui_Temp=0 , ui_EOC=0; + UINT ui_CommandRegister=0; + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + /*********************************/ + /* Write the channel to configure*/ + /*********************************/ + outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); + + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + /*****************************/ + /*Read the calibration offset*/ + /*****************************/ + ui_Temp = inl(devpriv->iobase+i_Offset + 12); + + /*********************************/ + /*Configure the Offset Conversion*/ + /*********************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12); + /*******************************/ + /*Initialise ui_CommandRegister*/ + /*******************************/ + + ui_CommandRegister = 0; + + /*********************************/ + /*Test if the interrupt is enable*/ + /*********************************/ + + if (i_InterruptFlag == ADDIDATA_ENABLE) + { + + /**********************/ + /*Enable the interrupt*/ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00100000; + + }//if (i_InterruptFlag == ADDIDATA_ENABLE) + + /**********************/ + /*Start the conversion*/ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00080000; + + + /***************************/ + /*Write the command regiter*/ + /***************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); + + /*****************************/ + /*Test if interrupt is enable*/ + /*****************************/ + + if (i_InterruptFlag == ADDIDATA_DISABLE) + { + + do + { + /*******************/ + /*Read the EOC flag*/ + /*******************/ + + ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + + /**************************************************/ + /*Read the digital value of the calibration Offset*/ + /**************************************************/ + + + data[0] = inl(devpriv->iobase+i_Offset+ 28); + }//if (i_InterruptFlag == ADDIDATA_DISABLE) +return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadCalibrationGainValue | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read calibration gain value of the selected channel | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : Calibration gain Value Of Input | +| ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCalibrationGainValue(comedi_device *dev,UINT *data) +{ + UINT ui_EOC=0; + INT ui_CommandRegister=0; + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + /*********************************/ + /* Write the channel to configure*/ + /*********************************/ + outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); + + /***************************/ + /*Read the calibration gain*/ + /***************************/ + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + /*******************************/ + /*Configure the Gain Conversion*/ + /*******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(0x00040000 , devpriv->iobase+i_Offset + 12); + + + /*******************************/ + /*Initialise ui_CommandRegister*/ + /*******************************/ + + ui_CommandRegister = 0; + + /*********************************/ + /*Test if the interrupt is enable*/ + /*********************************/ + + if (i_InterruptFlag == ADDIDATA_ENABLE) + { + + /**********************/ + /*Enable the interrupt*/ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00100000; + + }//if (i_InterruptFlag == ADDIDATA_ENABLE) + + /**********************/ + /*Start the conversion*/ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00080000; + /***************************/ + /*Write the command regiter*/ + /***************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); + + /*****************************/ + /*Test if interrupt is enable*/ + /*****************************/ + + if (i_InterruptFlag == ADDIDATA_DISABLE) + { + + do + { + + /*******************/ + /*Read the EOC flag*/ + /*******************/ + + ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + /************************************************/ + /*Read the digital value of the calibration Gain*/ + /************************************************/ + + data[0] = inl(devpriv->iobase+i_Offset + 28); + + }//if (i_InterruptFlag == ADDIDATA_DISABLE) +return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadCJCValue | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read CJC value of the selected channel | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : CJC Value | +| ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_ReadCJCValue(comedi_device *dev,lsampl_t *data) +{ + UINT ui_EOC=0; + INT ui_CommandRegister=0; + + /******************************/ + /*Set the converting time unit*/ + /******************************/ + + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + + /******************************/ + /*Configure the CJC Conversion*/ + /******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl( 0x00000400 , devpriv->iobase+i_Offset + 4); + /*******************************/ + /*Initialise dw_CommandRegister*/ + /*******************************/ + ui_CommandRegister = 0; + /*********************************/ + /*Test if the interrupt is enable*/ + /*********************************/ + if (i_InterruptFlag == ADDIDATA_ENABLE) + { + /**********************/ + /*Enable the interrupt*/ + /**********************/ + ui_CommandRegister =ui_CommandRegister | 0x00100000; + } + + /**********************/ + /*Start the conversion*/ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00080000; + + /***************************/ + /*Write the command regiter*/ + /***************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); + + /*****************************/ + /*Test if interrupt is enable*/ + /*****************************/ + + if (i_InterruptFlag == ADDIDATA_DISABLE) + { + do + { + + /*******************/ + /*Read the EOC flag*/ + /*******************/ + + ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + /***********************************/ + /*Read the digital value of the CJC*/ + /***********************************/ + + data[0] = inl(devpriv->iobase+i_Offset + 28); + + }//if (i_InterruptFlag == ADDIDATA_DISABLE) +return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadCJCCalOffset | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read CJC calibration offset value of the selected channel ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : CJC calibration offset Value +| ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCJCCalOffset(comedi_device *dev,lsampl_t *data) +{ + UINT ui_EOC=0; + INT ui_CommandRegister=0; + /*******************************************/ + /*Read calibration offset value for the CJC*/ + /*******************************************/ + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + /******************************/ + /*Configure the CJC Conversion*/ + /******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(0x00000400 , devpriv->iobase+i_Offset + 4); + /*********************************/ + /*Configure the Offset Conversion*/ + /*********************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(0x00020000, devpriv->iobase+i_Offset + 12); + + /*******************************/ + /*Initialise ui_CommandRegister*/ + /*******************************/ + ui_CommandRegister = 0; + /*********************************/ + /*Test if the interrupt is enable*/ + /*********************************/ + + if (i_InterruptFlag == ADDIDATA_ENABLE) + { + /**********************/ + /*Enable the interrupt*/ + /**********************/ + ui_CommandRegister =ui_CommandRegister | 0x00100000; + + } + + /**********************/ + /*Start the conversion*/ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00080000; + /***************************/ + /*Write the command regiter*/ + /***************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); + if (i_InterruptFlag == ADDIDATA_DISABLE) + { + do + { + /*******************/ + /*Read the EOC flag*/ + /*******************/ + ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + } while (ui_EOC != 1); + + /**************************************************/ + /*Read the digital value of the calibration Offset*/ + /**************************************************/ + data[0] = inl(devpriv->iobase+i_Offset + 28); + }//if (i_InterruptFlag == ADDIDATA_DISABLE) +return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_ReadCJCGainValue | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read CJC calibration gain value ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : CJC calibration gain value +| ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCJCCalGain(comedi_device *dev,lsampl_t *data) +{ + UINT ui_EOC=0; + INT ui_CommandRegister=0; + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + /******************************/ + /*Configure the CJC Conversion*/ + /******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(0x00000400,devpriv->iobase+i_Offset + 4); +/*******************************/ +/*Configure the Gain Conversion*/ +/*******************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(0x00040000,devpriv->iobase+i_Offset + 12); + + /*******************************/ + /*Initialise dw_CommandRegister*/ + /*******************************/ + ui_CommandRegister = 0; +/*********************************/ +/*Test if the interrupt is enable*/ +/*********************************/ + if (i_InterruptFlag == ADDIDATA_ENABLE) +{ +/**********************/ +/*Enable the interrupt*/ +/**********************/ +ui_CommandRegister = ui_CommandRegister | 0x00100000; +} +/**********************/ +/*Start the conversion*/ +/**********************/ +ui_CommandRegister = ui_CommandRegister | 0x00080000; +/***************************/ +/*Write the command regiter*/ +/***************************/ +while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); +outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); +if (i_InterruptFlag == ADDIDATA_DISABLE) + { + do + { + /*******************/ + /*Read the EOC flag*/ + /*******************/ + ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + } while (ui_EOC != 1); + /************************************************/ + /*Read the digital value of the calibration Gain*/ + /************************************************/ + data[0] = inl (devpriv->iobase+i_Offset + 28); + }//if (i_InterruptFlag == ADDIDATA_DISABLE) +return 0; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_InsnBits_AnalogInput_Test | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Tests the Selected Anlog Input Channel | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| +| +| data[0] : 0 TestAnalogInputShortCircuit +| 1 TestAnalogInputConnection | + ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : Digital value obtained | +| data[1] : calibration offset | +| data[2] : calibration gain | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +UINT ui_Configuration=0; +INT i_Temp,i_TimeUnit; +if(i_Initialised==0) + { + printk("\nThe channel is not initialised\n"); + i_APCI3200_Reset(dev); + return -EINVAL; + }//if(i_Initialised==0); +if(data[0]!=0 && data[0]!=1) + { + printk("\nError in selection of functionality\n"); + i_APCI3200_Reset(dev); + return -EINVAL; + }//if(data[0]!=0 && data[0]!=1) + +if(data[0]==1) //Perform Short Circuit TEST + { + /**************************/ + /*Set the short-cicuit bit*/ + /**************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); + /*************************/ + /*Set the time unit to ns*/ + /*************************/ + /* i_TimeUnit= i_ADDIDATAConversionTimeUnit; + i_ADDIDATAConversionTimeUnit= 1;*/ + i_Temp= i_InterruptFlag ; + i_InterruptFlag = ADDIDATA_DISABLE; + i_APCI3200_Read1AnalogInputChannel(dev,s,insn,data); + if(i_AutoCalibration == FALSE) + { + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); + data++; + i_APCI3200_ReadCalibrationOffsetValue(dev,data); + data++; + i_APCI3200_ReadCalibrationGainValue(dev,data); + } + } +else + { + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); + ui_Configuration = inl(devpriv->iobase+i_Offset + 0); + /*************************/ + /*Set the time unit to ns*/ + /*************************/ + /* i_TimeUnit= i_ADDIDATAConversionTimeUnit; + i_ADDIDATAConversionTimeUnit= 1;*/ + i_Temp= i_InterruptFlag ; + i_InterruptFlag = ADDIDATA_DISABLE; + i_APCI3200_Read1AnalogInputChannel(dev,s,insn,data); + if(i_AutoCalibration == FALSE) + { + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); + data++; + i_APCI3200_ReadCalibrationOffsetValue(dev,data); + data++; + i_APCI3200_ReadCalibrationGainValue(dev,data); + } + } + i_InterruptFlag=i_Temp ; +printk("\ni_InterruptFlag=%d\n",i_InterruptFlag); +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_InsnWriteReleaseAnalogInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Resets the channels | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer ++----------------------------------------------------------------------------+ +| Output Parameters : -- | + ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + i_APCI3200_Reset(dev); + return insn->n; + } + + + + + + + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3200_CommandTestAnalogInput(comedi_device *dev| +| ,comedi_subdevice *s,comedi_cmd *cmd) | +| | ++----------------------------------------------------------------------------+ +| Task : Test validity for a command for cyclic anlog input | +| acquisition | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| comedi_cmd *cmd | +| | +| +| | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value :0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_CommandTestAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) +{ + + int err=0; + int tmp;// divisor1,divisor2; + UINT ui_ConvertTime=0; + UINT ui_ConvertTimeBase=0; + UINT ui_DelayTime=0; + UINT ui_DelayTimeBase=0; + INT i_Triggermode=0; + INT i_TriggerEdge=0; + INT i_NbrOfChannel=0; + INT i_Cpt=0; + double d_ConversionTimeForAllChannels=0.0; + double d_SCANTimeNewUnit=0.0; + // step 1: make sure trigger sources are trivially valid + + tmp=cmd->start_src; + cmd->start_src &= TRIG_NOW|TRIG_EXT; + if(!cmd->start_src || tmp!=cmd->start_src)err++; + tmp=cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER|TRIG_FOLLOW; + if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++; + tmp=cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + if(!cmd->convert_src || tmp!=cmd->convert_src)err++; + tmp=cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++; + tmp=cmd->stop_src; + cmd->stop_src &= TRIG_COUNT|TRIG_NONE; + if(!cmd->stop_src || tmp!=cmd->stop_src)err++; + if(i_InterruptFlag==0) + { + err++; +// printk("\nThe interrupt should be enabled\n"); + } + if(err) + { + i_APCI3200_Reset(dev); + return 1; + } + + + if(cmd->start_src!=TRIG_NOW && cmd->start_src!=TRIG_EXT) + { + err++; + } + if(cmd->start_src==TRIG_EXT) + { + i_TriggerEdge=cmd->start_arg & 0xFFFF; + i_Triggermode=cmd->start_arg >> 16; + if(i_TriggerEdge < 1 || i_TriggerEdge >3 ) + { + err++; + printk("\nThe trigger edge selection is in error\n") ; + } + if(i_Triggermode!=2) + { + err++; + printk("\nThe trigger mode selection is in error\n") ; + } + } + + if(cmd->scan_begin_src!=TRIG_TIMER && + cmd->scan_begin_src!=TRIG_FOLLOW) err++; + + if(cmd->convert_src!=TRIG_TIMER ) err++; + + if(cmd->scan_end_src!=TRIG_COUNT) + { + cmd->scan_end_src=TRIG_COUNT; + err++; + } + + if(cmd->stop_src!=TRIG_NONE && + cmd->stop_src!=TRIG_COUNT ) err++; + + if(err) + { + i_APCI3200_Reset(dev); + return 2; + } + + i_FirstChannel=cmd->chanlist[0]; + i_LastChannel=cmd->chanlist[1]; + + + if (cmd->convert_src==TRIG_TIMER) + { + ui_ConvertTime=cmd->convert_arg & 0xFFFF; + ui_ConvertTimeBase=cmd->convert_arg >> 16; + if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 ) + + { + printk("\nThe selection of conversion time reload value is in error\n"); + err++; + }// if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 ) + if(ui_ConvertTimeBase!=2) + { + printk("\nThe selection of conversion time unit is in error\n"); + err++; + }//if(ui_ConvertTimeBase!=2) + } + else + { + ui_ConvertTime=0; + ui_ConvertTimeBase=0; + } + if(cmd->scan_begin_src==TRIG_FOLLOW) + { + ui_DelayTime=0; + ui_DelayTimeBase=0; + }//if(cmd->scan_begin_src==TRIG_FOLLOW) + else + { + ui_DelayTime=cmd->scan_begin_arg & 0xFFFF; + ui_DelayTimeBase=cmd->scan_begin_arg >> 16; + if(ui_DelayTimeBase!=2 && ui_DelayTimeBase!=3) + { + err++; + printk("\nThe Delay time base selection is in error\n"); + } + if(ui_DelayTime < 1 && ui_DelayTime >1023) + { + err++; + printk("\nThe Delay time value is in error\n"); + } + if(err) + { + i_APCI3200_Reset(dev); + return 3; + } + d_SCANTimeNewUnit = (double)ui_DelayTime; + i_NbrOfChannel= i_LastChannel-i_FirstChannel + 4; + /**********************************************************/ + /*calculate the total conversion time for all the channels*/ + /**********************************************************/ + d_ConversionTimeForAllChannels = (double)((double)ui_ConvertTime / (double)i_NbrOfChannel); + + /*******************************/ + /*Convert the frequence in time*/ + /*******************************/ + d_ConversionTimeForAllChannels =(double) 1.0/ d_ConversionTimeForAllChannels; + ui_ConvertTimeBase=3; + /***********************************/ + /*Test if the time unit is the same*/ + /***********************************/ + + if (ui_DelayTimeBase <= ui_ConvertTimeBase) + { + + for (i_Cpt = 0; i_Cpt < (ui_ConvertTimeBase-ui_DelayTimeBase);i_Cpt++) + { + + d_ConversionTimeForAllChannels = d_ConversionTimeForAllChannels * 1000; + d_ConversionTimeForAllChannels=d_ConversionTimeForAllChannels+1; + } + } + else + { + for (i_Cpt = 0; i_Cpt < (ui_DelayTimeBase-ui_ConvertTimeBase);i_Cpt++) + { + d_SCANTimeNewUnit = d_SCANTimeNewUnit * 1000; + + } + } + + if (d_ConversionTimeForAllChannels >= d_SCANTimeNewUnit) + { + + printk("\nSCAN Delay value cannot be used\n"); + /*********************************/ + /*SCAN Delay value cannot be used*/ + /*********************************/ + err++; + } + }//else if(cmd->scan_begin_src==TRIG_FOLLOW) + + + + if(err) + { + i_APCI3200_Reset(dev); + return 4; + } + + return 0; + } + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3200_StopCyclicAcquisition(comedi_device *dev,| +| comedi_subdevice *s)| +| | ++----------------------------------------------------------------------------+ +| Task : Stop the acquisition | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| | ++----------------------------------------------------------------------------+ +| Return Value :0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_StopCyclicAcquisition(comedi_device *dev,comedi_subdevice *s) +{ +UINT ui_Configuration=0; +i_InterruptFlag=0; +i_Initialised==0; +i_Count=0; +i_Sum=0; + /*******************/ + /*Read the register*/ + /*******************/ + ui_Configuration = inl(devpriv->iobase+i_Offset + 8); +/*****************************/ +/*Reset the START and IRQ bit*/ +/*****************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+i_Offset + 8); +return 0; +} +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3200_CommandAnalogInput(comedi_device *dev, | +| comedi_subdevice *s) | +| | ++----------------------------------------------------------------------------+ +| Task : Does asynchronous acquisition | +| Determines the mode 1 or 2. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| comedi_subdevice *s | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + + int i_APCI3200_CommandAnalogInput(comedi_device *dev,comedi_subdevice *s) +{ +comedi_cmd *cmd=&s->async->cmd; +UINT ui_Configuration=0; +INT i_CurrentSource = 0; +UINT ui_Trigger=0; +UINT ui_TriggerEdge=0; +UINT ui_Triggermode=0; +UINT ui_ScanMode=0; +UINT ui_ConvertTime=0; +UINT ui_ConvertTimeBase=0; +UINT ui_DelayTime=0; +UINT ui_DelayTimeBase=0; +UINT ui_DelayMode=0; + i_FirstChannel=cmd->chanlist[0]; + i_LastChannel=cmd->chanlist[1]; + if(cmd->start_src==TRIG_EXT) + { + ui_Trigger=1; + ui_TriggerEdge=cmd->start_arg &0xFFFF; + ui_Triggermode=cmd->start_arg >> 16; + }//if(cmd->start_src==TRIG_EXT) + else + { + ui_Trigger=0; + }//elseif(cmd->start_src==TRIG_EXT) + + if (cmd->stop_src==TRIG_COUNT) + { + ui_ScanMode=0; + }// if (cmd->stop_src==TRIG_COUNT) + else + { + ui_ScanMode=2; + }//else if (cmd->stop_src==TRIG_COUNT) + + if(cmd->scan_begin_src==TRIG_FOLLOW) + { + ui_DelayTime=0; + ui_DelayTimeBase=0; + ui_DelayMode=0; + }//if(cmd->scan_begin_src==TRIG_FOLLOW) + else + { + ui_DelayTime=cmd->scan_begin_arg & 0xFFFF; + ui_DelayTimeBase=cmd->scan_begin_arg >> 16; + ui_DelayMode =1; + }//else if(cmd->scan_begin_src==TRIG_FOLLOW) +// printk("\nui_DelayTime=%u\n",ui_DelayTime); +// printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase); + if (cmd->convert_src==TRIG_TIMER) + { + ui_ConvertTime=cmd->convert_arg & 0xFFFF; + ui_ConvertTimeBase=cmd->convert_arg >> 16; + } + else + { + ui_ConvertTime=0; + ui_ConvertTimeBase=0; + } + printk("\nui_ConvertTime=%u\n",ui_ConvertTime); + printk("\nui_ConvertTimebase=%u\n",ui_ConvertTimeBase); + // if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2))) + // { + /**************************************************/ + /*Read the old configuration of the current source*/ + /**************************************************/ + ui_Configuration = inl(devpriv->iobase+i_Offset + 12); + /***********************************************/ + /*Write the configuration of the current source*/ + /***********************************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+i_Offset +12); + // } + ui_Configuration=0; +// printk("\nfirstchannel=%u\n",i_FirstChannel); +// printk("\nlastchannel=%u\n",i_LastChannel); +// printk("\nui_Trigger=%u\n",ui_Trigger); +// printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge); +// printk("\nui_Triggermode=%u\n",ui_Triggermode); +// printk("\nui_DelayMode=%u\n",ui_DelayMode); +// printk("\nui_ScanMode=%u\n",ui_ScanMode); + ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 | + (ui_Trigger << 24) | + (ui_TriggerEdge << 25)| + (ui_Triggermode << 27)| + (ui_DelayMode << 18) | + (ui_ScanMode << 16); + + + /*************************/ + /*Write the Configuration*/ + /*************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8); + /***********************/ + /*Write the Delay Value*/ + /***********************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_DelayTime,devpriv->iobase+i_Offset + 40); + /***************************/ + /*Write the Delay time base*/ + /***************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44); + /*********************************/ + /*Write the conversion time value*/ + /*********************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32); + /********************************/ + /*Write the conversion time base*/ + /********************************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36); + /*******************/ + /*Read the register*/ + /*******************/ + ui_Configuration = inl(devpriv->iobase+i_Offset + 4); + /******************/ + /*Set the SCAN bit*/ + /******************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + + outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4); + /*******************/ + /*Read the register*/ + /*******************/ + ui_Configuration=0; + ui_Configuration = inl(devpriv->iobase+i_Offset + 8); + + /*******************/ + /*Set the START bit*/ + /*******************/ + while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8); + return 0; +} + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3200_Reset(comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task :Resets the registers of the card | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_Reset(comedi_device *dev) +{ +INT i_Temp; +DWORD dw_Dummy; +i_InterruptFlag=0; +i_Initialised==0; +i_Count=0; +i_Sum=0; + +outl(0x83838383,devpriv->i_IobaseAmcc+0x60); + + // Enable the interrupt for the controler + dw_Dummy = inl(devpriv->i_IobaseAmcc+ 0x38); + outl(dw_Dummy | 0x2000,devpriv->i_IobaseAmcc+0x38); +outl(0,devpriv->i_IobaseAddon);//Resets the output +/***************/ +/*Empty the buffer*/ +/**************/ +for(i_Temp=0;i_Temp<=95;i_Temp++) + { + ui_InterruptChannelValue[i_Temp]=0; + }//for(i_Temp=0;i_Temp<=95;i_Temp++) +/*****************************/ +/*Reset the START and IRQ bit*/ +/*****************************/ +for(i_Temp=0;i_Temp<=192;) + { + while (((inl(devpriv->iobase+i_Temp+12)>>19) & 1) != 1); + outl(0,devpriv->iobase+i_Temp + 8); + i_Temp=i_Temp+64; + }//for(i_Temp=0;i_Temp<=192;i_Temp+64) +return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI3200_Interrupt | +| (int irq , void *d, struct pt_regs *regs) | ++----------------------------------------------------------------------------+ +| Task : Interrupt processing Routine | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | +| struct pt_regs *regs : structure pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + void v_APCI3200_Interrupt(int irq, void *d, struct pt_regs *regs) +{ + comedi_device *dev = d; + UINT ui_StatusRegister=0; + UINT ui_ChannelNumber = 0; + INT i_CalibrationFlag = 0; + INT i_CJCFlag=0; + UINT ui_DummyValue = 0; + UINT ui_DigitalTemperature=0; + UINT ui_DigitalInput =0; + int i_ConvertCJCCalibration; + int k; + +switch(i_ScanType) + { + case 0: + case 1: + switch(i_ADDIDATAType) + { + case 0: + case 1: + + /************************************/ + /*Read the interrupt status register*/ + /************************************/ + ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); + if ((ui_StatusRegister & 0x2) == 0x2) + { + i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); + /*************************/ + /*Read the channel number*/ + /*************************/ + ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); + /*************************************/ + /*Read the digital analog input value*/ + /*************************************/ + ui_DigitalInput = inl(devpriv->iobase+i_Offset + 28); + /***********************************************/ + /* Test if the value read is the channel value */ + /***********************************************/ + if (i_CalibrationFlag == 0) + { + ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput; + + /******************************************************/ + /*Start the conversion of the calibration offset value*/ + /******************************************************/ + i_APCI3200_ReadCalibrationOffsetValue(dev,&ui_DummyValue); + }//if (i_CalibrationFlag == 0) + /**********************************************************/ + /* Test if the value read is the calibration offset value */ + /**********************************************************/ + + if (i_CalibrationFlag == 1) + { + + /******************/ + /* Save the value */ + /******************/ + + ui_InterruptChannelValue[i_Count + 1] = ui_DigitalInput; + + /******************************************************/ + /* Start the conversion of the calibration gain value */ + /******************************************************/ + i_APCI3200_ReadCalibrationGainValue(dev,&ui_DummyValue); + }//if (i_CalibrationFlag == 1) + /******************************************************/ + /*Test if the value read is the calibration gain value*/ + /******************************************************/ + + if (i_CalibrationFlag == 2) + { + + /****************/ + /*Save the value*/ + /****************/ + ui_InterruptChannelValue[i_Count + 2] = ui_DigitalInput; + if(i_ScanType==1) + { + + i_InterruptFlag=0; + i_Count=i_Count + 6; + }//if(i_ScanType==1) + else + { + i_Count=0; + }//elseif(i_ScanType==1) + if(i_ScanType!=1) + { + + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + }//if(i_ScanType!=1) + else + { + if(i_ChannelCount==i_Sum) + { + + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + } + }//if(i_ScanType!=1) + }//if (i_CalibrationFlag == 2) + }// if ((ui_StatusRegister & 0x2) == 0x2) + break; + + case 2: + /************************************/ + /*Read the interrupt status register*/ + /************************************/ + + ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); + /*************************/ + /*Test if interrupt occur*/ + /*************************/ + + + if ((ui_StatusRegister & 0x2) == 0x2) + { + + i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10); + + i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); + + /*************************/ + /*Read the channel number*/ + /*************************/ + + ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); + + + /************************************/ + /*Read the digital temperature value*/ + /************************************/ + ui_DigitalTemperature = inl(devpriv->iobase+i_Offset + 28); + + + + /*********************************************/ + /*Test if the value read is the channel value*/ + /*********************************************/ + + + if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0)) + { + ui_InterruptChannelValue[i_Count + 0]=ui_DigitalTemperature; + + /*********************************/ + /*Start the conversion of the CJC*/ + /*********************************/ + i_APCI3200_ReadCJCValue(dev,&ui_DummyValue); + + }//if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0)) + + + /*****************************************/ + /*Test if the value read is the CJC value*/ + /*****************************************/ + + if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0)) + { + ui_InterruptChannelValue[i_Count + 3]=ui_DigitalTemperature; + + + /******************************************************/ + /*Start the conversion of the calibration offset value*/ + /******************************************************/ + i_APCI3200_ReadCalibrationOffsetValue(dev,&ui_DummyValue); + }// if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0)) + + + /********************************************************/ + /*Test if the value read is the calibration offset value*/ + /********************************************************/ + + if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0)) + { + ui_InterruptChannelValue[i_Count + 1]=ui_DigitalTemperature; + + /****************************************************/ + /*Start the conversion of the calibration gain value*/ + /****************************************************/ + i_APCI3200_ReadCalibrationGainValue(dev,&ui_DummyValue); + + }//if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0)) + + + /******************************************************/ + /*Test if the value read is the calibration gain value*/ + /******************************************************/ + + + if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0)) + { + ui_InterruptChannelValue[i_Count + 2]=ui_DigitalTemperature; + + /**********************************************************/ + /*Test if the Calibration channel must be read for the CJC*/ + /**********************************************************/ + + /*Test if the polarity is the same*/ + /**********************************/ + if(i_CJCPolarity!=i_ADDIDATAPolarity) + { + i_ConvertCJCCalibration=1; + }//if(i_CJCPolarity!=i_ADDIDATAPolarity) + else + { + if(i_CJCGain==i_ADDIDATAGain) + { + i_ConvertCJCCalibration=0; + }//if(i_CJCGain==i_ADDIDATAGain) + else + { + i_ConvertCJCCalibration=1; + }//elseif(i_CJCGain==i_ADDIDATAGain) + }//elseif(i_CJCPolarity!=i_ADDIDATAPolarity) + if(i_ConvertCJCCalibration==1) + { + /****************************************************************/ + /*Start the conversion of the calibration gain value for the CJC*/ + /****************************************************************/ + i_APCI3200_ReadCJCCalOffset(dev,&ui_DummyValue); + + }//if(i_ConvertCJCCalibration==1) + else + { + ui_InterruptChannelValue[i_Count + 4]=0; + ui_InterruptChannelValue[i_Count + 5]=0; + + }//elseif(i_ConvertCJCCalibration==1) + }//else if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0)) + + /********************************************************************/ + /*Test if the value read is the calibration offset value for the CJC*/ + /********************************************************************/ + + + if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1)) + { + ui_InterruptChannelValue[i_Count + 4]=ui_DigitalTemperature; + + /****************************************************************/ + /*Start the conversion of the calibration gain value for the CJC*/ + /****************************************************************/ + i_APCI3200_ReadCJCCalGain(dev,&ui_DummyValue); + + }//if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1)) + + + /******************************************************************/ + /*Test if the value read is the calibration gain value for the CJC*/ + /******************************************************************/ + + + if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1)) + { + ui_InterruptChannelValue[i_Count + 5]=ui_DigitalTemperature; + + if(i_ScanType==1) + { + + i_InterruptFlag=0; + i_Count=i_Count + 6; + }//if(i_ScanType==1) + else + { + i_Count=0; + }//elseif(i_ScanType==1) + if(i_ScanType!=1) + { + + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + }//if(i_ScanType!=1) + else + { + if(i_ChannelCount==i_Sum) + { + send_sig(SIGIO,devpriv->tsk_Current,0); // send signal to the sample + + }//if(i_ChannelCount==i_Sum) + }//else if(i_ScanType!=1) + }//if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1)) + + }//else if ((ui_StatusRegister & 0x2) == 0x2) + break; + }//switch(i_ADDIDATAType) + break; + case 2: + case 3: + i_APCI3200_InterruptHandleEos(dev); + break; + }//switch(i_ScanType) +return; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3200_InterruptHandleEos(comedi_device *dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : . | +| This function copies the acquired data(from FIFO) | +| to Comedi buffer. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3200_InterruptHandleEos(comedi_device *dev) +{ + UINT ui_StatusRegister=0; + UINT ui_ChannelNumber = 0; + UINT *data; + comedi_subdevice *s=dev->subdevices+0; + comedi_async *async = s->async; + data=async->data+async->buf_int_ptr;//new samples added from here onwards + + /************************************/ + /*Read the interrupt status register*/ + /************************************/ + ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); + /*************************/ + /*Test if interrupt occur*/ + /*************************/ + + if ((ui_StatusRegister & 0x2) == 0x2) + { + /*************************/ + /*Read the channel number*/ + /*************************/ + ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); + + /*************************************/ + /*Read the digital Analog Input value*/ + /*************************************/ + + data[i_Count] = inl(devpriv->iobase+i_Offset + 28); +// printk("\ndata[%d]=%x\n",i_Count,data[i_Count]); + if((i_Count == (i_LastChannel-i_FirstChannel+3))) + { + i_Count=-1; + async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT); + async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT); + comedi_eos(dev,s); + if (s->async->buf_int_ptr>=s->async->data_len) // for buffer rool over + { + /* buffer rollover */ + s->async->buf_int_ptr=0; + comedi_eobuf(dev,s); + } + } + i_Count++; + } + i_InterruptFlag=0; + return 0; +} + + + diff --git a/comedi/drivers/addi-data/hwdrv_apci3200.h b/comedi/drivers/addi-data/hwdrv_apci3200.h new file mode 100644 index 00000000..8b123131 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci3200.h @@ -0,0 +1,109 @@ +// 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 +comedi_lrange range_apci3200_ai={ 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1) + } +}; + +//Analog Input related Defines +#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 + +//ADDIDATA Enable Disable +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +typedef struct + { + ULONG ul_NumberOfValue; + ULONG *pul_ResistanceValue; + ULONG *pul_TemperatureValue; + }str_ADDIDATA_RTDStruct,*pstr_ADDIDATA_RTDStruct; + + +// Hardware Layer functions for Apci3200 + +//AI + +INT i_APCI3200_ConfigAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI3200_ReadAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI3200_InsnWriteReleaseAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI3200_InsnBits_AnalogInput_Test(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI3200_StopCyclicAcquisition(comedi_device *dev,comedi_subdevice *s); +INT i_APCI3200_InterruptHandleEos(comedi_device *dev); +INT i_APCI3200_CommandTestAnalogInput(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) ; +INT i_APCI3200_CommandAnalogInput(comedi_device *dev,comedi_subdevice *s); +INT i_APCI3200_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +//Interrupt +void v_APCI3200_Interrupt(int irq, void *d, struct pt_regs *regs) ; +int i_APCI3200_InterruptHandleEos(comedi_device *dev); +//Reset functions +INT i_APCI3200_Reset(comedi_device *dev); + + +int i_APCI3200_ReadCJCCalOffset(comedi_device *dev,lsampl_t *data); +int i_APCI3200_ReadCJCValue(comedi_device *dev,lsampl_t *data); +int i_APCI3200_ReadCalibrationGainValue(comedi_device *dev,UINT *data); +int i_APCI3200_ReadCalibrationOffsetValue(comedi_device *dev,UINT *data); +int i_APCI3200_Read1AnalogInputChannel(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI3200_ReadCJCCalGain(comedi_device *dev,lsampl_t *data); diff --git a/comedi/drivers/addi-data/hwdrv_apci3501.c b/comedi/drivers/addi-data/hwdrv_apci3501.c new file mode 100644 index 00000000..a5850292 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -0,0 +1,706 @@ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : 13Card Linux Driver | Compiler : GCC | + | Module name : hwdrv_apci3501.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : Shitalkumar S Chavan | Date : 10.12.2001 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-3501 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci3501.h" + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ReadDigitalInput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI3501_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel=CR_CHAN(insn->chanspec); + ui_Temp=data[0]; + *data=inl(devpriv->iobase+APCI3501_DIGITAL_IP); + if (ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + } //if (ui_Temp==0) + else + { + if (ui_Temp==1) + { + + *data=*data & 0x3; + }//if (ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + }//elseif (ui_Temp==1) + }//elseif (ui_Temp==0) +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ConfigDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[1] : 1 Enable VCC Interrupt | +| 0 Disable VCC Interrupt | +| data[2] : 1 Enable CC Interrupt | +| 0 Disable CC Interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3501_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + +if ( (data[0]!=0) && (data[0]!=1) ) + { + comedi_error(dev,"Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + }//if ( (data[0]!=0) && (data[0]!=1) ) + if (data[0]) + { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE ; + }// if (data[0]) + else + { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + }//else if (data[0]) +return insn->n; +} + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_WriteDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : writes To the digital Output Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp,ui_Temp1; +UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if(devpriv->b_OutputMemoryStatus ) + { + ui_Temp=inl(devpriv->iobase+APCI3501_DIGITAL_OP); + }//if(devpriv->b_OutputMemoryStatus ) + else + { + ui_Temp=0; + }//if(devpriv->b_OutputMemoryStatus ) +if(data[3]==0) + { + if(data[1]==0) + { + data[0]=(data[0] << ui_NoOfChannel)|ui_Temp; + outl(data[0],devpriv->iobase+APCI3501_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + data[0]=(data[0] << (2*data[2]))|ui_Temp; + outl(data[0],devpriv->iobase+APCI3501_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==0) +else + { + if(data[3]==1) + { + if(data[1]==0) + { + data[0]=~data[0]&0x1; + ui_Temp1=1; + ui_Temp1=ui_Temp1<iobase+APCI3501_DIGITAL_OP); + }//if(data[1]==0) + else + { + if(data[1]==1) + { + data[0]=~data[0]&0x3; + ui_Temp1=3; + ui_Temp1=ui_Temp1<<2*data[2]; + ui_Temp=ui_Temp|ui_Temp1; + data[0]=((data[0] << (2*data[2]))^0xffffffff)& ui_Temp; + outl(data[0],devpriv->iobase+APCI3501_DIGITAL_OP); + }// if(data[1]==1) + else + { + printk("\nSpecified channel not supported\n"); + }//else if(data[1]==1) + }//elseif(data[1]==0) + }//if(data[3]==1); + else + { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + }//if else data[3]==1) + }//if else data[3]==0) +return insn->n; +} +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ReadDigitalOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + + ui_NoOfChannel=CR_CHAN(insn->chanspec); + ui_Temp=data[0]; + *data=inl(devpriv->iobase+APCI3501_DIGITAL_OP); + if (ui_Temp==0) + { + *data=(*data >> ui_NoOfChannel)&0x1; + } // if (ui_Temp==0) + else + { + if (ui_Temp==1) + { + *data=*data & 0x3; + + } // if (ui_Temp==1) + else + { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // else if (ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ConfigAnalogOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Analog Output Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : Voltage Mode | +| 0:Mode 0 | +| 1:Mode 1 | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_ConfigAnalogOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + outl(data[0],devpriv->iobase+APCI3501_ANALOG_OUTPUT+APCI3501_AO_VOLT_MODE); + + if(data[0]) + { + devpriv->b_InterruptMode=MODE1; + } + else + { + devpriv->b_InterruptMode=MODE0; + } +return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_WriteAnalogOutput | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Writes To the Selected Anlog Output Channel | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| comedi_subdevice *s : Subdevice Pointer | +| comedi_insn *insn : Insn Structure Pointer | +| lsampl_t *data : Data Pointer contains | +| configuration parameters as below | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_WriteAnalogOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +ULONG ul_Command1 = 0,ul_Channel_no,ul_Polarity,ul_DAC_Ready=0;; + +ul_Channel_no=CR_CHAN(insn->chanspec); + +if(devpriv->b_InterruptMode==MODE1) + { + ul_Polarity=0x80000000; + if((*data<0) || (*data>16384)) + { + printk("\nIn WriteAnalogOutput :: Not Valid Data\n"); + } + + } // end if(devpriv->b_InterruptMode==MODE1) +else { + ul_Polarity=0; + if((*data<0) || (*data>8192)) + { + printk("\nIn WriteAnalogOutput :: Not Valid Data\n"); + } + + }// end else + +if((ul_Channel_no<0)||(ul_Channel_no>7)) + { + printk("\nIn WriteAnalogOutput :: Not Valid Channel\n"); + } // end if((ul_Channel_no<0)||(ul_Channel_no>7)) + +ul_DAC_Ready=inl(devpriv->iobase+APCI3501_ANALOG_OUTPUT); + +while(ul_DAC_Ready==0) + { + ul_DAC_Ready=inl(devpriv->iobase+APCI3501_ANALOG_OUTPUT); + ul_DAC_Ready=(ul_DAC_Ready>>8)&1; + } + +if(ul_DAC_Ready) +{ +// Output the Value on the output channels. +ul_Command1=(ULONG)((ULONG)(ul_Channel_no & 0xFF)|(ULONG)((*data << 0x8)&0x7FFFFF00L)|(ULONG)(ul_Polarity)); +outl(ul_Command1,devpriv->iobase+APCI3501_ANALOG_OUTPUT+APCI3501_AO_PROG); +} + +return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ConfigTimerCounterWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Configure As Timer | +| 1 Configure As Counter | +| 2 Configure As Watchdog | +| data[1] : 1 Enable Interrupt | +| 0 Disable Interrupt | +| data[2] : Time Unit | +| data[3] : Reload Value | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_ConfigTimerCounterWatchdog (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + ULONG ul_Command1 = 0; +devpriv->tsk_Current=current; + if (data[0]==ADDIDATA_WATCHDOG) + { + + devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; + //Disable the watchdog + outl(0x0,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); //disable Wa + + if (data[1]==1) + { + //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES + outl(0x02,devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_PROG); + } + else + { + outl(0x0,devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_PROG);//disable Timer interrupt + } + + + //Loading the Timebase value + outl(data[2],devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_TIMEBASE); + + + //Loading the Reload value + outl(data[3],devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_RELOAD_VALUE); + //Set the mode + ul_Command1 = inl(devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_PROG) | 0xFFF819E0UL;//e2->e0 + outl(ul_Command1 , devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_PROG); + }//end if(data[0]==ADDIDATA_WATCHDOG) + + else if (data[0]==ADDIDATA_TIMER) + { + //First Stop The Timer + ul_Command1 =inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1 =ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG);//Stop The Timer + devpriv->b_TimerSelectMode =ADDIDATA_TIMER; + if (data[1]==1) + { + //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES + outl(0x02,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + } + else + { + outl(0x0,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG);//disable Timer interrupt + } + + // Loading Timebase + outl(data[2],devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_TIMEBASE); + + //Loading the Reload value + outl(data[3],devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_RELOAD_VALUE); + + // printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG)); + ul_Command1 =inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; + outl(ul_Command1,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG);//mode 2 + + }//end if(data[0]==ADDIDATA_TIMER) + +return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_StartStopWriteTimerCounterWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Timer | +| 1 Counter | +| 2 Watchdog | | data[1] : 1 Start | +| 0 Stop | 2 Trigger | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ +ULONG ul_Command1 = 0; +int i_Temp; +if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + { + + if (data[1]==1) + { + ul_Command1=inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1=(ul_Command1& 0xFFFFF9FFUL) | 0x1UL; + //Enable the Watchdog + outl(ul_Command1,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + } + + else if(data[1]==0)//Stop The Watchdog + { + //Stop The Watchdog + ul_Command1=inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1 =ul_Command1 & 0xFFFFF9FEUL; + outl(0x0,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + } + else if(data[1]==2) + { + ul_Command1=inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; + outl(ul_Command1,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + }//if(data[1]==2) + } // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + +if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + { + if (data[1]==1) + { + + ul_Command1=inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1=(ul_Command1& 0xFFFFF9FFUL) | 0x1UL; + //Enable the Timer + outl(ul_Command1,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + } + else if(data[1]==0) + { + //Stop The Timer + ul_Command1=inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1 =ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + } + + else if (data[1]==2) + { + //Trigger the Timer + ul_Command1=inl(devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; + outl(ul_Command1,devpriv->iobase+ APCI3501_WATCHDOG+ APCI3501_TCW_PROG); + } + + } // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) +i_Temp= inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_TRIG_STATUS)&0x1; +return insn->n; +} + + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ReadTimerCounterWatchdog | +| (comedi_device *dev,comedi_subdevice *s, | +| comedi_insn *insn,lsampl_t *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Timer | +| 1 Counter | +| 2 Watchdog | | data[1] : Timer Counter Watchdog Number | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3501_ReadTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) +{ + + if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + { + data[0]= inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_TRIG_STATUS)&0x1; + data[1]= inl(devpriv->iobase + APCI3501_WATCHDOG); + }// end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + + else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + { + data[0]= inl(devpriv->iobase+APCI3501_WATCHDOG+APCI3501_TCW_TRIG_STATUS)&0x1; + data[1]= inl(devpriv->iobase + APCI3501_WATCHDOG); + } // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + + else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)) + { + printk ("\nIn ReadTimerCounterWatchdog :: Invalid Subdevice \n"); + } +return insn->n; +} +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_Reset(comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task :Resets the registers of the card | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3501_Reset(comedi_device *dev) +{ +int i_Count=0,i_temp=0; +ULONG ul_Command1 = 0,ul_Polarity,ul_DAC_Ready=0; +outl(0x0,devpriv->iobase+APCI3501_DIGITAL_OP); +outl(1,devpriv->iobase+APCI3501_ANALOG_OUTPUT+APCI3501_AO_VOLT_MODE); + + ul_Polarity=0x80000000; + +for(i_Count=0;i_Count<=7;i_Count++) + { + ul_DAC_Ready=inl(devpriv->iobase+APCI3501_ANALOG_OUTPUT); + + while(ul_DAC_Ready==0) + { + ul_DAC_Ready=inl(devpriv->iobase+APCI3501_ANALOG_OUTPUT); + ul_DAC_Ready=(ul_DAC_Ready>>8)&1; + } + + if(ul_DAC_Ready) + { + // Output the Value on the output channels. + ul_Command1=(ULONG)((ULONG)(i_Count & 0xFF)|(ULONG)((i_temp << 0x8)&0x7FFFFF00L)|(ULONG)(ul_Polarity)); + outl(ul_Command1,devpriv->iobase+APCI3501_ANALOG_OUTPUT+APCI3501_AO_PROG); + } + } + +return 0; +} + + + + + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI3501_Interrupt | +| (int irq , void *d, struct pt_regs *regs) | ++----------------------------------------------------------------------------+ +| Task : Interrupt processing Routine | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | +| struct pt_regs *regs : structure pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + void v_APCI3501_Interrupt(int irq, void *d, struct pt_regs *regs) +{ + int i_temp; + comedi_device *dev = d; + unsigned int ui_Timer_AOWatchdog ; + unsigned long ul_Command1; + // Disable Interrupt + ul_Command1=inl(devpriv->iobase+APCI3501_WATCHDOG +APCI3501_TCW_PROG); + + ul_Command1 = (ul_Command1 & 0xFFFFF9FDul); + outl(ul_Command1 , devpriv->iobase+APCI3501_WATCHDOG +APCI3501_TCW_PROG); + + + ui_Timer_AOWatchdog=inl(devpriv->iobase+APCI3501_WATCHDOG +APCI3501_TCW_IRQ )& 0x1; + + if ((!ui_Timer_AOWatchdog)) + { + comedi_error(dev,"IRQ from unknow source"); + return; + } + + + // Enable Interrupt + //Send a signal to from kernel to user space + send_sig(SIGIO,devpriv->tsk_Current,0); + ul_Command1=inl(devpriv->iobase+APCI3501_WATCHDOG +APCI3501_TCW_PROG); + ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1); + outl(ul_Command1 , devpriv->iobase+APCI3501_WATCHDOG +APCI3501_TCW_PROG); + i_temp= inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_TRIG_STATUS)&0x1; +return; +} + + + diff --git a/comedi/drivers/addi-data/hwdrv_apci3501.h b/comedi/drivers/addi-data/hwdrv_apci3501.h new file mode 100644 index 00000000..957abae5 --- /dev/null +++ b/comedi/drivers/addi-data/hwdrv_apci3501.h @@ -0,0 +1,71 @@ +// Card Specific information +#define APCI3501_BOARD_VENDOR_ID 0x15B8 +#define APCI3501_ADDRESS_RANGE 255 + +#define APCI3501_DIGITAL_IP 0x50 +#define APCI3501_DIGITAL_OP 0x40 +#define APCI3501_ANALOG_OUTPUT 0x00 + +//Analog Output related Defines +#define APCI3501_AO_VOLT_MODE 0 +#define APCI3501_AO_PROG 4 +#define APCI3501_AO_TRIG_SCS 8 +#define UNIPOLAR 0 +#define BIPOLAR 1 +#define MODE0 0 +#define MODE1 1 +// ANALOG OUTPUT RANGE +comedi_lrange range_apci3501_ao= { 2, { + BIP_RANGE(10), + UNI_RANGE(10) + } +}; + +//Watchdog Related Defines + +#define APCI3501_WATCHDOG 0x20 +#define APCI3501_TCW_SYNC_ENABLEDISABLE 0 +#define APCI3501_TCW_RELOAD_VALUE 4 +#define APCI3501_TCW_TIMEBASE 8 +#define APCI3501_TCW_PROG 12 +#define APCI3501_TCW_TRIG_STATUS 16 +#define APCI3501_TCW_IRQ 20 +#define APCI3501_TCW_WARN_TIMEVAL 24 +#define APCI3501_TCW_WARN_TIMEBASE 28 +#define ADDIDATA_TIMER 0 +#define ADDIDATA_WATCHDOG 2 + + +// Hardware Layer functions for Apci3501 + +//AO +INT i_APCI3501_ConfigAnalogOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI3501_WriteAnalogOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +//DI +// for di read +//INT i_APCI3501_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +INT i_APCI3501_ReadDigitalInput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +//DO +int i_APCI3501_ConfigDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI3501_WriteDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +INT i_APCI3501_ReadDigitalOutput(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); + +// TIMER +// timer value is passed as u seconds +INT i_APCI3501_ConfigTimerCounterWatchdog (comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI3501_StartStopWriteTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +int i_APCI3501_ReadTimerCounterWatchdog(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); +//Interrupt +void v_APCI3501_Interrupt(int irq, void *d, struct pt_regs *regs) ; + +//Reset functions + int i_APCI3501_Reset(comedi_device *dev); + + + + + + -- 2.26.2