Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci2200.c
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 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-2200       | Compiler   : GCC                      |
33   | Module name : hwdrv_apci2200.c| Version    : 2.96                     |
34   +-------------------------------+---------------------------------------+
35   | Project manager: Eric Stolz   | Date       :  02/12/2002              |
36   +-------------------------------+---------------------------------------+
37   | Description :   Hardware Layer Access For APCI-2200                   |
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_apci2200.h"
55
56 /*
57 +----------------------------------------------------------------------------+
58 | Function   Name   : int i_APCI2200_Read1DigitalInput                       |
59 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
60 |                      struct comedi_insn *insn,unsigned int *data)                     |
61 +----------------------------------------------------------------------------+
62 | Task              : Return the status of the digital input                 |
63 +----------------------------------------------------------------------------+
64 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
65 |                      struct comedi_subdevice *s,   :pointer to subdevice structure
66 |                       struct comedi_insn *insn      :pointer to insn structure     |
67 |                     unsigned int *data          : Data Pointer to read status  |
68 +----------------------------------------------------------------------------+
69 | Output Parameters :   --                                                                                                       |
70 +----------------------------------------------------------------------------+
71 | Return Value      : TRUE  : No error occur                                 |
72 |                           : FALSE : Error occur. Return the error          |
73 |                                                                                |
74 +----------------------------------------------------------------------------+
75 */
76 int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
77         struct comedi_insn *insn, unsigned int *data)
78 {
79         unsigned int ui_TmpValue = 0;
80         unsigned int ui_Channel;
81         ui_Channel = CR_CHAN(insn->chanspec);
82         if (ui_Channel <= 7) {
83                 ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
84                 *data = (ui_TmpValue >> ui_Channel) & 0x1;
85         }                       /* if(ui_Channel >= 0 && ui_Channel <=7) */
86         else {
87                 printk("\nThe specified channel does not exist\n");
88                 return -EINVAL; /*  "sorry channel spec wrong " */
89         }                       /* else if(ui_Channel >= 0 && ui_Channel <=7) */
90
91         return insn->n;
92 }
93
94 /*
95 +----------------------------------------------------------------------------+
96 | Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
97 |                         (struct comedi_device *dev,struct comedi_subdevice *s,               |
98 |                     struct comedi_insn *insn,unsigned int *data)                      |
99 +----------------------------------------------------------------------------+
100 | Task              : Return the status of the Requested digital inputs      |
101 +----------------------------------------------------------------------------+
102 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
103 |                      struct comedi_subdevice *s,   :pointer to subdevice structure
104 |                       struct comedi_insn *insn      :pointer to insn structure     |
105 |                      unsigned int *data         : Data Pointer to read status  |
106 +----------------------------------------------------------------------------+
107 | Output Parameters :   --                                                                                                       |
108 +----------------------------------------------------------------------------+
109 | Return Value      : TRUE  : No error occur                                 |
110 |                           : FALSE : Error occur. Return the error          |
111 |                                                                                |
112 +----------------------------------------------------------------------------+
113 */
114
115 int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
116         struct comedi_insn *insn, unsigned int *data)
117 {
118
119         unsigned int ui_PortValue = data[0];
120         unsigned int ui_Mask = 0;
121         unsigned int ui_NoOfChannels;
122
123         ui_NoOfChannels = CR_CHAN(insn->chanspec);
124
125         *data = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
126         switch (ui_NoOfChannels) {
127         case 2:
128                 ui_Mask = 3;
129                 *data = (*data >> (2 * ui_PortValue)) & ui_Mask;
130                 break;
131         case 4:
132                 ui_Mask = 15;
133                 *data = (*data >> (4 * ui_PortValue)) & ui_Mask;
134                 break;
135         case 7:
136                 break;
137
138         default:
139                 printk("\nWrong parameters\n");
140                 return -EINVAL; /*  "sorry channel spec wrong " */
141                 break;
142         }                       /* switch(ui_NoOfChannels) */
143
144         return insn->n;
145 }
146
147 /*
148 +----------------------------------------------------------------------------+
149 | Function   Name   : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
150 |                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
151 |                                                                                    |
152 +----------------------------------------------------------------------------+
153 | Task              : Configures The Digital Output Subdevice.               |
154 +----------------------------------------------------------------------------+
155 | Input Parameters  : struct comedi_device *dev : Driver handle                     |
156 |                     unsigned int *data         : Data Pointer contains         |
157 |                                          configuration parameters as below |
158 |                      struct comedi_subdevice *s,   :pointer to subdevice structure
159 |                       struct comedi_insn *insn      :pointer to insn structure                                                           |
160 |                                         data[0]  :1:Memory on                          |
161 |                                                   0:Memory off                         |
162 |                                                                                                            |
163 |                                                                                                                                        |
164 +----------------------------------------------------------------------------+
165 | Output Parameters :   --                                                                                                       |
166 +----------------------------------------------------------------------------+
167 | Return Value      : TRUE  : No error occur                                 |
168 |                           : FALSE : Error occur. Return the error          |
169 |                                                                                |
170 +----------------------------------------------------------------------------+
171 */
172 int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
173         struct comedi_insn *insn, unsigned int *data)
174 {
175         devpriv->b_OutputMemoryStatus = data[0];
176         return insn->n;
177 }
178
179 /*
180 +----------------------------------------------------------------------------+
181 | Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
182 |                       (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
183 |                     unsigned int *data)                                         |
184 +----------------------------------------------------------------------------+
185 | Task              : Writes port value  To the selected port                |
186 +----------------------------------------------------------------------------+
187 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
188 |                     struct comedi_subdevice *s,   :pointer to subdevice structure
189 |                      struct comedi_insn *insn      :pointer to insn structure      |
190 |                    unsigned int *data           : Data Pointer to read status  |
191 +----------------------------------------------------------------------------+
192 | Output Parameters :   --                                                                                                       |
193 +----------------------------------------------------------------------------+
194 | Return Value      : TRUE  : No error occur                                 |
195 |                           : FALSE : Error occur. Return the error          |
196 |                                                                                |
197 +----------------------------------------------------------------------------+
198 */
199
200 int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
201         struct comedi_insn *insn, unsigned int *data)
202 {
203         unsigned int ui_Temp, ui_Temp1;
204         unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
205         if (devpriv->b_OutputMemoryStatus) {
206                 ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
207
208         }                       /* if(devpriv->b_OutputMemoryStatus ) */
209         else {
210                 ui_Temp = 0;
211         }                       /* if(devpriv->b_OutputMemoryStatus ) */
212         if (data[3] == 0) {
213                 if (data[1] == 0) {
214                         data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
215                         outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP);
216                 }               /* if(data[1]==0) */
217                 else {
218                         if (data[1] == 1) {
219                                 switch (ui_NoOfChannel) {
220
221                                 case 2:
222                                         data[0] =
223                                                 (data[0] << (2 *
224                                                         data[2])) | ui_Temp;
225                                         break;
226
227                                 case 4:
228                                         data[0] =
229                                                 (data[0] << (4 *
230                                                         data[2])) | ui_Temp;
231                                         break;
232
233                                 case 8:
234                                         data[0] =
235                                                 (data[0] << (8 *
236                                                         data[2])) | ui_Temp;
237                                         break;
238                                 case 15:
239                                         data[0] = data[0] | ui_Temp;
240                                         break;
241                                 default:
242                                         comedi_error(dev, " chan spec wrong");
243                                         return -EINVAL; /*  "sorry channel spec wrong " */
244
245                                 }       /* switch(ui_NoOfChannels) */
246
247                                 outw(data[0],
248                                         devpriv->iobase + APCI2200_DIGITAL_OP);
249                         }       /*  if(data[1]==1) */
250                         else {
251                                 printk("\nSpecified channel not supported\n");
252                         }       /* else if(data[1]==1) */
253                 }               /* elseif(data[1]==0) */
254         }                       /* if(data[3]==0) */
255         else {
256                 if (data[3] == 1) {
257                         if (data[1] == 0) {
258                                 data[0] = ~data[0] & 0x1;
259                                 ui_Temp1 = 1;
260                                 ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
261                                 ui_Temp = ui_Temp | ui_Temp1;
262                                 data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
263                                 data[0] = data[0] & ui_Temp;
264                                 outw(data[0],
265                                         devpriv->iobase + APCI2200_DIGITAL_OP);
266                         }       /* if(data[1]==0) */
267                         else {
268                                 if (data[1] == 1) {
269                                         switch (ui_NoOfChannel) {
270
271                                         case 2:
272                                                 data[0] = ~data[0] & 0x3;
273                                                 ui_Temp1 = 3;
274                                                 ui_Temp1 =
275                                                         ui_Temp1 << 2 * data[2];
276                                                 ui_Temp = ui_Temp | ui_Temp1;
277                                                 data[0] =
278                                                         ((data[0] << (2 *
279                                                                         data
280                                                                         [2])) ^
281                                                         0xffff) & ui_Temp;
282                                                 break;
283
284                                         case 4:
285                                                 data[0] = ~data[0] & 0xf;
286                                                 ui_Temp1 = 15;
287                                                 ui_Temp1 =
288                                                         ui_Temp1 << 4 * data[2];
289                                                 ui_Temp = ui_Temp | ui_Temp1;
290                                                 data[0] =
291                                                         ((data[0] << (4 *
292                                                                         data
293                                                                         [2])) ^
294                                                         0xffff) & ui_Temp;
295                                                 break;
296
297                                         case 8:
298                                                 data[0] = ~data[0] & 0xff;
299                                                 ui_Temp1 = 255;
300                                                 ui_Temp1 =
301                                                         ui_Temp1 << 8 * data[2];
302                                                 ui_Temp = ui_Temp | ui_Temp1;
303                                                 data[0] =
304                                                         ((data[0] << (8 *
305                                                                         data
306                                                                         [2])) ^
307                                                         0xffff) & ui_Temp;
308                                                 break;
309                                         case 15:
310                                                 break;
311
312                                         default:
313                                                 comedi_error(dev,
314                                                         " chan spec wrong");
315                                                 return -EINVAL; /*  "sorry channel spec wrong " */
316
317                                         }       /* switch(ui_NoOfChannels) */
318
319                                         outw(data[0],
320                                                 devpriv->iobase +
321                                                 APCI2200_DIGITAL_OP);
322                                 }       /*  if(data[1]==1) */
323                                 else {
324                                         printk("\nSpecified channel not supported\n");
325                                 }       /* else if(data[1]==1) */
326                         }       /* elseif(data[1]==0) */
327                 }               /* if(data[3]==1); */
328                 else {
329                         printk("\nSpecified functionality does not exist\n");
330                         return -EINVAL;
331                 }               /* if else data[3]==1) */
332         }                       /* if else data[3]==0) */
333         return insn->n;
334 }
335
336 /*
337 +----------------------------------------------------------------------------+
338 | Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
339 |                       (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
340 |                    unsigned int *data)                                             |
341 +----------------------------------------------------------------------------+
342 | Task              : Read  value  of the selected channel or port           |
343 +----------------------------------------------------------------------------+
344 | Input Parameters  : struct comedi_device *dev      : Driver handle                |
345 |                     struct comedi_subdevice *s,   :pointer to subdevice structure
346 |                     struct comedi_insn *insn      :pointer to insn structure      |
347 |                     unsigned int *data          : Data Pointer to read status  |
348 +----------------------------------------------------------------------------+
349 | Output Parameters :   --                                                                                                       |
350 +----------------------------------------------------------------------------+
351 | Return Value      : TRUE  : No error occur                                 |
352 |                           : FALSE : Error occur. Return the error          |
353 |                                                                                |
354 +----------------------------------------------------------------------------+
355 */
356
357 int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
358         struct comedi_insn *insn, unsigned int *data)
359 {
360
361         unsigned int ui_Temp;
362         unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);  /*  get the channel */
363         ui_Temp = data[0];
364         *data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
365         if (ui_Temp == 0) {
366                 *data = (*data >> ui_NoOfChannel) & 0x1;
367         }                       /* if(ui_Temp==0) */
368         else {
369                 if (ui_Temp == 1) {
370                         switch (ui_NoOfChannel) {
371
372                         case 2:
373                                 *data = (*data >> (2 * data[1])) & 3;
374                                 break;
375
376                         case 4:
377                                 *data = (*data >> (4 * data[1])) & 15;
378                                 break;
379
380                         case 8:
381                                 *data = (*data >> (8 * data[1])) & 255;
382                                 break;
383
384                         case 15:
385                                 break;
386
387                         default:
388                                 comedi_error(dev, " chan spec wrong");
389                                 return -EINVAL; /*  "sorry channel spec wrong " */
390
391                         }       /* switch(ui_NoOfChannels) */
392                 }               /* if(ui_Temp==1) */
393                 else {
394                         printk("\nSpecified channel not supported \n");
395                 }               /* elseif(ui_Temp==1) */
396         }                       /* elseif(ui_Temp==0) */
397         return insn->n;
398 }
399
400 /*
401 +----------------------------------------------------------------------------+
402 | Function   Name   : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
403 |                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
404 |                                                                                    |
405 +----------------------------------------------------------------------------+
406 | Task              : Configures The Watchdog                                |
407 +----------------------------------------------------------------------------+
408 | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
409 |                     struct comedi_subdevice *s,   :pointer to subdevice structure
410 |                      struct comedi_insn *insn      :pointer to insn structure      |
411 |                     unsigned int *data          : Data Pointer to read status                                                                                                             |
412 +----------------------------------------------------------------------------+
413 | Output Parameters :   --                                                                                                       |
414 +----------------------------------------------------------------------------+
415 | Return Value      : TRUE  : No error occur                                 |
416 |                           : FALSE : Error occur. Return the error          |
417 |                                                                                |
418 +----------------------------------------------------------------------------+
419 */
420
421 int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
422         struct comedi_insn *insn, unsigned int *data)
423 {
424         if (data[0] == 0) {
425                 /* Disable the watchdog */
426                 outw(0x0,
427                         devpriv->iobase + APCI2200_WATCHDOG +
428                         APCI2200_WATCHDOG_ENABLEDISABLE);
429                 /* Loading the Reload value */
430                 outw(data[1],
431                         devpriv->iobase + APCI2200_WATCHDOG +
432                         APCI2200_WATCHDOG_RELOAD_VALUE);
433                 data[1] = data[1] >> 16;
434                 outw(data[1],
435                         devpriv->iobase + APCI2200_WATCHDOG +
436                         APCI2200_WATCHDOG_RELOAD_VALUE + 2);
437         }                       /* if(data[0]==0) */
438         else {
439                 printk("\nThe input parameters are wrong\n");
440                 return -EINVAL;
441         }                       /* elseif(data[0]==0) */
442
443         return insn->n;
444 }
445
446  /*
447     +----------------------------------------------------------------------------+
448     | Function   Name   : int i_APCI2200_StartStopWriteWatchdog                  |
449     |                           (struct comedi_device *dev,struct comedi_subdevice *s,
450     struct comedi_insn *insn,unsigned int *data);                      |
451     +----------------------------------------------------------------------------+
452     | Task              : Start / Stop The Watchdog                              |
453     +----------------------------------------------------------------------------+
454     | Input Parameters  : struct comedi_device *dev      : Driver handle                |
455     |                     struct comedi_subdevice *s,   :pointer to subdevice structure
456     struct comedi_insn *insn      :pointer to insn structure      |
457     |                     unsigned int *data          : Data Pointer to read status  |
458     +----------------------------------------------------------------------------+
459     | Output Parameters :       --                                                                                                       |
460     +----------------------------------------------------------------------------+
461     | Return Value      : TRUE  : No error occur                                 |
462     |                       : FALSE : Error occur. Return the error          |
463     |                                                                            |
464     +----------------------------------------------------------------------------+
465   */
466
467 int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
468         struct comedi_insn *insn, unsigned int *data)
469 {
470         switch (data[0]) {
471         case 0:         /* stop the watchdog */
472                 outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);       /* disable the watchdog */
473                 break;
474         case 1:         /* start the watchdog */
475                 outw(0x0001,
476                         devpriv->iobase + APCI2200_WATCHDOG +
477                         APCI2200_WATCHDOG_ENABLEDISABLE);
478                 break;
479         case 2:         /* Software trigger */
480                 outw(0x0201,
481                         devpriv->iobase + APCI2200_WATCHDOG +
482                         APCI2200_WATCHDOG_ENABLEDISABLE);
483                 break;
484         default:
485                 printk("\nSpecified functionality does not exist\n");
486                 return -EINVAL;
487         }                       /*  switch(data[0]) */
488         return insn->n;
489 }
490
491 /*
492 +----------------------------------------------------------------------------+
493 | Function   Name   : int i_APCI2200_ReadWatchdog                            |
494 |                       (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
495 |                    unsigned int *data);                                            |
496 +----------------------------------------------------------------------------+
497 | Task              : Read The Watchdog                                      |
498 +----------------------------------------------------------------------------+
499 | Input Parameters  :   struct comedi_device *dev      : Driver handle              |
500 |                     struct comedi_subdevice *s,   :pointer to subdevice structure
501 |                      struct comedi_insn *insn      :pointer to insn structure      |
502 |                     unsigned int *data          : Data Pointer to read status  |
503 +----------------------------------------------------------------------------+
504 | Output Parameters :   --                                                                                                       |
505 +----------------------------------------------------------------------------+
506 | Return Value      : TRUE  : No error occur                                 |
507 |                           : FALSE : Error occur. Return the error          |
508 |                                                                                |
509 +----------------------------------------------------------------------------+
510 */
511
512 int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
513         struct comedi_insn *insn, unsigned int *data)
514 {
515         data[0] =
516                 inw(devpriv->iobase + APCI2200_WATCHDOG +
517                 APCI2200_WATCHDOG_STATUS) & 0x1;
518         return insn->n;
519 }
520
521 /*
522 +----------------------------------------------------------------------------+
523 | Function   Name   : int i_APCI2200_Reset(struct comedi_device *dev)               |                                                                                                          |
524 +----------------------------------------------------------------------------+
525 | Task              :resets all the registers                                |
526 +----------------------------------------------------------------------------+
527 | Input Parameters  : struct comedi_device *dev
528 +----------------------------------------------------------------------------+
529 | Output Parameters :   --                                                                                                       |
530 +----------------------------------------------------------------------------+
531 | Return Value      :                                                        |
532 |                                                                                |
533 +----------------------------------------------------------------------------+
534 */
535
536 int i_APCI2200_Reset(struct comedi_device *dev)
537 {
538         outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);       /* RESETS THE DIGITAL OUTPUTS */
539         outw(0x0,
540                 devpriv->iobase + APCI2200_WATCHDOG +
541                 APCI2200_WATCHDOG_ENABLEDISABLE);
542         outw(0x0,
543                 devpriv->iobase + APCI2200_WATCHDOG +
544                 APCI2200_WATCHDOG_RELOAD_VALUE);
545         outw(0x0,
546                 devpriv->iobase + APCI2200_WATCHDOG +
547                 APCI2200_WATCHDOG_RELOAD_VALUE + 2);
548         return 0;
549 }