]>
Commit | Line | Data |
---|---|---|
c995fe94 ADG |
1 | /** |
2 | @verbatim | |
3 | ||
4 | Copyright (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 | ||
14 | 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. | |
15 | ||
16 | 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. | |
17 | ||
18 | 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 | |
19 | ||
20 | You 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> | |
2696fb57 | 56 | /* Global variables */ |
117102b0 | 57 | unsigned int ui_InterruptStatus = 0; |
c995fe94 ADG |
58 | |
59 | /* | |
60 | +----------------------------------------------------------------------------+ | |
61 | | Function Name : int i_APCI1032_ConfigDigitalInput | | |
34c43922 | 62 | | (struct comedi_device *dev,struct comedi_subdevice *s, | |
90035c08 | 63 | | struct comedi_insn *insn,unsigned int *data) | |
c995fe94 ADG |
64 | +----------------------------------------------------------------------------+ |
65 | | Task : Configures the digital input Subdevice | | |
66 | +----------------------------------------------------------------------------+ | |
71b5f4f1 | 67 | | Input Parameters : struct comedi_device *dev : Driver handle | |
790c5541 | 68 | | unsigned int *data : Data Pointer contains | |
c995fe94 ADG |
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 | ||
da91b269 BP |
87 | int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, |
88 | struct comedi_insn *insn, unsigned int *data) | |
c995fe94 | 89 | { |
117102b0 | 90 | unsigned int ui_TmpValue; |
c995fe94 | 91 | |
82a6e2e7 BP |
92 | unsigned int ul_Command1 = 0; |
93 | unsigned int ul_Command2 = 0; | |
c995fe94 ADG |
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); | |
2696fb57 | 110 | } /* if (data[1] == ADDIDATA_OR) */ |
c995fe94 ADG |
111 | else { |
112 | outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); | |
2696fb57 BP |
113 | } /* else if(data[1] == ADDIDATA_OR) */ |
114 | } /* if( data[0] == ADDIDATA_ENABLE) */ | |
c995fe94 ADG |
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); | |
2696fb57 | 123 | } /* else if ( data[0] == ADDIDATA_ENABLE) */ |
c995fe94 ADG |
124 | |
125 | return insn->n; | |
126 | } | |
127 | ||
128 | /* | |
129 | +----------------------------------------------------------------------------+ | |
130 | | Function Name : int i_APCI1032_Read1DigitalInput | | |
34c43922 | 131 | | (struct comedi_device *dev,struct comedi_subdevice *s, | |
90035c08 | 132 | | struct comedi_insn *insn,unsigned int *data) | |
c995fe94 ADG |
133 | +----------------------------------------------------------------------------+ |
134 | | Task : Return the status of the digital input | | |
135 | +----------------------------------------------------------------------------+ | |
71b5f4f1 | 136 | | Input Parameters : struct comedi_device *dev : Driver handle | |
117102b0 | 137 | | unsigned int ui_Channel : Channel number to read | |
790c5541 | 138 | | unsigned int *data : Data Pointer to read status | |
c995fe94 ADG |
139 | +----------------------------------------------------------------------------+ |
140 | | Output Parameters : -- | | |
141 | +----------------------------------------------------------------------------+ | |
142 | | Return Value : TRUE : No error occur | | |
143 | | : FALSE : Error occur. Return the error | | |
144 | | | | |
145 | +----------------------------------------------------------------------------+ | |
146 | */ | |
da91b269 BP |
147 | int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, |
148 | struct comedi_insn *insn, unsigned int *data) | |
c995fe94 | 149 | { |
117102b0 BP |
150 | unsigned int ui_TmpValue = 0; |
151 | unsigned int ui_Channel; | |
c995fe94 ADG |
152 | ui_Channel = CR_CHAN(insn->chanspec); |
153 | if (ui_Channel >= 0 && ui_Channel <= 31) { | |
117102b0 | 154 | ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP); |
2696fb57 BP |
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 | */ | |
c995fe94 | 159 | *data = (ui_TmpValue >> ui_Channel) & 0x1; |
2696fb57 | 160 | } /* if(ui_Channel >= 0 && ui_Channel <=31) */ |
c995fe94 | 161 | else { |
2696fb57 BP |
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) */ | |
c995fe94 ADG |
165 | return insn->n; |
166 | } | |
167 | ||
168 | /* | |
169 | +----------------------------------------------------------------------------+ | |
170 | | Function Name : int i_APCI1032_ReadMoreDigitalInput | | |
34c43922 | 171 | | (struct comedi_device *dev,struct comedi_subdevice *s, | |
90035c08 | 172 | | struct comedi_insn *insn,unsigned int *data) | |
c995fe94 ADG |
173 | +----------------------------------------------------------------------------+ |
174 | | Task : Return the status of the Requested digital inputs | | |
175 | +----------------------------------------------------------------------------+ | |
71b5f4f1 | 176 | | Input Parameters : struct comedi_device *dev : Driver handle | |
117102b0 BP |
177 | | unsigned int ui_NoOfChannels : No Of Channels To be Read | |
178 | | unsigned int *data : Data Pointer to read status | | |
c995fe94 ADG |
179 | +----------------------------------------------------------------------------+ |
180 | | Output Parameters : -- | | |
181 | +----------------------------------------------------------------------------+ | |
182 | | Return Value : TRUE : No error occur | | |
183 | | : FALSE : Error occur. Return the error | | |
184 | | | | |
185 | +----------------------------------------------------------------------------+ | |
186 | */ | |
187 | ||
da91b269 BP |
188 | int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, |
189 | struct comedi_insn *insn, unsigned int *data) | |
c995fe94 | 190 | { |
117102b0 BP |
191 | unsigned int ui_PortValue = data[0]; |
192 | unsigned int ui_Mask = 0; | |
193 | unsigned int ui_NoOfChannels; | |
c995fe94 ADG |
194 | |
195 | ui_NoOfChannels = CR_CHAN(insn->chanspec); | |
196 | if (data[1] == 0) { | |
117102b0 | 197 | *data = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP); |
c995fe94 ADG |
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: | |
2696fb57 BP |
218 | /* comedi_error(dev," \nchan spec wrong\n"); */ |
219 | return -EINVAL; /* "sorry channel spec wrong " */ | |
c995fe94 | 220 | break; |
2696fb57 BP |
221 | } /* switch(ui_NoOfChannels) */ |
222 | } /* if(data[1]==0) */ | |
c995fe94 ADG |
223 | else { |
224 | if (data[1] == 1) { | |
225 | *data = ui_InterruptStatus; | |
2696fb57 BP |
226 | } /* if(data[1]==1) */ |
227 | } /* else if(data[1]==0) */ | |
c995fe94 ADG |
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 | */ | |
3019b410 | 248 | static void v_APCI1032_Interrupt(int irq, void *d) |
c995fe94 | 249 | { |
71b5f4f1 | 250 | struct comedi_device *dev = d; |
c995fe94 | 251 | |
117102b0 | 252 | unsigned int ui_Temp; |
2696fb57 | 253 | /* disable the interrupt */ |
c995fe94 ADG |
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; | |
2696fb57 BP |
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 */ | |
c995fe94 ADG |
262 | return; |
263 | } | |
264 | ||
265 | /* | |
266 | +----------------------------------------------------------------------------+ | |
71b5f4f1 | 267 | | Function Name : int i_APCI1032_Reset(struct comedi_device *dev) | | |
c995fe94 ADG |
268 | +----------------------------------------------------------------------------+ |
269 | | Task :resets all the registers | | |
270 | +----------------------------------------------------------------------------+ | |
71b5f4f1 | 271 | | Input Parameters : struct comedi_device *dev |
c995fe94 ADG |
272 | +----------------------------------------------------------------------------+ |
273 | | Output Parameters : -- | | |
274 | +----------------------------------------------------------------------------+ | |
275 | | Return Value : | | |
276 | | | | |
277 | +----------------------------------------------------------------------------+ | |
278 | */ | |
279 | ||
da91b269 | 280 | int i_APCI1032_Reset(struct comedi_device *dev) |
c995fe94 | 281 | { |
2696fb57 BP |
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 */ | |
c995fe94 ADG |
285 | outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); |
286 | return 0; | |
287 | } |