4 Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
10 Fax: +49(0)7223/9493-92
11 http://www.addi-data.com
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.
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.
21 +-----------------------------------------------------------------------+
22 | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier |
23 +-----------------------------------------------------------------------+
24 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
25 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
26 +-----------------------------------------------------------------------+
27 | Project : APCI-3120 | Compiler : GCC |
28 | Module name : hwdrv_apci3120.c| Version : 2.96 |
29 +-------------------------------+---------------------------------------+
30 | Project manager: Eric Stolz | Date : 02/12/2002 |
31 +-----------------------------------------------------------------------+
32 | Description :APCI3120 Module. Hardware abstraction Layer for APCI3120|
33 +-----------------------------------------------------------------------+
35 +-----------------------------------------------------------------------+
36 | Date | Author | Description of updates |
37 +----------+-----------+------------------------------------------------+
40 +----------+-----------+------------------------------------------------+
43 #define APCI3120_START 1
44 #define APCI3120_STOP 0
46 #define APCI3120_RD_FIFO 0x00
48 /* software trigger dummy register */
49 #define APCI3120_START_CONVERSION 0x02
52 #define APCI3120_QUARTZ_A 70
53 #define APCI3120_QUARTZ_B 50
54 #define APCI3120_TIMER 1
55 #define APCI3120_WATCHDOG 2
56 #define APCI3120_TIMER_DISABLE 0
57 #define APCI3120_TIMER_ENABLE 1
59 #define APCI3120_COUNTER 3
61 static void apci3120_addon_write(struct comedi_device *dev,
62 unsigned int val, unsigned int reg)
64 struct apci3120_private *devpriv = dev->private;
66 /* 16-bit interface for AMCC add-on registers */
68 outw(reg, devpriv->addon + APCI3120_ADDON_ADDR_REG);
69 outw(val & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
71 outw(reg + 2, devpriv->addon + APCI3120_ADDON_ADDR_REG);
72 outw((val >> 16) & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
75 static int apci3120_reset(struct comedi_device *dev)
77 struct apci3120_private *devpriv = dev->private;
79 /* variables used in timer subdevice */
80 devpriv->b_Timer2Mode = 0;
81 devpriv->b_Timer2Interrupt = 0;
83 /* Disable all interrupts, watchdog for the anolog output */
85 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
87 /* disable all counters, ext trigger, and reset scan */
89 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
91 inw(dev->iobase + APCI3120_STATUS_REG);
96 static int apci3120_cancel(struct comedi_device *dev,
97 struct comedi_subdevice *s)
99 struct apci3120_private *devpriv = dev->private;
101 /* Add-On - disable DMA */
102 outw(0, devpriv->addon + 4);
104 /* Add-On - disable bus master */
105 apci3120_addon_write(dev, 0, AMCC_OP_REG_AGCSTS);
107 /* AMCC - disable bus master */
108 outl(0, devpriv->amcc + AMCC_OP_REG_MCSR);
110 /* disable all counters, ext trigger, and reset scan */
112 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
114 /* DISABLE_ALL_INTERRUPT */
116 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
118 inw(dev->iobase + APCI3120_STATUS_REG);
119 devpriv->ui_DmaActualBuffer = 0;
124 static int apci3120_ai_cmdtest(struct comedi_device *dev,
125 struct comedi_subdevice *s,
126 struct comedi_cmd *cmd)
130 /* Step 1 : check if triggers are trivially valid */
132 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
133 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
134 TRIG_TIMER | TRIG_FOLLOW);
135 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
136 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
137 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
142 /* Step 2a : make sure trigger sources are unique */
144 err |= cfc_check_trigger_is_unique(cmd->start_src);
145 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
146 err |= cfc_check_trigger_is_unique(cmd->stop_src);
148 /* Step 2b : and mutually compatible */
153 /* Step 3: check if arguments are trivially valid */
155 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
157 if (cmd->scan_begin_src == TRIG_TIMER) /* Test Delay timing */
158 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 100000);
160 if (cmd->scan_begin_src == TRIG_TIMER) {
161 if (cmd->convert_arg)
162 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
165 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
168 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
169 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
171 if (cmd->stop_src == TRIG_COUNT)
172 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
174 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
179 /* step 4: fix up any arguments */
181 if (cmd->scan_begin_src == TRIG_TIMER &&
182 cmd->scan_begin_arg < cmd->convert_arg * cmd->scan_end_arg) {
183 cmd->scan_begin_arg = cmd->convert_arg * cmd->scan_end_arg;
193 static void apci3120_init_dma(struct comedi_device *dev,
194 struct apci3120_dmabuf *dmabuf)
196 struct apci3120_private *devpriv = dev->private;
198 /* AMCC - enable transfer count and reset A2P FIFO */
199 outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
200 devpriv->amcc + AMCC_OP_REG_AGCSTS);
202 /* Add-On - enable transfer count and reset A2P FIFO */
203 apci3120_addon_write(dev, AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
206 /* AMCC - enable transfers and reset A2P flags */
207 outl(RESET_A2P_FLAGS | EN_A2P_TRANSFERS,
208 devpriv->amcc + AMCC_OP_REG_MCSR);
210 /* Add-On - DMA start address */
211 apci3120_addon_write(dev, dmabuf->hw, AMCC_OP_REG_AMWAR);
213 /* Add-On - Number of acquisitions */
214 apci3120_addon_write(dev, dmabuf->use_size, AMCC_OP_REG_AMWTC);
216 /* AMCC - enable write complete (DMA) and set FIFO advance */
217 outl(APCI3120_FIFO_ADVANCE_ON_BYTE_2 | AINT_WRITE_COMPL,
218 devpriv->amcc + AMCC_OP_REG_INTCSR);
220 /* Add-On - enable DMA */
221 outw(APCI3120_ADDON_CTRL_AMWEN_ENA | APCI3120_ADDON_CTRL_A2P_FIFO_ENA,
222 devpriv->addon + APCI3120_ADDON_CTRL_REG);
225 static void apci3120_setup_dma(struct comedi_device *dev,
226 struct comedi_subdevice *s)
228 struct apci3120_private *devpriv = dev->private;
229 struct comedi_cmd *cmd = &s->async->cmd;
230 struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
231 struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
232 unsigned int dmalen0 = dmabuf0->size;
233 unsigned int dmalen1 = dmabuf1->size;
234 unsigned int scan_bytes;
236 scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg);
238 if (cmd->stop_src == TRIG_COUNT) {
240 * Must we fill full first buffer? And must we fill
241 * full second buffer when first is once filled?
243 if (dmalen0 > (cmd->stop_arg * scan_bytes))
244 dmalen0 = cmd->stop_arg * scan_bytes;
245 else if (dmalen1 > (cmd->stop_arg * scan_bytes - dmalen0))
246 dmalen1 = cmd->stop_arg * scan_bytes - dmalen0;
249 if (cmd->flags & CMDF_WAKE_EOS) {
250 /* don't we want wake up every scan? */
251 if (dmalen0 > scan_bytes) {
252 dmalen0 = scan_bytes;
253 if (cmd->scan_end_arg & 1)
256 if (dmalen1 > scan_bytes) {
257 dmalen1 = scan_bytes;
258 if (cmd->scan_end_arg & 1)
264 /* isn't output buff smaller that our DMA buff? */
265 if (dmalen0 > s->async->prealloc_bufsz)
266 dmalen0 = s->async->prealloc_bufsz;
267 if (dmalen1 > s->async->prealloc_bufsz)
268 dmalen1 = s->async->prealloc_bufsz;
270 dmabuf0->use_size = dmalen0;
271 dmabuf1->use_size = dmalen1;
273 apci3120_init_dma(dev, dmabuf0);
276 static int apci3120_ai_cmd(struct comedi_device *dev,
277 struct comedi_subdevice *s)
279 struct apci3120_private *devpriv = dev->private;
280 struct comedi_cmd *cmd = &s->async->cmd;
281 unsigned int divisor;
283 /* set default mode bits */
284 devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
285 APCI3120_MODE_TIMER2_AS_TIMER;
287 /* AMCC- Clear write complete interrupt (DMA) */
288 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
290 devpriv->ui_DmaActualBuffer = 0;
292 /* load chanlist for command scan */
293 apci3120_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist);
295 if (cmd->start_src == TRIG_EXT)
296 apci3120_exttrig_enable(dev, true);
298 if (cmd->scan_begin_src == TRIG_TIMER) {
300 * Timer 1 is used in MODE2 (rate generator) to set the
301 * start time for each scan.
303 divisor = apci3120_ns_to_timer(dev, 1, cmd->scan_begin_arg,
305 apci3120_timer_set_mode(dev, 1, APCI3120_TIMER_MODE2);
306 apci3120_timer_write(dev, 1, divisor);
310 * Timer 0 is used in MODE2 (rate generator) to set the conversion
311 * time for each acquisition.
313 divisor = apci3120_ns_to_timer(dev, 0, cmd->convert_arg, cmd->flags);
314 apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE2);
315 apci3120_timer_write(dev, 0, divisor);
317 if (devpriv->us_UseDma) {
318 apci3120_setup_dma(dev, s);
320 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
322 if (cmd->stop_src == TRIG_COUNT) {
324 * Timer 2 is used in MODE0 (hardware retriggerable
325 * one-shot) to count the number of scans.
327 * NOTE: not sure about the -2 value
329 apci3120_timer_set_mode(dev, 2, APCI3120_TIMER_MODE0);
330 apci3120_timer_write(dev, 2, cmd->stop_arg - 2);
332 apci3120_clr_timer2_interrupt(dev);
334 apci3120_timer_enable(dev, 2, true);
336 /* configure Timer 2 For counting EOS */
337 devpriv->mode |= APCI3120_MODE_TIMER2_AS_COUNTER |
338 APCI3120_MODE_TIMER2_CLK_EOS |
339 APCI3120_MODE_TIMER2_IRQ_ENA;
341 devpriv->b_Timer2Mode = APCI3120_COUNTER;
342 devpriv->b_Timer2Interrupt = 1;
346 /* set mode to enable acquisition */
347 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
349 if (cmd->scan_begin_src == TRIG_TIMER)
350 apci3120_timer_enable(dev, 1, true);
351 apci3120_timer_enable(dev, 0, true);
357 * This is a handler for the DMA interrupt.
358 * This function copies the data to Comedi Buffer.
359 * For continuous DMA it reinitializes the DMA operation.
360 * For single mode DMA it stop the acquisition.
362 static void apci3120_interrupt_dma(int irq, void *d)
364 struct comedi_device *dev = d;
365 struct apci3120_private *devpriv = dev->private;
366 struct comedi_subdevice *s = dev->read_subdev;
367 struct comedi_cmd *cmd = &s->async->cmd;
368 struct apci3120_dmabuf *dmabuf;
369 unsigned int samplesinbuf;
371 dmabuf = &devpriv->dmabuf[devpriv->ui_DmaActualBuffer];
373 samplesinbuf = dmabuf->use_size - inl(devpriv->amcc + AMCC_OP_REG_MWTC);
375 if (samplesinbuf < dmabuf->use_size)
376 dev_err(dev->class_dev, "Interrupted DMA transfer!\n");
377 if (samplesinbuf & 1) {
378 dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n");
379 apci3120_cancel(dev, s);
382 samplesinbuf = samplesinbuf >> 1; /* number of received samples */
384 if (devpriv->b_DmaDoubleBuffer) {
385 struct apci3120_dmabuf *next_dmabuf;
387 next_dmabuf = &devpriv->dmabuf[1 - devpriv->ui_DmaActualBuffer];
389 /* start DMA on next buffer */
390 apci3120_init_dma(dev, next_dmabuf);
394 comedi_buf_write_samples(s, dmabuf->virt, samplesinbuf);
396 if (!(cmd->flags & CMDF_WAKE_EOS))
397 s->async->events |= COMEDI_CB_EOS;
399 if (cmd->stop_src == TRIG_COUNT &&
400 s->async->scans_done >= cmd->stop_arg) {
401 s->async->events |= COMEDI_CB_EOA;
405 if (devpriv->b_DmaDoubleBuffer) {
406 /* switch dma buffers for next interrupt */
407 devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
409 /* restart DMA if is not using double buffering */
410 apci3120_init_dma(dev, dmabuf);
414 static irqreturn_t apci3120_interrupt(int irq, void *d)
416 struct comedi_device *dev = d;
417 struct apci3120_private *devpriv = dev->private;
418 struct comedi_subdevice *s = dev->read_subdev;
419 struct comedi_cmd *cmd = &s->async->cmd;
421 unsigned int int_amcc;
423 status = inw(dev->iobase + APCI3120_STATUS_REG);
424 int_amcc = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
426 if (!(status & APCI3120_STATUS_INT_MASK) &&
427 !(int_amcc & ANY_S593X_INT)) {
428 dev_err(dev->class_dev, "IRQ from unknown source\n");
432 outl(int_amcc | AINT_INT_MASK, devpriv->amcc + AMCC_OP_REG_INTCSR);
434 if (devpriv->ctrl & APCI3120_CTRL_EXT_TRIG)
435 apci3120_exttrig_enable(dev, false);
437 apci3120_clr_timer2_interrupt(dev);
439 if (int_amcc & MASTER_ABORT_INT)
440 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
441 if (int_amcc & TARGET_ABORT_INT)
442 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
444 if ((status & APCI3120_STATUS_EOC_INT) == 0 &&
445 (devpriv->mode & APCI3120_MODE_EOC_IRQ_ENA)) {
446 /* nothing to do... EOC mode is not currently used */
449 if ((status & APCI3120_STATUS_EOS_INT) &&
450 (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) {
454 for (i = 0; i < cmd->chanlist_len; i++) {
455 val = inw(dev->iobase + 0);
456 comedi_buf_write_samples(s, &val, 1);
459 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
460 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
463 if (status & APCI3120_STATUS_TIMER2_INT) {
464 switch (devpriv->b_Timer2Mode) {
465 case APCI3120_COUNTER:
466 devpriv->mode &= ~APCI3120_MODE_EOS_IRQ_ENA;
467 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
469 s->async->events |= COMEDI_CB_EOA;
474 /* Send a signal to from kernel to user space */
475 send_sig(SIGIO, devpriv->tsk_Current, 0);
478 case APCI3120_WATCHDOG:
480 /* Send a signal to from kernel to user space */
481 send_sig(SIGIO, devpriv->tsk_Current, 0);
485 /* disable Timer Interrupt */
486 devpriv->mode &= ~APCI3120_MODE_TIMER2_IRQ_ENA;
487 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
490 apci3120_clr_timer2_interrupt(dev);
493 if (status & APCI3120_STATUS_AMCC_INT) {
494 /* AMCC- Clear write complete interrupt (DMA) */
495 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
497 apci3120_clr_timer2_interrupt(dev);
499 /* do some data transfer */
500 apci3120_interrupt_dma(irq, d);
502 comedi_handle_events(dev, s);
510 * data[0] = TIMER configure as timer
511 * = WATCHDOG configure as watchdog
512 * data[1] = Timer constant
513 * data[2] = Timer2 interrupt (1)enable or(0) disable
515 static int apci3120_config_insn_timer(struct comedi_device *dev,
516 struct comedi_subdevice *s,
517 struct comedi_insn *insn,
520 struct apci3120_private *devpriv = dev->private;
521 unsigned int divisor;
524 dev_err(dev->class_dev, "No timer constant!\n");
526 devpriv->b_Timer2Interrupt = (unsigned char) data[2]; /* save info whether to enable or disable interrupt */
528 divisor = apci3120_ns_to_timer(dev, 2, data[1], CMDF_ROUND_DOWN);
530 apci3120_timer_enable(dev, 2, false);
532 /* disable timer 2 interrupt and reset operation mode (timer) */
533 devpriv->mode &= ~APCI3120_MODE_TIMER2_IRQ_ENA &
534 ~APCI3120_MODE_TIMER2_AS_MASK;
536 /* Disable Eoc and Eos Interrupts */
537 devpriv->mode &= ~APCI3120_MODE_EOC_IRQ_ENA &
538 ~APCI3120_MODE_EOS_IRQ_ENA;
539 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
541 if (data[0] == APCI3120_TIMER) { /* initialize timer */
542 /* Set the Timer 2 in mode 2(Timer) */
543 apci3120_timer_set_mode(dev, 2, APCI3120_TIMER_MODE2);
545 /* Set timer 2 delay */
546 apci3120_timer_write(dev, 2, divisor);
548 /* timer2 in Timer mode enabled */
549 devpriv->b_Timer2Mode = APCI3120_TIMER;
550 } else { /* Initialize Watch dog */
551 /* Set the Timer 2 in mode 5(Watchdog) */
552 apci3120_timer_set_mode(dev, 2, APCI3120_TIMER_MODE5);
554 /* Set timer 2 delay */
555 apci3120_timer_write(dev, 2, divisor);
557 /* watchdog enabled */
558 devpriv->b_Timer2Mode = APCI3120_WATCHDOG;
567 * To start and stop the timer
569 * data[0] = 1 (start)
571 * = 2 (write new value)
572 * data[1] = new value
574 * devpriv->b_Timer2Mode = 0 DISABLE
578 static int apci3120_write_insn_timer(struct comedi_device *dev,
579 struct comedi_subdevice *s,
580 struct comedi_insn *insn,
583 struct apci3120_private *devpriv = dev->private;
584 unsigned int divisor;
586 if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
587 && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
588 dev_err(dev->class_dev, "timer2 not configured\n");
592 if (data[0] == 2) { /* write new value */
593 if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
594 dev_err(dev->class_dev,
595 "timer2 not configured in TIMER MODE\n");
602 apci3120_clr_timer2_interrupt(dev);
604 if (devpriv->b_Timer2Mode == APCI3120_TIMER) { /* start timer */
606 devpriv->mode &= 0x0b;
607 devpriv->mode |= APCI3120_MODE_TIMER2_AS_TIMER;
608 } else { /* start watch dog */
609 /* Enable WatchDog */
610 devpriv->mode &= 0x0b;
611 devpriv->mode |= APCI3120_MODE_TIMER2_AS_WDOG;
614 /* enable disable interrupt */
615 if (devpriv->b_Timer2Interrupt) {
616 devpriv->mode |= APCI3120_MODE_TIMER2_IRQ_ENA;
618 /* save the task structure to pass info to user */
619 devpriv->tsk_Current = current;
621 devpriv->mode &= ~APCI3120_MODE_TIMER2_IRQ_ENA;
623 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
626 if (devpriv->b_Timer2Mode == APCI3120_TIMER)
627 apci3120_timer_enable(dev, 2, true);
631 /* disable timer 2 interrupt and reset operation mode (timer) */
632 devpriv->mode &= ~APCI3120_MODE_TIMER2_IRQ_ENA &
633 ~APCI3120_MODE_TIMER2_AS_MASK;
634 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
636 apci3120_timer_enable(dev, 2, false);
638 apci3120_clr_timer2_interrupt(dev);
641 case 2: /* write new value to Timer */
642 if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
643 dev_err(dev->class_dev,
644 "timer2 not configured in TIMER MODE\n");
648 divisor = apci3120_ns_to_timer(dev, 2, data[1],
651 /* Set timer 2 delay */
652 apci3120_timer_write(dev, 2, divisor);
655 return -EINVAL; /* Not a valid input */
662 * Read the Timer value
664 * for Timer: data[0]= Timer constant
666 * for watchdog: data[0] = 0 (still running)
669 static int apci3120_read_insn_timer(struct comedi_device *dev,
670 struct comedi_subdevice *s,
671 struct comedi_insn *insn,
674 struct apci3120_private *devpriv = dev->private;
677 if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
678 && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
679 dev_err(dev->class_dev, "timer2 not configured\n");
681 if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
682 data[0] = apci3120_timer_read(dev, 2);
684 /* Read watch dog status */
685 status = inw(dev->iobase + APCI3120_STATUS_REG);
686 if (status & APCI3120_STATUS_TIMER2_INT) {
687 apci3120_clr_timer2_interrupt(dev);