hwdrv_apci1032.c revision 3019b4106bf8c2658343a84361f4f1abb6280633
1/** 2@verbatim 3 4Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. 5 6 ADDI-DATA GmbH 7 Dieselstrasse 3 8 D-77833 Ottersweier 9 Tel: +19(0)7223/9493-0 10 Fax: +49(0)7223/9493-92 11 http://www.addi-data-com 12 info@addi-data.com 13 14This 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. 15 16This 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. 17 18You 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 19 20You shoud also find the complete GPL in the COPYING file accompanying this source code. 21 22@endverbatim 23*/ 24/* 25 26 +-----------------------------------------------------------------------+ 27 | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | 28 +-----------------------------------------------------------------------+ 29 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | 30 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | 31 +-------------------------------+---------------------------------------+ 32 | Project : APCI-1032 | Compiler : GCC | 33 | Module name : hwdrv_apci1032.c| Version : 2.96 | 34 +-------------------------------+---------------------------------------+ 35 | Project manager: Eric Stolz | Date : 02/12/2002 | 36 +-------------------------------+---------------------------------------+ 37 | Description : Hardware Layer Acces For APCI-1032 | 38 +-----------------------------------------------------------------------+ 39 | UPDATES | 40 +----------+-----------+------------------------------------------------+ 41 | Date | Author | Description of updates | 42 +----------+-----------+------------------------------------------------+ 43 | | | | 44 | | | | 45 | | | | 46 +----------+-----------+------------------------------------------------+ 47*/ 48 49/* 50+----------------------------------------------------------------------------+ 51| Included files | 52+----------------------------------------------------------------------------+ 53*/ 54#include "hwdrv_apci1032.h" 55#include <linux/delay.h> 56//Global variables 57UINT ui_InterruptStatus = 0; 58 59/* 60+----------------------------------------------------------------------------+ 61| Function Name : int i_APCI1032_ConfigDigitalInput | 62| (struct comedi_device *dev,struct comedi_subdevice *s, | 63| struct comedi_insn *insn,unsigned int *data) | 64+----------------------------------------------------------------------------+ 65| Task : Configures the digital input Subdevice | 66+----------------------------------------------------------------------------+ 67| Input Parameters : struct comedi_device *dev : Driver handle | 68| unsigned int *data : Data Pointer contains | 69| configuration parameters as below | 70| | 71| data[0] : 1 Enable Digital Input Interrupt | 72| 0 Disable Digital Input Interrupt | 73| data[1] : 0 ADDIDATA Interrupt OR LOGIC | 74| : 1 ADDIDATA Interrupt AND LOGIC | 75| data[2] : Interrupt mask for the mode 1 | 76| data[3] : Interrupt mask for the mode 2 | 77| | 78+----------------------------------------------------------------------------+ 79| Output Parameters : -- | 80+----------------------------------------------------------------------------+ 81| Return Value : TRUE : No error occur | 82| : FALSE : Error occur. Return the error | 83| | 84+----------------------------------------------------------------------------+ 85*/ 86 87INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, 88 struct comedi_insn * insn, unsigned int * data) 89{ 90 UINT ui_TmpValue; 91 92 ULONG ul_Command1 = 0; 93 ULONG ul_Command2 = 0; 94 devpriv->tsk_Current = current; 95 96 /*******************************/ 97 /* Set the digital input logic */ 98 /*******************************/ 99 if (data[0] == ADDIDATA_ENABLE) { 100 ul_Command1 = ul_Command1 | data[2]; 101 ul_Command2 = ul_Command2 | data[3]; 102 outl(ul_Command1, 103 devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); 104 outl(ul_Command2, 105 devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); 106 if (data[1] == ADDIDATA_OR) { 107 outl(0x4, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 108 ui_TmpValue = 109 inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 110 } //if (data[1] == ADDIDATA_OR) 111 else { 112 outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 113 } //else if(data[1] == ADDIDATA_OR) 114 } // if( data[0] == ADDIDATA_ENABLE) 115 else { 116 ul_Command1 = ul_Command1 & 0xFFFF0000; 117 ul_Command2 = ul_Command2 & 0xFFFF0000; 118 outl(ul_Command1, 119 devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); 120 outl(ul_Command2, 121 devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); 122 outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 123 } //else if ( data[0] == ADDIDATA_ENABLE) 124 125 return insn->n; 126} 127 128/* 129+----------------------------------------------------------------------------+ 130| Function Name : int i_APCI1032_Read1DigitalInput | 131| (struct comedi_device *dev,struct comedi_subdevice *s, | 132| struct comedi_insn *insn,unsigned int *data) | 133+----------------------------------------------------------------------------+ 134| Task : Return the status of the digital input | 135+----------------------------------------------------------------------------+ 136| Input Parameters : struct comedi_device *dev : Driver handle | 137| UINT ui_Channel : Channel number to read | 138| unsigned int *data : Data Pointer to read status | 139+----------------------------------------------------------------------------+ 140| Output Parameters : -- | 141+----------------------------------------------------------------------------+ 142| Return Value : TRUE : No error occur | 143| : FALSE : Error occur. Return the error | 144| | 145+----------------------------------------------------------------------------+ 146*/ 147INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, 148 struct comedi_insn * insn, unsigned int * data) 149{ 150 UINT ui_TmpValue = 0; 151 UINT ui_Channel; 152 ui_Channel = CR_CHAN(insn->chanspec); 153 if (ui_Channel >= 0 && ui_Channel <= 31) { 154 ui_TmpValue = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP); 155 // since only 1 channel reqd to bring it to last bit it is rotated 156 // 8 +(chan - 1) times then ANDed with 1 for last bit. 157 *data = (ui_TmpValue >> ui_Channel) & 0x1; 158 } //if(ui_Channel >= 0 && ui_Channel <=31) 159 else { 160 //comedi_error(dev," \n chan spec wrong\n"); 161 return -EINVAL; // "sorry channel spec wrong " 162 } //else if(ui_Channel >= 0 && ui_Channel <=31) 163 return insn->n; 164} 165 166/* 167+----------------------------------------------------------------------------+ 168| Function Name : int i_APCI1032_ReadMoreDigitalInput | 169| (struct comedi_device *dev,struct comedi_subdevice *s, | 170| struct comedi_insn *insn,unsigned int *data) | 171+----------------------------------------------------------------------------+ 172| Task : Return the status of the Requested digital inputs | 173+----------------------------------------------------------------------------+ 174| Input Parameters : struct comedi_device *dev : Driver handle | 175| UINT ui_NoOfChannels : No Of Channels To be Read | 176| UINT *data : Data Pointer to read status | 177+----------------------------------------------------------------------------+ 178| Output Parameters : -- | 179+----------------------------------------------------------------------------+ 180| Return Value : TRUE : No error occur | 181| : FALSE : Error occur. Return the error | 182| | 183+----------------------------------------------------------------------------+ 184*/ 185 186INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, 187 struct comedi_insn * insn, unsigned int * data) 188{ 189 UINT ui_PortValue = data[0]; 190 UINT ui_Mask = 0; 191 UINT ui_NoOfChannels; 192 193 ui_NoOfChannels = CR_CHAN(insn->chanspec); 194 if (data[1] == 0) { 195 *data = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP); 196 switch (ui_NoOfChannels) { 197 case 2: 198 ui_Mask = 3; 199 *data = (*data >> (2 * ui_PortValue)) & ui_Mask; 200 break; 201 case 4: 202 ui_Mask = 15; 203 *data = (*data >> (4 * ui_PortValue)) & ui_Mask; 204 break; 205 case 8: 206 ui_Mask = 255; 207 *data = (*data >> (8 * ui_PortValue)) & ui_Mask; 208 break; 209 case 16: 210 ui_Mask = 65535; 211 *data = (*data >> (16 * ui_PortValue)) & ui_Mask; 212 break; 213 case 31: 214 break; 215 default: 216 //comedi_error(dev," \nchan spec wrong\n"); 217 return -EINVAL; // "sorry channel spec wrong " 218 break; 219 } //switch(ui_NoOfChannels) 220 } //if(data[1]==0) 221 else { 222 if (data[1] == 1) { 223 *data = ui_InterruptStatus; 224 } //if(data[1]==1) 225 } //else if(data[1]==0) 226 return insn->n; 227} 228 229/* 230+----------------------------------------------------------------------------+ 231| Function Name : static void v_APCI1032_Interrupt | 232| (int irq , void *d) | 233+----------------------------------------------------------------------------+ 234| Task : Interrupt handler for the interruptible digital inputs | 235+----------------------------------------------------------------------------+ 236| Input Parameters : int irq : irq number | 237| void *d : void pointer | 238+----------------------------------------------------------------------------+ 239| Output Parameters : -- | 240+----------------------------------------------------------------------------+ 241| Return Value : TRUE : No error occur | 242| : FALSE : Error occur. Return the error | 243| | 244+----------------------------------------------------------------------------+ 245*/ 246static void v_APCI1032_Interrupt(int irq, void *d) 247{ 248 struct comedi_device *dev = d; 249 250 UINT ui_Temp; 251 //disable the interrupt 252 ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 253 outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE, 254 devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 255 ui_InterruptStatus = 256 inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); 257 ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF; 258 send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample 259 outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //enable the interrupt 260 return; 261} 262 263/* 264+----------------------------------------------------------------------------+ 265| Function Name : int i_APCI1032_Reset(struct comedi_device *dev) | | 266+----------------------------------------------------------------------------+ 267| Task :resets all the registers | 268+----------------------------------------------------------------------------+ 269| Input Parameters : struct comedi_device *dev 270+----------------------------------------------------------------------------+ 271| Output Parameters : -- | 272+----------------------------------------------------------------------------+ 273| Return Value : | 274| | 275+----------------------------------------------------------------------------+ 276*/ 277 278INT i_APCI1032_Reset(struct comedi_device * dev) 279{ 280 outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //disable the interrupts 281 inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); //Reset the interrupt status register 282 outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt 283 outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); 284 return 0; 285} 286