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