/* * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. * * ADDI-DATA GmbH * Dieselstrasse 3 * D-77833 Ottersweier * Tel: +19(0)7223/9493-0 * Fax: +49(0)7223/9493-92 * http://www.addi-data-com * info@addi-data.com * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. */ /* | Description : APCI-1710 82X54 timer module | */ #include "APCI1710_82x54.h" /* +----------------------------------------------------------------------------+ | Function Name : _INT_ i_APCI1710_InitTimer | | (unsigned char_ b_BoardHandle, | | unsigned char_ b_ModulNbr, | | unsigned char_ b_TimerNbr, | | unsigned char_ b_TimerMode, | | ULONG_ ul_ReloadValue, | | unsigned char_ b_InputClockSelection, | | unsigned char_ b_InputClockLevel, | | unsigned char_ b_OutputLevel, | | unsigned char_ b_HardwareGateLevel) int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Configure the Timer (b_TimerNbr) operating mode | | (b_TimerMode) from selected module (b_ModulNbr). | | You must calling this function be for you call any | | other function witch access of the timer. | | | | | | Timer mode description table | | | |+--------+-----------------------------+--------------+--------------------+| ||Selected+ Mode description +u_ReloadValue | Hardware gate input|| || mode | | description | action || |+--------+-----------------------------+--------------+--------------------+| || |Mode 0 is typically used | | || || |for event counting. After | | || || |the initialisation, OUT | | || || |is initially low, and | | || || 0 |will remain low until the |Start counting| Hardware gate || || |counter reaches zero. | value | || || |OUT then goes high and | | || || |remains high until a new | | || || |count is written. See | | || || |"i_APCI1710_WriteTimerValue" | | || || |function. | | || |+--------+-----------------------------+--------------+--------------------+| || |Mode 1 is similar to mode 0 | | || || |except for the gate input | | || || 1 |action. The gate input is not|Start counting| Hardware trigger || || |used for enabled or disabled | value | || || |the timer. | | || || |The gate input is used for | | || || |triggered the timer. | | || |+--------+-----------------------------+--------------+--------------------+| || |This mode functions like a | | || || |divide-by-ul_ReloadValue | | || || |counter. It is typically used| | || || |to generate a real time clock| | || || |interrupt. OUT will initially| | || || 2 |be high after the | Division | Hardware gate || || |initialisation. When the | factor | || || |initial count has decremented| | || || |to 1, OUT goes low for one | | || || |CLK pule. OUT then goes high | | || || |again, the counter reloads | | || || |the initial count | | || || |(ul_ReloadValue) and the | | || || |process is repeated. | | || || |This action can generated a | | || || |interrupt. See function | | || || |"i_APCI1710_SetBoardInt- | | || || |RoutineX" | | || || |and "i_APCI1710_EnableTimer" | | || |+--------+-----------------------------+--------------+--------------------+| || |Mode 3 is typically used for | | || || |baud rate generation. This | | || || |mode is similar to mode 2 | | || || |except for the duty cycle of | | || || 3 |OUT. OUT will initially be | Division | Hardware gate || || |high after the initialisation| factor | || || |When half the initial count | | || || |(ul_ReloadValue) has expired,| | || || |OUT goes low for the | | || || |remainder of the count. The | | || || |mode is periodic; the | | || || |sequence above is repeated | | || || |indefinitely. | | || |+--------+-----------------------------+--------------+--------------------+| || |OUT will be initially high | | || || |after the initialisation. | | || || |When the initial count | | || || 4 |expires OUT will go low for |Start counting| Hardware gate || || |one CLK pulse and then go | value | || || |high again. | | || || |The counting sequences is | | || || |triggered by writing a new | | || || |value. See | | || || |"i_APCI1710_WriteTimerValue" | | || || |function. If a new count is | | || || |written during counting, | | || || |it will be loaded on the | | || || |next CLK pulse | | || |+--------+-----------------------------+--------------+--------------------+| || |Mode 5 is similar to mode 4 | | || || |except for the gate input | | || || |action. The gate input is not| | || || 5 |used for enabled or disabled |Start counting| Hardware trigger || || |the timer. The gate input is | value | || || |used for triggered the timer.| | || |+--------+-----------------------------+--------------+--------------------+| | | | | | | | Input clock selection table | | | | +--------------------------------+------------------------------------+ | | | b_InputClockSelection | Description | | | | parameter | | | | +--------------------------------+------------------------------------+ | | | APCI1710_PCI_BUS_CLOCK | For the timer input clock, the PCI | | | | | bus clock / 4 is used. This PCI bus| | | | | clock can be 30MHz or 33MHz. For | | | | | Timer 0 only this selection are | | | | | available. | | | +--------------------------------+------------------------------------+ | | | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the| | | | | possibility to inject a input clock| | | | | for Timer 1 or Timer 2. The source | | | | | from this clock can eat the output | | | | | clock from Timer 0 or any other | | | | | clock source. | | | +--------------------------------+------------------------------------+ | | | +----------------------------------------------------------------------------+ | Input Parameters : unsigned char_ b_BoardHandle : Handle of board | | APCI-1710 | | unsigned char_ b_ModulNbr : Module number to | | configure (0 to 3) | | unsigned char_ b_TimerNbr : Timer number to | | configure (0 to 2) | | unsigned char_ 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. | | unsigned char_ b_InputClockSelection : Selection from input | | timer clock. | | See input clock | | selection table. | | unsigned char_ b_InputClockLevel : Selection from input | | clock level. | | 0 : Low active | | (Input inverted) | | 1 : High active | | unsigned char_ b_OutputLevel, : Selection from output | | clock level. | | 0 : Low active | | 1 : High active | | (Output inverted) | | unsigned char_ 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 = (unsigned char) CR_AREF(insn->chanspec); b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); b_TimerMode = (unsigned char) data[0]; ul_ReloadValue = (unsigned int) data[1]; b_InputClockSelection =(unsigned char) data[2]; b_InputClockLevel =(unsigned char) data[3]; b_OutputLevel =(unsigned char) data[4]; b_HardwareGateLevel =(unsigned char) data[5]; +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : 0: No error | | -1: The handle parameter of the board is wrong | | -2: Module selection wrong | | -3: Timer selection wrong | | -4: The module is not a TIMER module | | -5: Timer mode selection is wrong | | -6: Input timer clock selection is wrong | | -7: Selection from input clock level is wrong | | -8: Selection from output clock level is wrong | | -9: Selection from hardware gate level is wrong | +----------------------------------------------------------------------------+ */ int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i_ReturnValue = 0; unsigned char b_ModulNbr; unsigned char b_TimerNbr; unsigned char b_TimerMode; unsigned int ul_ReloadValue; unsigned char b_InputClockSelection; unsigned char b_InputClockLevel; unsigned char b_OutputLevel; unsigned char b_HardwareGateLevel; /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ unsigned int dw_Test = 0; /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ i_ReturnValue = insn->n; b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); b_TimerMode = (unsigned char) data[0]; ul_ReloadValue = (unsigned int) data[1]; b_InputClockSelection = (unsigned char) data[2]; b_InputClockLevel = (unsigned char) data[3]; b_OutputLevel = (unsigned char) data[4]; b_HardwareGateLevel = (unsigned char) data[5]; /* Test the module number */ if (b_ModulNbr < 4) { /* Test if 82X54 timer */ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { /* Test the timer number */ if (b_TimerNbr <= 2) { /* Test the timer mode */ if (b_TimerMode <= 5) { /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ /* Test te imput clock selection */ /* if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) || ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1)))) */ if (((b_TimerNbr == 0) && (b_InputClockSelection == APCI1710_PCI_BUS_CLOCK)) || ((b_TimerNbr == 0) && (b_InputClockSelection == APCI1710_10MHZ)) || ((b_TimerNbr != 0) && ((b_InputClockSelection == APCI1710_PCI_BUS_CLOCK) || (b_InputClockSelection == APCI1710_FRONT_CONNECTOR_INPUT) || (b_InputClockSelection == APCI1710_10MHZ)))) { /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ if (((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) || (b_InputClockSelection != APCI1710_10MHZ)) { /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ /* Test the input clock level selection */ if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) { /* Test the output clock level selection */ if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) { /* Test the hardware gate level selection */ if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) { /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ /* Test if version > 1.1 and clock selection = 10MHz */ if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) { /* Test if 40MHz quartz on board */ dw_Test = inl(devpriv->s_BoardInfos.ui_Address + (16 + (b_TimerNbr * 4) + (64 * b_ModulNbr))); dw_Test = (dw_Test >> 16) & 1; } else { dw_Test = 1; } /* Test if detection OK */ if (dw_Test == 1) { /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ /* Initialisation OK */ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init = 1; /* Save the input clock selection */ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockSelection = b_InputClockSelection; /* Save the input clock level */ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockLevel = ~b_InputClockLevel & 1; /* Save the output level */ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel = ~b_OutputLevel & 1; /* Save the gate level */ devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel; /* Set the configuration word and disable the timer */ /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ /* devpriv->s_ModuleInfo [b_ModulNbr]. s_82X54ModuleInfo. s_82X54TimerInfo [b_TimerNbr]. dw_ConfigurationWord = (unsigned int) (((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x10)); */ /* Test if 10MHz selected */ if (b_InputClockSelection == APCI1710_10MHZ) { b_InputClockSelection = 2; } devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (unsigned int)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30)); /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); /* Initialise the 82X54 Timer */ outl((unsigned int) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); /* Write the reload value */ outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ } /* if (dw_Test == 1) */ else { /* Input timer clock selection is wrong */ i_ReturnValue = -6; } /* if (dw_Test == 1) */ /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ } /* if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */ else { /* Selection from hardware gate level is wrong */ DPRINTK("Selection from hardware gate level is wrong\n"); i_ReturnValue = -9; } /* if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */ } /* if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */ else { /* Selection from output clock level is wrong */ DPRINTK("Selection from output clock level is wrong\n"); i_ReturnValue = -8; } /* if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */ } /* if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */ else { /* Selection from input clock level is wrong */ DPRINTK("Selection from input clock level is wrong\n"); i_ReturnValue = -7; } /* if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */ } else { /* Input timer clock selection is wrong */ DPRINTK("Input timer clock selection is wrong\n"); i_ReturnValue = -6; } } else { /* Input timer clock selection is wrong */ DPRINTK("Input timer clock selection is wrong\n"); i_ReturnValue = -6; } } /* if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */ else { /* Timer mode selection is wrong */ DPRINTK("Timer mode selection is wrong\n"); i_ReturnValue = -5; } /* if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */ } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ else { /* Timer selection wrong */ DPRINTK("Timer selection wrong\n"); i_ReturnValue = -3; } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ } else { /* The module is not a TIMER module */ DPRINTK("The module is not a TIMER module\n"); i_ReturnValue = -4; } } else { /* Module number error */ DPRINTK("Module number error\n"); i_ReturnValue = -2; } return i_ReturnValue; } /* +----------------------------------------------------------------------------+ | Function Name : _INT_ i_APCI1710_EnableTimer | | (unsigned char_ b_BoardHandle, | | unsigned char_ b_ModulNbr, | | unsigned char_ b_TimerNbr, | | unsigned char_ b_InterruptEnable) int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Enable OR Disable the Timer (b_TimerNbr) from selected module | | (b_ModulNbr). You must calling the | | "i_APCI1710_InitTimer" function be for you call this | | function. If you enable the timer interrupt, the timer | | generate a interrupt after the timer value reach | | the zero. See function "i_APCI1710_SetBoardIntRoutineX"| +----------------------------------------------------------------------------+ | Input Parameters : unsigned char_ b_BoardHandle : Handle of board | | APCI-1710 | | unsigned char_ b_ModulNbr : Selected module number | | (0 to 3) | | unsigned char_ b_TimerNbr : Timer number to enable | | (0 to 2) | | unsigned char_ 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 = (unsigned char) CR_AREF(insn->chanspec); b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); b_ActionType = (unsigned char) data[0]; /* enable disable */ +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : 0: No error | | -1: The handle parameter of the board is wrong | | -2: Module selection wrong | | -3: Timer selection wrong | | -4: The module is not a TIMER module | | -5: Timer not initialised see function | | "i_APCI1710_InitTimer" | | -6: Interrupt parameter is wrong | | -7: Interrupt function not initialised. | | See function "i_APCI1710_SetBoardIntRoutineX" | +----------------------------------------------------------------------------+ */ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i_ReturnValue = 0; unsigned int dw_DummyRead; unsigned char b_ModulNbr; unsigned char b_TimerNbr; unsigned char b_ActionType; unsigned char b_InterruptEnable; i_ReturnValue = insn->n; b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); b_ActionType = (unsigned char) data[0]; /* enable disable */ /* Test the module number */ if (b_ModulNbr < 4) { /* Test if 82X54 timer */ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { /* Test the timer number */ if (b_TimerNbr <= 2) { /* Test if timer initialised */ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { switch (b_ActionType) { case APCI1710_ENABLE: b_InterruptEnable = (unsigned char) 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 | | (unsigned char_ b_BoardHandle, | | unsigned char_ b_ModulNbr, | | PULONG_ pul_TimerValueArray) int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Return the all timer values from selected timer | | module (b_ModulNbr). | +----------------------------------------------------------------------------+ | Input Parameters : unsigned char_ b_BoardHandle : Handle of board | | APCI-1710 | | unsigned char_ b_ModulNbr : Selected module number | | (0 to 3) | +----------------------------------------------------------------------------+ | Output Parameters : PULONG_ pul_TimerValueArray : Timer value array. | | Element 0 contain the timer 0 value. | | Element 1 contain the timer 1 value. | | Element 2 contain the timer 2 value. | +----------------------------------------------------------------------------+ | Return Value : 0: No error | | -1: The handle parameter of the board is wrong | | -2: Module selection wrong | | -3: The module is not a TIMER module | | -4: Timer 0 not initialised see function | | "i_APCI1710_InitTimer" | | -5: Timer 1 not initialised see function | | "i_APCI1710_InitTimer" | | -6: Timer 2 not initialised see function | | "i_APCI1710_InitTimer" | +----------------------------------------------------------------------------+ */ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i_ReturnValue = 0; unsigned char b_ModulNbr, b_ReadType; unsigned int *pul_TimerValueArray; b_ModulNbr = CR_AREF(insn->chanspec); b_ReadType = CR_CHAN(insn->chanspec); pul_TimerValueArray = (unsigned int *) data; i_ReturnValue = insn->n; switch (b_ReadType) { case APCI1710_TIMER_READINTERRUPT: data[0] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].b_OldModuleMask; data[1] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldInterruptMask; data[2] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; /* Increment the read FIFO */ devpriv->s_InterruptParameters.ui_Read = (devpriv->s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; break; case APCI1710_TIMER_READALLTIMER: /* Test the module number */ if (b_ModulNbr < 4) { /* Test if 82X54 timer */ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { /* Test if timer 0 iniutialised */ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[0].b_82X54Init == 1) { /* Test if timer 1 iniutialised */ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[1].b_82X54Init == 1) { /* Test if timer 2 iniutialised */ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[2].b_82X54Init == 1) { /* Latch all counter */ outl(0x17, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); /* Read the timer 0 value */ pul_TimerValueArray[0] = inl(devpriv->s_BoardInfos.ui_Address + 0 + (64 * b_ModulNbr)); /* Read the timer 1 value */ pul_TimerValueArray[1] = inl(devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); /* Read the timer 2 value */ pul_TimerValueArray[2] = inl(devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr)); } else { /* Timer 2 not initialised see function */ DPRINTK("Timer 2 not initialised see function\n"); i_ReturnValue = -6; } } else { /* Timer 1 not initialised see function */ DPRINTK("Timer 1 not initialised see function\n"); i_ReturnValue = -5; } } else { /* Timer 0 not initialised see function */ DPRINTK("Timer 0 not initialised see function\n"); i_ReturnValue = -4; } } else { /* The module is not a TIMER module */ DPRINTK("The module is not a TIMER module\n"); i_ReturnValue = -3; } } else { /* Module number error */ DPRINTK("Module number error\n"); i_ReturnValue = -2; } } /* End of Switch */ return i_ReturnValue; } /* +----------------------------------------------------------------------------+ | Function Name :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | +----------------------------------------------------------------------------+ | Task : Read write functions for Timer | +----------------------------------------------------------------------------+ | Input Parameters : +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : +----------------------------------------------------------------------------+ */ int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned char b_BitsType; int i_ReturnValue = 0; b_BitsType = data[0]; printk("\n82X54"); switch (b_BitsType) { case APCI1710_TIMER_READVALUE: i_ReturnValue = i_APCI1710_ReadTimerValue(dev, (unsigned char)CR_AREF(insn->chanspec), (unsigned char)CR_CHAN(insn->chanspec), (unsigned int *) &data[0]); break; case APCI1710_TIMER_GETOUTPUTLEVEL: i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev, (unsigned char)CR_AREF(insn->chanspec), (unsigned char)CR_CHAN(insn->chanspec), (unsigned char *) &data[0]); break; case APCI1710_TIMER_GETPROGRESSSTATUS: i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev, (unsigned char)CR_AREF(insn->chanspec), (unsigned char)CR_CHAN(insn->chanspec), (unsigned char *)&data[0]); break; case APCI1710_TIMER_WRITEVALUE: i_ReturnValue = i_APCI1710_WriteTimerValue(dev, (unsigned char)CR_AREF(insn->chanspec), (unsigned char)CR_CHAN(insn->chanspec), (unsigned int)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 | | (unsigned char_ b_BoardHandle, | | unsigned char_ b_ModulNbr, | | unsigned char_ b_TimerNbr, | | PULONG_ pul_TimerValue) | +----------------------------------------------------------------------------+ | Task : Return the timer value from selected digital timer | | (b_TimerNbr) from selected timer module (b_ModulNbr). | +----------------------------------------------------------------------------+ | Input Parameters : unsigned char_ b_BoardHandle : Handle of board | | APCI-1710 | | unsigned char_ b_ModulNbr : Selected module number | | (0 to 3) | | unsigned char_ b_TimerNbr : Timer number to read | | (0 to 2) | +----------------------------------------------------------------------------+ | Output Parameters : PULONG_ pul_TimerValue : Timer value | +----------------------------------------------------------------------------+ | Return Value : 0: No error | | -1: The handle parameter of the board is wrong | | -2: Module selection wrong | | -3: Timer selection wrong | | -4: The module is not a TIMER module | | -5: Timer not initialised see function | | "i_APCI1710_InitTimer" | +----------------------------------------------------------------------------+ */ int i_APCI1710_ReadTimerValue(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_TimerNbr, unsigned int *pul_TimerValue) { int i_ReturnValue = 0; /* Test the module number */ if (b_ModulNbr < 4) { /* Test if 82X54 timer */ if ((devpriv->s_BoardInfos. dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { /* Test the timer number */ if (b_TimerNbr <= 2) { /* Test if timer initialised */ if (devpriv-> s_ModuleInfo[b_ModulNbr]. s_82X54ModuleInfo. s_82X54TimerInfo[b_TimerNbr]. b_82X54Init == 1) { /* Latch the timer value */ outl((2 << b_TimerNbr) | 0xD0, devpriv->s_BoardInfos. ui_Address + 12 + (64 * b_ModulNbr)); /* Read the counter value */ *pul_TimerValue = inl(devpriv->s_BoardInfos. ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr)); } else { /* Timer not initialised see function */ DPRINTK("Timer not initialised see function\n"); i_ReturnValue = -5; } } else { /* Timer selection wrong */ DPRINTK("Timer selection wrong\n"); i_ReturnValue = -3; } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ } else { /* The module is not a TIMER module */ DPRINTK("The module is not a TIMER module\n"); i_ReturnValue = -4; } } else { /* Module number error */ DPRINTK("Module number error\n"); i_ReturnValue = -2; } return i_ReturnValue; } /* +----------------------------------------------------------------------------+ | Function Name : _INT_ i_APCI1710_GetTimerOutputLevel | | (unsigned char_ b_BoardHandle, | | unsigned char_ b_ModulNbr, | | unsigned char_ b_TimerNbr, | | unsigned char *_ pb_OutputLevel) | +----------------------------------------------------------------------------+ | Task : Return the output signal level (pb_OutputLevel) from | | selected digital timer (b_TimerNbr) from selected timer| | module (b_ModulNbr). | +----------------------------------------------------------------------------+ | Input Parameters : unsigned char_ b_BoardHandle : Handle of board | | APCI-1710 | | unsigned char_ b_ModulNbr : Selected module number | | (0 to 3) | | unsigned char_ b_TimerNbr : Timer number to test | | (0 to 2) | +----------------------------------------------------------------------------+ | Output Parameters : unsigned char *_ pb_OutputLevel : Output signal level | | 0 : The output is low | | 1 : The output is high | +----------------------------------------------------------------------------+ | Return Value : 0: No error | | -1: The handle parameter of the board is wrong | | -2: Module selection wrong | | -3: Timer selection wrong | | -4: The module is not a TIMER module | | -5: Timer not initialised see function | | "i_APCI1710_InitTimer" | +----------------------------------------------------------------------------+ */ int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_TimerNbr, unsigned char *pb_OutputLevel) { int i_ReturnValue = 0; unsigned int dw_TimerStatus; /* Test the module number */ if (b_ModulNbr < 4) { /* Test if 82X54 timer */ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { /* Test the timer number */ if (b_TimerNbr <= 2) { /* Test if timer initialised */ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { /* Latch the timer value */ outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); /* Read the timer status */ dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); *pb_OutputLevel = (unsigned char) (((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 | | (unsigned char_ b_BoardHandle, | | unsigned char_ b_ModulNbr, | | unsigned char_ b_TimerNbr, | | unsigned char *_ pb_TimerStatus) | +----------------------------------------------------------------------------+ | Task : Return the progress status (pb_TimerStatus) from | | selected digital timer (b_TimerNbr) from selected timer| | module (b_ModulNbr). | +----------------------------------------------------------------------------+ | Input Parameters : unsigned char_ b_BoardHandle : Handle of board | | APCI-1710 | | unsigned char_ b_ModulNbr : Selected module number | | (0 to 3) | | unsigned char_ b_TimerNbr : Timer number to test | | (0 to 2) | +----------------------------------------------------------------------------+ | Output Parameters : unsigned char *_ pb_TimerStatus : Output signal level | | 0 : Timer not in progress | | 1 : Timer in progress | +----------------------------------------------------------------------------+ | Return Value : 0: No error | | -1: The handle parameter of the board is wrong | | -2: Module selection wrong | | -3: Timer selection wrong | | -4: The module is not a TIMER module | | -5: Timer not initialised see function | | "i_APCI1710_InitTimer" | +----------------------------------------------------------------------------+ */ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_TimerNbr, unsigned char *pb_TimerStatus) { int i_ReturnValue = 0; unsigned int dw_TimerStatus; /* Test the module number */ if (b_ModulNbr < 4) { /* Test if 82X54 timer */ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { /* Test the timer number */ if (b_TimerNbr <= 2) { /* Test if timer initialised */ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { /* Latch the timer value */ outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); /* Read the timer status */ dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); *pb_TimerStatus = (unsigned char) ((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 | | (unsigned char_ b_BoardHandle, | | unsigned char_ b_ModulNbr, | | unsigned char_ 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 : unsigned char_ b_BoardHandle : Handle of board | | APCI-1710 | | unsigned char_ b_ModulNbr : Selected module number | | (0 to 3) | | unsigned char_ b_TimerNbr : Timer number to write | | (0 to 2) | | ULONG_ ul_WriteValue : Value to write | +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ | Return Value : 0: No error | | -1: The handle parameter of the board is wrong | | -2: Module selection wrong | | -3: Timer selection wrong | | -4: The module is not a TIMER module | | -5: Timer not initialised see function | | "i_APCI1710_InitTimer" | +----------------------------------------------------------------------------+ */ int i_APCI1710_WriteTimerValue(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_TimerNbr, unsigned int ul_WriteValue) { int i_ReturnValue = 0; /* Test the module number */ if (b_ModulNbr < 4) { /* Test if 82X54 timer */ if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { /* Test the timer number */ if (b_TimerNbr <= 2) { /* Test if timer initialised */ if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { /* Write the value */ outl(ul_WriteValue, devpriv->s_BoardInfos.ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr)); } else { /* Timer not initialised see function */ DPRINTK("Timer not initialised see function\n"); i_ReturnValue = -5; } } else { /* Timer selection wrong */ DPRINTK("Timer selection wrong\n"); i_ReturnValue = -3; } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ } else { /* The module is not a TIMER module */ DPRINTK("The module is not a TIMER module\n"); i_ReturnValue = -4; } } else { /* Module number error */ DPRINTK("Module number error\n"); i_ReturnValue = -2; } return i_ReturnValue; }