blob: 8ebb2544df480e139ef186bbe4eef3adda0e145d [file] [log] [blame]
/**
@verbatim
Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data.com
info@addi-data.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
/*
+-----------------------------------------------------------------------+
| (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
+-----------------------------------------------------------------------+
| Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
| Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
+-----------------------------------------------------------------------+
| Project : API APCI1648 | Compiler : gcc |
| Module name : TTL.C | Version : 2.96 |
+-------------------------------+---------------------------------------+
| Project manager: S. Weber | Date : 25/05/2005 |
+-----------------------------------------------------------------------+
| Description : APCI-16XX TTL I/O module |
| |
| |
+-----------------------------------------------------------------------+
| UPDATES |
+-----------------------------------------------------------------------+
| Date | Author | Description of updates |
+----------+-----------+------------------------------------------------+
|25.05.2005| S.Weber | Creation |
| | | |
+-----------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Included files |
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci16xx.h"
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI16XX_InsnConfigInitTTLIO |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task APCI16XX_TTL_INIT (using defaults) : |
| Configure the TTL I/O operating mode from all ports |
| You must calling this function be |
| for you call any other function witch access of TTL. |
| APCI16XX_TTL_INITDIRECTION(user inputs for direction) |
+----------------------------------------------------------------------------+
| Input Parameters : b_InitType = (unsigned char) data[0]; |
| b_Port0Mode = (unsigned char) data[1]; |
| b_Port1Mode = (unsigned char) data[2]; |
| b_Port2Mode = (unsigned char) data[3]; |
| b_Port3Mode = (unsigned char) data[4]; |
| ........ |
+----------------------------------------------------------------------------+
| Output Parameters : - |
+----------------------------------------------------------------------------+
| Return Value :>0: No error |
| -1: Port 0 mode selection is wrong |
| -2: Port 1 mode selection is wrong |
| -3: Port 2 mode selection is wrong |
| -4: Port 3 mode selection is wrong |
| -X: Port X-1 mode selection is wrong |
| .... |
| -100 : Config command error |
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Command = 0;
unsigned char b_Cpt = 0;
unsigned char b_NumberOfPort =
(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= 1) {
/*******************/
/* Get the command */
/* **************** */
b_Command = (unsigned char) data[0];
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_INIT) ||
(b_Command == APCI16XX_TTL_INITDIRECTION) ||
(b_Command == APCI16XX_TTL_OUTPUTMEMORY)) {
/***************************************/
/* Test the initialisation buffer size */
/***************************************/
if ((b_Command == APCI16XX_TTL_INITDIRECTION)
&& ((unsigned char) (insn->n - 1) != b_NumberOfPort)) {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
if ((b_Command == APCI16XX_TTL_OUTPUTMEMORY)
&& ((unsigned char) (insn->n) != 2)) {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
} else {
/************************/
/* Config command error */
/************************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
/**************************************************************************/
/* Test if no error occur and APCI16XX_TTL_INITDIRECTION command selected */
/**************************************************************************/
if ((i_ReturnValue >= 0) && (b_Command == APCI16XX_TTL_INITDIRECTION)) {
memset(devpriv->ul_TTLPortConfiguration, 0,
sizeof(devpriv->ul_TTLPortConfiguration));
/*************************************/
/* Test the port direction selection */
/*************************************/
for (b_Cpt = 1;
(b_Cpt <= b_NumberOfPort) && (i_ReturnValue >= 0);
b_Cpt++) {
/**********************/
/* Test the direction */
/**********************/
if ((data[b_Cpt] != 0) && (data[b_Cpt] != 0xFF)) {
/************************/
/* Port direction error */
/************************/
printk("\nPort %d direction selection error",
(int) b_Cpt);
i_ReturnValue = -(int) b_Cpt;
}
/**************************/
/* Save the configuration */
/**************************/
devpriv->ul_TTLPortConfiguration[(b_Cpt - 1) / 4] =
devpriv->ul_TTLPortConfiguration[(b_Cpt -
1) / 4] | (data[b_Cpt] << (8 * ((b_Cpt -
1) % 4)));
}
}
/**************************/
/* Test if no error occur */
/**************************/
if (i_ReturnValue >= 0) {
/***********************************/
/* Test if TTL port initilaisation */
/***********************************/
if ((b_Command == APCI16XX_TTL_INIT)
|| (b_Command == APCI16XX_TTL_INITDIRECTION)) {
/******************************/
/* Set all port configuration */
/******************************/
for (b_Cpt = 0; b_Cpt <= b_NumberOfPort; b_Cpt++) {
if ((b_Cpt % 4) == 0) {
/*************************/
/* Set the configuration */
/*************************/
outl(devpriv->
ul_TTLPortConfiguration[b_Cpt /
4],
devpriv->iobase + 32 + b_Cpt);
}
}
}
}
/************************************************/
/* Test if output memory initialisation command */
/************************************************/
if (b_Command == APCI16XX_TTL_OUTPUTMEMORY) {
if (data[1]) {
devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
} else {
devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
}
}
return i_ReturnValue;
}
/*
+----------------------------------------------------------------------------+
| INPUT FUNCTIONS |
+----------------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI16XX_InsnBitsReadTTLIO |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read the status from selected TTL digital input |
| (b_InputChannel) |
+----------------------------------------------------------------------------+
| Task : Read the status from digital input port |
| (b_SelectedPort) |
+----------------------------------------------------------------------------+
| Input Parameters : |
| APCI16XX_TTL_READCHANNEL |
| b_SelectedPort= CR_RANGE(insn->chanspec); |
| b_InputChannel= CR_CHAN(insn->chanspec); |
| b_ReadType = (unsigned char) data[0]; |
| |
| APCI16XX_TTL_READPORT |
| b_SelectedPort= CR_RANGE(insn->chanspec); |
| b_ReadType = (unsigned char) data[0]; |
+----------------------------------------------------------------------------+
| Output Parameters : data[0] 0 : Channle is not active |
| 1 : Channle is active |
+----------------------------------------------------------------------------+
| Return Value : >0 : No error |
| -100 : Config command error |
| -101 : Data size error |
| -102 : The selected TTL input port is wrong |
| -103 : The selected TTL digital input is wrong |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Command = 0;
unsigned char b_NumberOfPort =
(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
unsigned char b_InputChannel = CR_CHAN(insn->chanspec);
unsigned char *pb_Status;
unsigned int dw_Status;
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= 1) {
/*******************/
/* Get the command */
/* **************** */
b_Command = (unsigned char) data[0];
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_READCHANNEL)
|| (b_Command == APCI16XX_TTL_READPORT)) {
/**************************/
/* Test the selected port */
/**************************/
if (b_SelectedPort < b_NumberOfPort) {
/**********************/
/* Test if input port */
/**********************/
if (((devpriv->ul_TTLPortConfiguration
[b_SelectedPort /
4] >> (8 *
(b_SelectedPort
%
4))) &
0xFF) == 0) {
/***************************/
/* Test the channel number */
/***************************/
if ((b_Command ==
APCI16XX_TTL_READCHANNEL)
&& (b_InputChannel > 7)) {
/*******************************************/
/* The selected TTL digital input is wrong */
/*******************************************/
printk("\nChannel selection error");
i_ReturnValue = -103;
}
} else {
/****************************************/
/* The selected TTL input port is wrong */
/****************************************/
printk("\nPort selection error");
i_ReturnValue = -102;
}
} else {
/****************************************/
/* The selected TTL input port is wrong */
/****************************************/
printk("\nPort selection error");
i_ReturnValue = -102;
}
} else {
/************************/
/* Config command error */
/************************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
/**************************/
/* Test if no error occur */
/**************************/
if (i_ReturnValue >= 0) {
pb_Status = (unsigned char *) &data[0];
/*******************************/
/* Get the digital inpu status */
/*******************************/
dw_Status =
inl(devpriv->iobase + 8 + ((b_SelectedPort / 4) * 4));
dw_Status = (dw_Status >> (8 * (b_SelectedPort % 4))) & 0xFF;
/***********************/
/* Save the port value */
/***********************/
*pb_Status = (unsigned char) dw_Status;
/***************************************/
/* Test if read channel status command */
/***************************************/
if (b_Command == APCI16XX_TTL_READCHANNEL) {
*pb_Status = (*pb_Status >> b_InputChannel) & 1;
}
}
return i_ReturnValue;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI16XX_InsnReadTTLIOAllPortValue |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Read the status from all digital input ports |
+----------------------------------------------------------------------------+
| Input Parameters : - |
+----------------------------------------------------------------------------+
| Output Parameters : data[0] : Port 0 to 3 data |
| data[1] : Port 4 to 7 data |
| .... |
+----------------------------------------------------------------------------+
| Return Value : 0: No error |
| -100 : Read command error |
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
{
unsigned char b_Command = (unsigned char) CR_AREF(insn->chanspec);
int i_ReturnValue = insn->n;
unsigned char b_Cpt = 0;
unsigned char b_NumberOfPort = 0;
unsigned int *pls_ReadData = data;
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_READ_ALL_INPUTS)
|| (b_Command == APCI16XX_TTL_READ_ALL_OUTPUTS)) {
/**********************************/
/* Get the number of 32-Bit ports */
/**********************************/
b_NumberOfPort =
(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 32);
if ((b_NumberOfPort * 32) <
devpriv->ps_BoardInfo->i_NbrTTLChannel) {
b_NumberOfPort = b_NumberOfPort + 1;
}
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= b_NumberOfPort) {
if (b_Command == APCI16XX_TTL_READ_ALL_INPUTS) {
/**************************/
/* Read all digital input */
/**************************/
for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
/************************/
/* Read the 32-Bit port */
/************************/
pls_ReadData[b_Cpt] =
inl(devpriv->iobase + 8 +
(b_Cpt * 4));
/**************************************/
/* Mask all channels used als outputs */
/**************************************/
pls_ReadData[b_Cpt] =
pls_ReadData[b_Cpt] &
(~devpriv->
ul_TTLPortConfiguration[b_Cpt]);
}
} else {
/****************************/
/* Read all digital outputs */
/****************************/
for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) {
/************************/
/* Read the 32-Bit port */
/************************/
pls_ReadData[b_Cpt] =
inl(devpriv->iobase + 20 +
(b_Cpt * 4));
/**************************************/
/* Mask all channels used als outputs */
/**************************************/
pls_ReadData[b_Cpt] =
pls_ReadData[b_Cpt] & devpriv->
ul_TTLPortConfiguration[b_Cpt];
}
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
} else {
/*****************/
/* Command error */
/*****************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
return i_ReturnValue;
}
/*
+----------------------------------------------------------------------------+
| OUTPUT FUNCTIONS |
+----------------------------------------------------------------------------+
*/
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI16XX_InsnBitsWriteTTLIO |
| (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data) |
+----------------------------------------------------------------------------+
| Task : Set the state from selected TTL digital output |
| (b_OutputChannel) |
+----------------------------------------------------------------------------+
| Task : Set the state from digital output port |
| (b_SelectedPort) |
+----------------------------------------------------------------------------+
| Input Parameters : |
| APCI16XX_TTL_WRITECHANNEL_ON | APCI16XX_TTL_WRITECHANNEL_OFF |
| b_SelectedPort = CR_RANGE(insn->chanspec); |
| b_OutputChannel= CR_CHAN(insn->chanspec); |
| b_Command = (unsigned char) data[0]; |
| |
| APCI16XX_TTL_WRITEPORT_ON | APCI16XX_TTL_WRITEPORT_OFF |
| b_SelectedPort = CR_RANGE(insn->chanspec); |
| b_Command = (unsigned char) data[0]; |
+----------------------------------------------------------------------------+
| Output Parameters : data[0] : TTL output port 0 to 3 data |
| data[1] : TTL output port 4 to 7 data |
| .... |
+----------------------------------------------------------------------------+
| Return Value : >0 : No error |
| -100 : Command error |
| -101 : Data size error |
| -102 : The selected TTL output port is wrong |
| -103 : The selected TTL digital output is wrong |
| -104 : Output memory disabled |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Command = 0;
unsigned char b_NumberOfPort =
(unsigned char) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8);
unsigned char b_SelectedPort = CR_RANGE(insn->chanspec);
unsigned char b_OutputChannel = CR_CHAN(insn->chanspec);
unsigned int dw_Status = 0;
/************************/
/* Test the buffer size */
/************************/
if (insn->n >= 1) {
/*******************/
/* Get the command */
/* **************** */
b_Command = (unsigned char) data[0];
/********************/
/* Test the command */
/********************/
if ((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) ||
(b_Command == APCI16XX_TTL_WRITEPORT_ON) ||
(b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) ||
(b_Command == APCI16XX_TTL_WRITEPORT_OFF)) {
/**************************/
/* Test the selected port */
/**************************/
if (b_SelectedPort < b_NumberOfPort) {
/***********************/
/* Test if output port */
/***********************/
if (((devpriv->ul_TTLPortConfiguration
[b_SelectedPort /
4] >> (8 *
(b_SelectedPort
%
4))) &
0xFF) == 0xFF) {
/***************************/
/* Test the channel number */
/***************************/
if (((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) || (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF)) && (b_OutputChannel > 7)) {
/********************************************/
/* The selected TTL digital output is wrong */
/********************************************/
printk("\nChannel selection error");
i_ReturnValue = -103;
}
if (((b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE)) {
/********************************************/
/* The selected TTL digital output is wrong */
/********************************************/
printk("\nOutput memory disabled");
i_ReturnValue = -104;
}
/************************/
/* Test the buffer size */
/************************/
if (((b_Command == APCI16XX_TTL_WRITEPORT_ON) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (insn->n < 2)) {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
} else {
/*****************************************/
/* The selected TTL output port is wrong */
/*****************************************/
printk("\nPort selection error %lX",
(unsigned long)devpriv->
ul_TTLPortConfiguration[0]);
i_ReturnValue = -102;
}
} else {
/****************************************/
/* The selected TTL output port is wrong */
/****************************************/
printk("\nPort selection error %d %d",
b_SelectedPort, b_NumberOfPort);
i_ReturnValue = -102;
}
} else {
/************************/
/* Config command error */
/************************/
printk("\nCommand selection error");
i_ReturnValue = -100;
}
} else {
/*******************/
/* Data size error */
/*******************/
printk("\nBuffer size error");
i_ReturnValue = -101;
}
/**************************/
/* Test if no error occur */
/**************************/
if (i_ReturnValue >= 0) {
/********************************/
/* Get the digital output state */
/********************************/
dw_Status =
inl(devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
/**********************************/
/* Test if output memory not used */
/**********************************/
if (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE) {
/*********************************/
/* Clear the selected port value */
/*********************************/
dw_Status =
dw_Status & (0xFFFFFFFFUL -
(0xFFUL << (8 * (b_SelectedPort % 4))));
}
/******************************/
/* Test if setting channel ON */
/******************************/
if (b_Command == APCI16XX_TTL_WRITECHANNEL_ON) {
dw_Status =
dw_Status | (1UL << ((8 * (b_SelectedPort %
4)) + b_OutputChannel));
}
/***************************/
/* Test if setting port ON */
/***************************/
if (b_Command == APCI16XX_TTL_WRITEPORT_ON) {
dw_Status =
dw_Status | ((data[1] & 0xFF) << (8 *
(b_SelectedPort % 4)));
}
/*******************************/
/* Test if setting channel OFF */
/*******************************/
if (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) {
dw_Status =
dw_Status & (0xFFFFFFFFUL -
(1UL << ((8 * (b_SelectedPort % 4)) +
b_OutputChannel)));
}
/****************************/
/* Test if setting port OFF */
/****************************/
if (b_Command == APCI16XX_TTL_WRITEPORT_OFF) {
dw_Status =
dw_Status & (0xFFFFFFFFUL -
((data[1] & 0xFF) << (8 * (b_SelectedPort %
4))));
}
outl(dw_Status,
devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4));
}
return i_ReturnValue;
}
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+
| Task :resets all the registers |
+----------------------------------------------------------------------------+
| Input Parameters : struct comedi_device *dev |
+----------------------------------------------------------------------------+
| Output Parameters : - |
+----------------------------------------------------------------------------+
| Return Value : - |
+----------------------------------------------------------------------------+
*/
int i_APCI16XX_Reset(struct comedi_device *dev)
{
return 0;
}