blob: b59f2d484fd99ecb3c1e7b93053d99bf8cf1ef87 [file] [log] [blame]
/*
* 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;
}