Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwdrv_apci2032.c
Go to the documentation of this file.
1 
24 /*
25 
26  +-----------------------------------------------------------------------+
27  | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
28  +-----------------------------------------------------------------------+
29  | Tel : +49 (0) 7223/9493-0 | email : [email protected] |
30  | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
31  +-------------------------------+---------------------------------------+
32  | Project : APCI-2032 | Compiler : GCC |
33  | Module name : hwdrv_apci2032.c| Version : 2.96 |
34  +-------------------------------+---------------------------------------+
35  | Project manager: Eric Stolz | Date : 02/12/2002 |
36  +-------------------------------+---------------------------------------+
37  | Description : Hardware Layer Access For APCI-2032 |
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 
55 #include "hwdrv_apci2032.h"
56 static unsigned int ui_InterruptData, ui_Type;
57 /*
58 +----------------------------------------------------------------------------+
59 | Function Name : int i_APCI2032_ConfigDigitalOutput |
60 | (struct comedi_device *dev,struct comedi_subdevice *s, |
61 | struct comedi_insn *insn,unsigned int *data) |
62 +----------------------------------------------------------------------------+
63 | Task : Configures The Digital Output Subdevice. |
64 +----------------------------------------------------------------------------+
65 | Input Parameters : struct comedi_device *dev : Driver handle |
66 | unsigned int *data : Data Pointer contains |
67 | configuration parameters as below |
68 | |
69 | data[1] : 1 Enable VCC Interrupt |
70 | 0 Disable VCC Interrupt |
71 | data[2] : 1 Enable CC Interrupt |
72 | 0 Disable CC Interrupt |
73 | |
74 +----------------------------------------------------------------------------+
75 | Output Parameters : -- |
76 +----------------------------------------------------------------------------+
77 | Return Value : TRUE : No error occur |
78 | : FALSE : Error occur. Return the error |
79 | |
80 +----------------------------------------------------------------------------+
81 */
83  struct comedi_insn *insn, unsigned int *data)
84 {
85  unsigned int ul_Command = 0;
86  devpriv->tsk_Current = current;
87 
88  if ((data[0] != 0) && (data[0] != 1)) {
89  comedi_error(dev,
90  "Not a valid Data !!! ,Data should be 1 or 0\n");
91  return -EINVAL;
92  } /* if ( (data[0]!=0) && (data[0]!=1) ) */
93  if (data[0]) {
94  devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
95  } /* if (data[0]) */
96  else {
97  devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
98  } /* else if (data[0]) */
99 
100  if (data[1] == ADDIDATA_ENABLE) {
101  ul_Command = ul_Command | 0x1;
102  } /* if (data[1] == ADDIDATA_ENABLE) */
103  else {
104  ul_Command = ul_Command & 0xFFFFFFFE;
105  } /* elseif (data[1] == ADDIDATA_ENABLE) */
106  if (data[2] == ADDIDATA_ENABLE) {
107  ul_Command = ul_Command | 0x2;
108  } /* if (data[2] == ADDIDATA_ENABLE) */
109  else {
110  ul_Command = ul_Command & 0xFFFFFFFD;
111  } /* elseif (data[2] == ADDIDATA_ENABLE) */
112  outl(ul_Command, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
113  ui_InterruptData = inl(devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT);
114  return insn->n;
115 }
116 
117 /*
118 +----------------------------------------------------------------------------+
119 | Function Name : int i_APCI2032_WriteDigitalOutput |
120 | (struct comedi_device *dev,struct comedi_subdevice *s, |
121 | struct comedi_insn *insn,unsigned int *data) |
122 +----------------------------------------------------------------------------+
123 | Task : Writes port value To the selected port |
124 +----------------------------------------------------------------------------+
125 | Input Parameters : struct comedi_device *dev : Driver handle |
126 | unsigned int ui_NoOfChannels : No Of Channels To Write |
127 | unsigned int *data : Data Pointer to read status |
128 +----------------------------------------------------------------------------+
129 | Output Parameters : -- |
130 +----------------------------------------------------------------------------+
131 | Return Value : TRUE : No error occur |
132 | : FALSE : Error occur. Return the error |
133 | |
134 +----------------------------------------------------------------------------+
135 */
136 
138  struct comedi_insn *insn, unsigned int *data)
139 {
140  unsigned int ui_Temp, ui_Temp1;
141  unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */
142  if (devpriv->b_OutputMemoryStatus) {
143  ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
144 
145  } /* if(devpriv->b_OutputMemoryStatus ) */
146  else {
147  ui_Temp = 0;
148  } /* if(devpriv->b_OutputMemoryStatus ) */
149  if (data[3] == 0) {
150  if (data[1] == 0) {
151  data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
152  outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP);
153  } /* if(data[1]==0) */
154  else {
155  if (data[1] == 1) {
156  switch (ui_NoOfChannel) {
157 
158  case 2:
159  data[0] =
160  (data[0] << (2 *
161  data[2])) | ui_Temp;
162  break;
163 
164  case 4:
165  data[0] =
166  (data[0] << (4 *
167  data[2])) | ui_Temp;
168  break;
169 
170  case 8:
171  data[0] =
172  (data[0] << (8 *
173  data[2])) | ui_Temp;
174  break;
175 
176  case 16:
177  data[0] =
178  (data[0] << (16 *
179  data[2])) | ui_Temp;
180  break;
181  case 31:
182  data[0] = data[0] | ui_Temp;
183  break;
184 
185  default:
186  comedi_error(dev, " chan spec wrong");
187  return -EINVAL; /* "sorry channel spec wrong " */
188 
189  } /* switch(ui_NoOfChannels) */
190 
191  outl(data[0],
192  devpriv->iobase + APCI2032_DIGITAL_OP);
193  } /* if(data[1]==1) */
194  else {
195  printk("\nSpecified channel not supported\n");
196  } /* else if(data[1]==1) */
197  } /* elseif(data[1]==0) */
198  } /* if(data[3]==0) */
199  else {
200  if (data[3] == 1) {
201  if (data[1] == 0) {
202  data[0] = ~data[0] & 0x1;
203  ui_Temp1 = 1;
204  ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
205  ui_Temp = ui_Temp | ui_Temp1;
206  data[0] =
207  (data[0] << ui_NoOfChannel) ^
208  0xffffffff;
209  data[0] = data[0] & ui_Temp;
210  outl(data[0],
211  devpriv->iobase + APCI2032_DIGITAL_OP);
212  } /* if(data[1]==0) */
213  else {
214  if (data[1] == 1) {
215  switch (ui_NoOfChannel) {
216 
217  case 2:
218  data[0] = ~data[0] & 0x3;
219  ui_Temp1 = 3;
220  ui_Temp1 =
221  ui_Temp1 << 2 * data[2];
222  ui_Temp = ui_Temp | ui_Temp1;
223  data[0] =
224  ((data[0] << (2 *
225  data
226  [2])) ^
227  0xffffffff) & ui_Temp;
228  break;
229 
230  case 4:
231  data[0] = ~data[0] & 0xf;
232  ui_Temp1 = 15;
233  ui_Temp1 =
234  ui_Temp1 << 4 * data[2];
235  ui_Temp = ui_Temp | ui_Temp1;
236  data[0] =
237  ((data[0] << (4 *
238  data
239  [2])) ^
240  0xffffffff) & ui_Temp;
241  break;
242 
243  case 8:
244  data[0] = ~data[0] & 0xff;
245  ui_Temp1 = 255;
246  ui_Temp1 =
247  ui_Temp1 << 8 * data[2];
248  ui_Temp = ui_Temp | ui_Temp1;
249  data[0] =
250  ((data[0] << (8 *
251  data
252  [2])) ^
253  0xffffffff) & ui_Temp;
254  break;
255 
256  case 16:
257  data[0] = ~data[0] & 0xffff;
258  ui_Temp1 = 65535;
259  ui_Temp1 =
260  ui_Temp1 << 16 *
261  data[2];
262  ui_Temp = ui_Temp | ui_Temp1;
263  data[0] =
264  ((data[0] << (16 *
265  data
266  [2])) ^
267  0xffffffff) & ui_Temp;
268  break;
269 
270  case 31:
271  break;
272  default:
273  comedi_error(dev,
274  " chan spec wrong");
275  return -EINVAL; /* "sorry channel spec wrong " */
276 
277  } /* switch(ui_NoOfChannels) */
278 
279  outl(data[0],
280  devpriv->iobase +
282  } /* if(data[1]==1) */
283  else {
284  printk("\nSpecified channel not supported\n");
285  } /* else if(data[1]==1) */
286  } /* elseif(data[1]==0) */
287  } /* if(data[3]==1); */
288  else {
289  printk("\nSpecified functionality does not exist\n");
290  return -EINVAL;
291  } /* if else data[3]==1) */
292  } /* if else data[3]==0) */
293  return insn->n;
294 }
295 
296 /*
297 +----------------------------------------------------------------------------+
298 | Function Name : int i_APCI2032_ReadDigitalOutput |
299 | (struct comedi_device *dev,struct comedi_subdevice *s, |
300 | struct comedi_insn *insn,unsigned int *data) |
301 +----------------------------------------------------------------------------+
302 | Task : Read value of the selected channel or port |
303 +----------------------------------------------------------------------------+
304 | Input Parameters : struct comedi_device *dev : Driver handle |
305 | unsigned int ui_NoOfChannels : No Of Channels To read |
306 | unsigned int *data : Data Pointer to read status |
307 +----------------------------------------------------------------------------+
308 | Output Parameters : -- |
309 +----------------------------------------------------------------------------+
310 | Return Value : TRUE : No error occur |
311 | : FALSE : Error occur. Return the error |
312 | |
313 +----------------------------------------------------------------------------+
314 */
315 
317  struct comedi_insn *insn, unsigned int *data)
318 {
319  unsigned int ui_Temp;
320  unsigned int ui_NoOfChannel;
321  ui_NoOfChannel = CR_CHAN(insn->chanspec);
322  ui_Temp = data[0];
323  *data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
324  if (ui_Temp == 0) {
325  *data = (*data >> ui_NoOfChannel) & 0x1;
326  } /* if (ui_Temp==0) */
327  else {
328  if (ui_Temp == 1) {
329  switch (ui_NoOfChannel) {
330 
331  case 2:
332  *data = (*data >> (2 * data[1])) & 3;
333  break;
334 
335  case 4:
336  *data = (*data >> (4 * data[1])) & 15;
337  break;
338 
339  case 8:
340  *data = (*data >> (8 * data[1])) & 255;
341  break;
342 
343  case 16:
344  *data = (*data >> (16 * data[1])) & 65535;
345  break;
346 
347  case 31:
348  break;
349 
350  default:
351  comedi_error(dev, " chan spec wrong");
352  return -EINVAL; /* "sorry channel spec wrong " */
353 
354  } /* switch(ui_NoOfChannels) */
355  } /* if (ui_Temp==1) */
356  else {
357  printk("\nSpecified channel not supported \n");
358  } /* elseif (ui_Temp==1) */
359  }
360  return insn->n;
361 }
362 
363 /*
364 +----------------------------------------------------------------------------+
365 | Function Name : int i_APCI2032_ConfigWatchdog(comedi_device
366 | *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)|
367 | |
368 +----------------------------------------------------------------------------+
369 | Task : Configures The Watchdog |
370 +----------------------------------------------------------------------------+
371 | Input Parameters : struct comedi_device *dev : Driver handle |
372 | struct comedi_subdevice *s, :pointer to subdevice structure
373 | struct comedi_insn *insn :pointer to insn structure |
374 | unsigned int *data : Data Pointer to read status |
375 +----------------------------------------------------------------------------+
376 | Output Parameters : -- |
377 +----------------------------------------------------------------------------+
378 | Return Value : TRUE : No error occur |
379 | : FALSE : Error occur. Return the error |
380 | |
381 +----------------------------------------------------------------------------+
382 */
384  struct comedi_insn *insn, unsigned int *data)
385 {
386  if (data[0] == 0) {
387  /* Disable the watchdog */
388  outl(0x0,
391  /* Loading the Reload value */
392  outl(data[1],
395  } else {
396  printk("\nThe input parameters are wrong\n");
397  return -EINVAL;
398  }
399 
400  return insn->n;
401 }
402 
403  /*
404  +----------------------------------------------------------------------------+
405  | Function Name : int i_APCI2032_StartStopWriteWatchdog |
406  | (struct comedi_device *dev,struct comedi_subdevice *s,
407  struct comedi_insn *insn,unsigned int *data); |
408  +----------------------------------------------------------------------------+
409  | Task : Start / Stop The Watchdog |
410  +----------------------------------------------------------------------------+
411  | Input Parameters : struct comedi_device *dev : Driver handle |
412  | struct comedi_subdevice *s, :pointer to subdevice structure
413  struct comedi_insn *insn :pointer to insn structure |
414  | unsigned int *data : Data Pointer to read status |
415  +----------------------------------------------------------------------------+
416  | Output Parameters : -- |
417  +----------------------------------------------------------------------------+
418  | Return Value : TRUE : No error occur |
419  | : FALSE : Error occur. Return the error |
420  | |
421  +----------------------------------------------------------------------------+
422  */
423 
425  struct comedi_insn *insn, unsigned int *data)
426 {
427  switch (data[0]) {
428  case 0: /* stop the watchdog */
429  outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); /* disable the watchdog */
430  break;
431  case 1: /* start the watchdog */
432  outl(0x0001,
435  break;
436  case 2: /* Software trigger */
437  outl(0x0201,
440  break;
441  default:
442  printk("\nSpecified functionality does not exist\n");
443  return -EINVAL;
444  }
445  return insn->n;
446 }
447 
448 /*
449 +----------------------------------------------------------------------------+
450 | Function Name : int i_APCI2032_ReadWatchdog |
451 | (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
452 | unsigned int *data); |
453 +----------------------------------------------------------------------------+
454 | Task : Read The Watchdog |
455 +----------------------------------------------------------------------------+
456 | Input Parameters : struct comedi_device *dev : Driver handle |
457 | struct comedi_subdevice *s, :pointer to subdevice structure
458 | struct comedi_insn *insn :pointer to insn structure |
459 | unsigned int *data : Data Pointer to read status |
460 +----------------------------------------------------------------------------+
461 | Output Parameters : -- |
462 +----------------------------------------------------------------------------+
463 | Return Value : TRUE : No error occur |
464 | : FALSE : Error occur. Return the error |
465 | |
466 +----------------------------------------------------------------------------+
467 */
468 
470  struct comedi_insn *insn, unsigned int *data)
471 {
472 
473  data[0] =
476  return insn->n;
477 }
478 
479 /*
480 +----------------------------------------------------------------------------+
481 | Function Name : void v_APCI2032_Interrupt |
482 | (int irq , void *d) |
483 +----------------------------------------------------------------------------+
484 | Task : Writes port value To the selected port |
485 +----------------------------------------------------------------------------+
486 | Input Parameters : int irq : irq number |
487 | void *d : void pointer |
488 +----------------------------------------------------------------------------+
489 | Output Parameters : -- |
490 +----------------------------------------------------------------------------+
491 | Return Value : TRUE : No error occur |
492 | : FALSE : Error occur. Return the error |
493 | |
494 +----------------------------------------------------------------------------+
495 */
496 void v_APCI2032_Interrupt(int irq, void *d)
497 {
498  struct comedi_device *dev = d;
499  unsigned int ui_DO;
500 
501  ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1; /* Check if VCC OR CC interrupt has occurred. */
502 
503  if (ui_DO == 0) {
504  printk("\nInterrupt from unKnown source\n");
505  } /* if(ui_DO==0) */
506  if (ui_DO) {
507  /* Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. */
508  ui_Type =
509  inl(devpriv->iobase +
511  outl(0x0,
512  devpriv->iobase + APCI2032_DIGITAL_OP +
514  if (ui_Type == 1) {
515  /* Sends signal to user space */
516  send_sig(SIGIO, devpriv->tsk_Current, 0);
517  } /* if (ui_Type==1) */
518  else {
519  if (ui_Type == 2) {
520  /* Sends signal to user space */
521  send_sig(SIGIO, devpriv->tsk_Current, 0);
522  } /* if (ui_Type==2) */
523  } /* else if (ui_Type==1) */
524  } /* if(ui_DO) */
525 
526  return;
527 
528 }
529 
530 /*
531 +----------------------------------------------------------------------------+
532 | Function Name : int i_APCI2032_ReadInterruptStatus |
533 | (struct comedi_device *dev,struct comedi_subdevice *s, |
534 | struct comedi_insn *insn,unsigned int *data) |
535 +----------------------------------------------------------------------------+
536 | Task :Reads the interrupt status register |
537 +----------------------------------------------------------------------------+
538 | Input Parameters : |
539 +----------------------------------------------------------------------------+
540 | Output Parameters : -- |
541 +----------------------------------------------------------------------------+
542 | Return Value : |
543 | |
544 +----------------------------------------------------------------------------+
545 */
546 
548  struct comedi_insn *insn, unsigned int *data)
549 {
550  *data = ui_Type;
551  return insn->n;
552 }
553 
554 /*
555 +----------------------------------------------------------------------------+
556 | Function Name : int i_APCI2032_Reset(struct comedi_device *dev) |
557 | |
558 +----------------------------------------------------------------------------+
559 | Task :Resets the registers of the card |
560 +----------------------------------------------------------------------------+
561 | Input Parameters : |
562 +----------------------------------------------------------------------------+
563 | Output Parameters : -- |
564 +----------------------------------------------------------------------------+
565 | Return Value : |
566 | |
567 +----------------------------------------------------------------------------+
568 */
569 
571 {
572  devpriv->b_DigitalOutputRegister = 0;
573  ui_Type = 0;
574  outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP); /* Resets the output channels */
575  outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT); /* Disables the interrupt. */
576  outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); /* disable the watchdog */
577  outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE); /* reload=0 */
578  return 0;
579 }