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 should 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 Access 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 57static unsigned int ui_InterruptStatus; 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 unsigned int ui_TmpValue; 91 92 unsigned int ul_Command1 = 0; 93 unsigned int 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| unsigned int 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 unsigned int ui_TmpValue = 0; 151 unsigned int ui_Channel; 152 ui_Channel = CR_CHAN(insn->chanspec); 153 if (ui_Channel <= 31) { 154 ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP); 155/* 156* since only 1 channel reqd to bring it to last bit it is rotated 8 157* +(chan - 1) times then ANDed with 1 for last bit. 158*/ 159 *data = (ui_TmpValue >> ui_Channel) & 0x1; 160 } /* if(ui_Channel >= 0 && ui_Channel <=31) */ 161 else { 162 /* comedi_error(dev," \n chan spec wrong\n"); */ 163 return -EINVAL; /* "sorry channel spec wrong " */ 164 } /* else if(ui_Channel >= 0 && ui_Channel <=31) */ 165 return insn->n; 166} 167 168/* 169+----------------------------------------------------------------------------+ 170| Function Name : int i_APCI1032_ReadMoreDigitalInput | 171| (struct comedi_device *dev,struct comedi_subdevice *s, | 172| struct comedi_insn *insn,unsigned int *data) | 173+----------------------------------------------------------------------------+ 174| Task : Return the status of the Requested digital inputs | 175+----------------------------------------------------------------------------+ 176| Input Parameters : struct comedi_device *dev : Driver handle | 177| unsigned int ui_NoOfChannels : No Of Channels To be Read | 178| unsigned int *data : Data Pointer to read status | 179+----------------------------------------------------------------------------+ 180| Output Parameters : -- | 181+----------------------------------------------------------------------------+ 182| Return Value : TRUE : No error occur | 183| : FALSE : Error occur. Return the error | 184| | 185+----------------------------------------------------------------------------+ 186*/ 187 188int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, 189 struct comedi_insn *insn, unsigned int *data) 190{ 191 unsigned int ui_PortValue = data[0]; 192 unsigned int ui_Mask = 0; 193 unsigned int ui_NoOfChannels; 194 195 ui_NoOfChannels = CR_CHAN(insn->chanspec); 196 if (data[1] == 0) { 197 *data = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP); 198 switch (ui_NoOfChannels) { 199 case 2: 200 ui_Mask = 3; 201 *data = (*data >> (2 * ui_PortValue)) & ui_Mask; 202 break; 203 case 4: 204 ui_Mask = 15; 205 *data = (*data >> (4 * ui_PortValue)) & ui_Mask; 206 break; 207 case 8: 208 ui_Mask = 255; 209 *data = (*data >> (8 * ui_PortValue)) & ui_Mask; 210 break; 211 case 16: 212 ui_Mask = 65535; 213 *data = (*data >> (16 * ui_PortValue)) & ui_Mask; 214 break; 215 case 31: 216 break; 217 default: 218 /* comedi_error(dev," \nchan spec wrong\n"); */ 219 return -EINVAL; /* "sorry channel spec wrong " */ 220 break; 221 } /* switch(ui_NoOfChannels) */ 222 } /* if(data[1]==0) */ 223 else { 224 if (data[1] == 1) 225 *data = ui_InterruptStatus; 226 /* if(data[1]==1) */ 227 } /* else if(data[1]==0) */ 228 return insn->n; 229} 230 231/* 232+----------------------------------------------------------------------------+ 233| Function Name : static void v_APCI1032_Interrupt | 234| (int irq , void *d) | 235+----------------------------------------------------------------------------+ 236| Task : Interrupt handler for the interruptible digital inputs | 237+----------------------------------------------------------------------------+ 238| Input Parameters : int irq : irq number | 239| void *d : void pointer | 240+----------------------------------------------------------------------------+ 241| Output Parameters : -- | 242+----------------------------------------------------------------------------+ 243| Return Value : TRUE : No error occur | 244| : FALSE : Error occur. Return the error | 245| | 246+----------------------------------------------------------------------------+ 247*/ 248static void v_APCI1032_Interrupt(int irq, void *d) 249{ 250 struct comedi_device *dev = d; 251 252 unsigned int ui_Temp; 253 /* disable the interrupt */ 254 ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 255 outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE, 256 devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); 257 ui_InterruptStatus = 258 inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); 259 ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF; 260 send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ 261 outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); /* enable the interrupt */ 262 return; 263} 264 265/* 266+----------------------------------------------------------------------------+ 267| Function Name : int i_APCI1032_Reset(struct comedi_device *dev) | | 268+----------------------------------------------------------------------------+ 269| Task :resets all the registers | 270+----------------------------------------------------------------------------+ 271| Input Parameters : struct comedi_device *dev 272+----------------------------------------------------------------------------+ 273| Output Parameters : -- | 274+----------------------------------------------------------------------------+ 275| Return Value : | 276| | 277+----------------------------------------------------------------------------+ 278*/ 279 280int i_APCI1032_Reset(struct comedi_device *dev) 281{ 282 outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); /* disable the interrupts */ 283 inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); /* Reset the interrupt status register */ 284 outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); /* Disable the and/or interrupt */ 285 outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); 286 return 0; 287} 288