3 * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
8 * Tel: +19(0)7223/9493-0
9 * Fax: +49(0)7223/9493-92
10 * http://www.addi-data.com
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
18 * This program is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
24 #include <linux/module.h>
25 #include <linux/interrupt.h>
27 #include "../comedi_pci.h"
28 #include "amcc_s5933.h"
31 * PCI BAR 0 register map (devpriv->amcc)
32 * see amcc_s5933.h for register and bit defines
34 #define APCI3120_FIFO_ADVANCE_ON_BYTE_2 BIT(29)
37 * PCI BAR 1 register map (dev->iobase)
39 #define APCI3120_AI_FIFO_REG 0x00
40 #define APCI3120_CTRL_REG 0x00
41 #define APCI3120_CTRL_EXT_TRIG BIT(15)
42 #define APCI3120_CTRL_GATE(x) BIT(12 + (x))
43 #define APCI3120_CTRL_PR(x) (((x) & 0xf) << 8)
44 #define APCI3120_CTRL_PA(x) (((x) & 0xf) << 0)
45 #define APCI3120_AI_SOFTTRIG_REG 0x02
46 #define APCI3120_STATUS_REG 0x02
47 #define APCI3120_STATUS_EOC_INT BIT(15)
48 #define APCI3120_STATUS_AMCC_INT BIT(14)
49 #define APCI3120_STATUS_EOS_INT BIT(13)
50 #define APCI3120_STATUS_TIMER2_INT BIT(12)
51 #define APCI3120_STATUS_INT_MASK (0xf << 12)
52 #define APCI3120_STATUS_TO_DI_BITS(x) (((x) >> 8) & 0xf)
53 #define APCI3120_STATUS_TO_VERSION(x) (((x) >> 4) & 0xf)
54 #define APCI3120_STATUS_FIFO_FULL BIT(2)
55 #define APCI3120_STATUS_FIFO_EMPTY BIT(1)
56 #define APCI3120_STATUS_DA_READY BIT(0)
57 #define APCI3120_TIMER_REG 0x04
58 #define APCI3120_CHANLIST_REG 0x06
59 #define APCI3120_CHANLIST_INDEX(x) (((x) & 0xf) << 8)
60 #define APCI3120_CHANLIST_UNIPOLAR BIT(7)
61 #define APCI3120_CHANLIST_GAIN(x) (((x) & 0x3) << 4)
62 #define APCI3120_CHANLIST_MUX(x) (((x) & 0xf) << 0)
63 #define APCI3120_AO_REG(x) (0x08 + (((x) / 4) * 2))
64 #define APCI3120_AO_MUX(x) (((x) & 0x3) << 14)
65 #define APCI3120_AO_DATA(x) ((x) << 0)
66 #define APCI3120_TIMER_MODE_REG 0x0c
67 #define APCI3120_TIMER_MODE(_t, _m) ((_m) << ((_t) * 2))
68 #define APCI3120_TIMER_MODE0 0 /* I8254_MODE0 */
69 #define APCI3120_TIMER_MODE2 1 /* I8254_MODE2 */
70 #define APCI3120_TIMER_MODE4 2 /* I8254_MODE4 */
71 #define APCI3120_TIMER_MODE5 3 /* I8254_MODE5 */
72 #define APCI3120_TIMER_MODE_MASK(_t) (3 << ((_t) * 2))
73 #define APCI3120_CTR0_REG 0x0d
74 #define APCI3120_CTR0_DO_BITS(x) ((x) << 4)
75 #define APCI3120_CTR0_TIMER_SEL(x) ((x) << 0)
76 #define APCI3120_MODE_REG 0x0e
77 #define APCI3120_MODE_TIMER2_CLK(x) (((x) & 0x3) << 6)
78 #define APCI3120_MODE_TIMER2_CLK_OSC APCI3120_MODE_TIMER2_CLK(0)
79 #define APCI3120_MODE_TIMER2_CLK_OUT1 APCI3120_MODE_TIMER2_CLK(1)
80 #define APCI3120_MODE_TIMER2_CLK_EOC APCI3120_MODE_TIMER2_CLK(2)
81 #define APCI3120_MODE_TIMER2_CLK_EOS APCI3120_MODE_TIMER2_CLK(3)
82 #define APCI3120_MODE_TIMER2_CLK_MASK APCI3120_MODE_TIMER2_CLK(3)
83 #define APCI3120_MODE_TIMER2_AS(x) (((x) & 0x3) << 4)
84 #define APCI3120_MODE_TIMER2_AS_TIMER APCI3120_MODE_TIMER2_AS(0)
85 #define APCI3120_MODE_TIMER2_AS_COUNTER APCI3120_MODE_TIMER2_AS(1)
86 #define APCI3120_MODE_TIMER2_AS_WDOG APCI3120_MODE_TIMER2_AS(2)
87 #define APCI3120_MODE_TIMER2_AS_MASK APCI3120_MODE_TIMER2_AS(3)
88 #define APCI3120_MODE_SCAN_ENA BIT(3)
89 #define APCI3120_MODE_TIMER2_IRQ_ENA BIT(2)
90 #define APCI3120_MODE_EOS_IRQ_ENA BIT(1)
91 #define APCI3120_MODE_EOC_IRQ_ENA BIT(0)
94 * PCI BAR 2 register map (devpriv->addon)
96 #define APCI3120_ADDON_ADDR_REG 0x00
97 #define APCI3120_ADDON_DATA_REG 0x02
98 #define APCI3120_ADDON_CTRL_REG 0x04
99 #define APCI3120_ADDON_CTRL_AMWEN_ENA BIT(1)
100 #define APCI3120_ADDON_CTRL_A2P_FIFO_ENA BIT(0)
105 #define APCI3120_REVA 0xa
106 #define APCI3120_REVB 0xb
107 #define APCI3120_REVA_OSC_BASE 70 /* 70ns = 14.29MHz */
108 #define APCI3120_REVB_OSC_BASE 50 /* 50ns = 20MHz */
110 static const struct comedi_lrange apci3120_ai_range = {
123 enum apci3120_boardid {
128 struct apci3120_board {
130 unsigned int ai_is_16bit:1;
131 unsigned int has_ao:1;
134 static const struct apci3120_board apci3120_boardtypes[] = {
145 struct apci3120_dmabuf {
146 unsigned short *virt;
149 unsigned int use_size;
152 struct apci3120_private {
155 unsigned int osc_base;
156 unsigned int use_dma:1;
157 unsigned int use_double_buffer:1;
158 unsigned int cur_dmabuf:1;
159 struct apci3120_dmabuf dmabuf[2];
160 unsigned char do_bits;
161 unsigned char timer_mode;
166 static void apci3120_addon_write(struct comedi_device *dev,
167 unsigned int val, unsigned int reg)
169 struct apci3120_private *devpriv = dev->private;
171 /* 16-bit interface for AMCC add-on registers */
173 outw(reg, devpriv->addon + APCI3120_ADDON_ADDR_REG);
174 outw(val & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
176 outw(reg + 2, devpriv->addon + APCI3120_ADDON_ADDR_REG);
177 outw((val >> 16) & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
180 static void apci3120_init_dma(struct comedi_device *dev,
181 struct apci3120_dmabuf *dmabuf)
183 struct apci3120_private *devpriv = dev->private;
185 /* AMCC - enable transfer count and reset A2P FIFO */
186 outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
187 devpriv->amcc + AMCC_OP_REG_AGCSTS);
189 /* Add-On - enable transfer count and reset A2P FIFO */
190 apci3120_addon_write(dev, AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
193 /* AMCC - enable transfers and reset A2P flags */
194 outl(RESET_A2P_FLAGS | EN_A2P_TRANSFERS,
195 devpriv->amcc + AMCC_OP_REG_MCSR);
197 /* Add-On - DMA start address */
198 apci3120_addon_write(dev, dmabuf->hw, AMCC_OP_REG_AMWAR);
200 /* Add-On - Number of acquisitions */
201 apci3120_addon_write(dev, dmabuf->use_size, AMCC_OP_REG_AMWTC);
203 /* AMCC - enable write complete (DMA) and set FIFO advance */
204 outl(APCI3120_FIFO_ADVANCE_ON_BYTE_2 | AINT_WRITE_COMPL,
205 devpriv->amcc + AMCC_OP_REG_INTCSR);
207 /* Add-On - enable DMA */
208 outw(APCI3120_ADDON_CTRL_AMWEN_ENA | APCI3120_ADDON_CTRL_A2P_FIFO_ENA,
209 devpriv->addon + APCI3120_ADDON_CTRL_REG);
212 static void apci3120_setup_dma(struct comedi_device *dev,
213 struct comedi_subdevice *s)
215 struct apci3120_private *devpriv = dev->private;
216 struct comedi_cmd *cmd = &s->async->cmd;
217 struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
218 struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
219 unsigned int dmalen0 = dmabuf0->size;
220 unsigned int dmalen1 = dmabuf1->size;
221 unsigned int scan_bytes;
223 scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg);
225 if (cmd->stop_src == TRIG_COUNT) {
227 * Must we fill full first buffer? And must we fill
228 * full second buffer when first is once filled?
230 if (dmalen0 > (cmd->stop_arg * scan_bytes))
231 dmalen0 = cmd->stop_arg * scan_bytes;
232 else if (dmalen1 > (cmd->stop_arg * scan_bytes - dmalen0))
233 dmalen1 = cmd->stop_arg * scan_bytes - dmalen0;
236 if (cmd->flags & CMDF_WAKE_EOS) {
237 /* don't we want wake up every scan? */
238 if (dmalen0 > scan_bytes) {
239 dmalen0 = scan_bytes;
240 if (cmd->scan_end_arg & 1)
243 if (dmalen1 > scan_bytes) {
244 dmalen1 = scan_bytes;
245 if (cmd->scan_end_arg & 1)
251 /* isn't output buff smaller that our DMA buff? */
252 if (dmalen0 > s->async->prealloc_bufsz)
253 dmalen0 = s->async->prealloc_bufsz;
254 if (dmalen1 > s->async->prealloc_bufsz)
255 dmalen1 = s->async->prealloc_bufsz;
257 dmabuf0->use_size = dmalen0;
258 dmabuf1->use_size = dmalen1;
260 apci3120_init_dma(dev, dmabuf0);
264 * There are three timers on the board. They all use the same base
265 * clock with a fixed prescaler for each timer. The base clock used
266 * depends on the board version and type.
268 * APCI-3120 Rev A boards OSC = 14.29MHz base clock (~70ns)
269 * APCI-3120 Rev B boards OSC = 20MHz base clock (50ns)
270 * APCI-3001 boards OSC = 20MHz base clock (50ns)
272 * The prescalers for each timer are:
273 * Timer 0 CLK = OSC/10
274 * Timer 1 CLK = OSC/1000
275 * Timer 2 CLK = OSC/1000
277 static unsigned int apci3120_ns_to_timer(struct comedi_device *dev,
282 struct apci3120_private *devpriv = dev->private;
283 unsigned int prescale = (timer == 0) ? 10 : 1000;
284 unsigned int timer_base = devpriv->osc_base * prescale;
285 unsigned int divisor;
287 switch (flags & CMDF_ROUND_MASK) {
289 divisor = DIV_ROUND_UP(ns, timer_base);
291 case CMDF_ROUND_DOWN:
292 divisor = ns / timer_base;
294 case CMDF_ROUND_NEAREST:
296 divisor = DIV_ROUND_CLOSEST(ns, timer_base);
301 /* timer 2 is 24-bits */
302 if (divisor > 0x00ffffff)
303 divisor = 0x00ffffff;
305 /* timers 0 and 1 are 16-bits */
306 if (divisor > 0xffff)
309 /* the timers require a minimum divisor of 2 */
316 static void apci3120_clr_timer2_interrupt(struct comedi_device *dev)
318 /* a dummy read of APCI3120_CTR0_REG clears the timer 2 interrupt */
319 inb(dev->iobase + APCI3120_CTR0_REG);
322 static void apci3120_timer_write(struct comedi_device *dev,
323 unsigned int timer, unsigned int val)
325 struct apci3120_private *devpriv = dev->private;
327 /* write 16-bit value to timer (lower 16-bits of timer 2) */
328 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
329 APCI3120_CTR0_TIMER_SEL(timer),
330 dev->iobase + APCI3120_CTR0_REG);
331 outw(val & 0xffff, dev->iobase + APCI3120_TIMER_REG);
334 /* write upper 16-bits to timer 2 */
335 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
336 APCI3120_CTR0_TIMER_SEL(timer + 1),
337 dev->iobase + APCI3120_CTR0_REG);
338 outw((val >> 16) & 0xffff, dev->iobase + APCI3120_TIMER_REG);
342 static unsigned int apci3120_timer_read(struct comedi_device *dev,
345 struct apci3120_private *devpriv = dev->private;
348 /* read 16-bit value from timer (lower 16-bits of timer 2) */
349 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
350 APCI3120_CTR0_TIMER_SEL(timer),
351 dev->iobase + APCI3120_CTR0_REG);
352 val = inw(dev->iobase + APCI3120_TIMER_REG);
355 /* read upper 16-bits from timer 2 */
356 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
357 APCI3120_CTR0_TIMER_SEL(timer + 1),
358 dev->iobase + APCI3120_CTR0_REG);
359 val |= (inw(dev->iobase + APCI3120_TIMER_REG) << 16);
365 static void apci3120_timer_set_mode(struct comedi_device *dev,
366 unsigned int timer, unsigned int mode)
368 struct apci3120_private *devpriv = dev->private;
370 devpriv->timer_mode &= ~APCI3120_TIMER_MODE_MASK(timer);
371 devpriv->timer_mode |= APCI3120_TIMER_MODE(timer, mode);
372 outb(devpriv->timer_mode, dev->iobase + APCI3120_TIMER_MODE_REG);
375 static void apci3120_timer_enable(struct comedi_device *dev,
376 unsigned int timer, bool enable)
378 struct apci3120_private *devpriv = dev->private;
381 devpriv->ctrl |= APCI3120_CTRL_GATE(timer);
383 devpriv->ctrl &= ~APCI3120_CTRL_GATE(timer);
384 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
387 static void apci3120_exttrig_enable(struct comedi_device *dev, bool enable)
389 struct apci3120_private *devpriv = dev->private;
392 devpriv->ctrl |= APCI3120_CTRL_EXT_TRIG;
394 devpriv->ctrl &= ~APCI3120_CTRL_EXT_TRIG;
395 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
398 static void apci3120_set_chanlist(struct comedi_device *dev,
399 struct comedi_subdevice *s,
400 int n_chan, unsigned int *chanlist)
402 struct apci3120_private *devpriv = dev->private;
405 /* set chanlist for scan */
406 for (i = 0; i < n_chan; i++) {
407 unsigned int chan = CR_CHAN(chanlist[i]);
408 unsigned int range = CR_RANGE(chanlist[i]);
411 val = APCI3120_CHANLIST_MUX(chan) |
412 APCI3120_CHANLIST_GAIN(range) |
413 APCI3120_CHANLIST_INDEX(i);
415 if (comedi_range_is_unipolar(s, range))
416 val |= APCI3120_CHANLIST_UNIPOLAR;
418 outw(val, dev->iobase + APCI3120_CHANLIST_REG);
421 /* a dummy read of APCI3120_TIMER_MODE_REG resets the ai FIFO */
422 inw(dev->iobase + APCI3120_TIMER_MODE_REG);
424 /* set scan length (PR) and scan start (PA) */
425 devpriv->ctrl = APCI3120_CTRL_PR(n_chan - 1) | APCI3120_CTRL_PA(0);
426 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
428 /* enable chanlist scanning if necessary */
430 devpriv->mode |= APCI3120_MODE_SCAN_ENA;
433 static void apci3120_interrupt_dma(struct comedi_device *dev,
434 struct comedi_subdevice *s)
436 struct apci3120_private *devpriv = dev->private;
437 struct comedi_async *async = s->async;
438 struct comedi_cmd *cmd = &async->cmd;
439 struct apci3120_dmabuf *dmabuf;
441 unsigned int nsamples;
443 dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
445 nbytes = dmabuf->use_size - inl(devpriv->amcc + AMCC_OP_REG_MWTC);
447 if (nbytes < dmabuf->use_size)
448 dev_err(dev->class_dev, "Interrupted DMA transfer!\n");
450 dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n");
451 async->events |= COMEDI_CB_ERROR;
455 nsamples = comedi_bytes_to_samples(s, nbytes);
457 comedi_buf_write_samples(s, dmabuf->virt, nsamples);
459 if (!(cmd->flags & CMDF_WAKE_EOS))
460 async->events |= COMEDI_CB_EOS;
463 if ((async->events & COMEDI_CB_CANCEL_MASK) ||
464 (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg))
467 if (devpriv->use_double_buffer) {
468 /* switch DMA buffers for next interrupt */
469 devpriv->cur_dmabuf = !devpriv->cur_dmabuf;
470 dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
471 apci3120_init_dma(dev, dmabuf);
473 /* restart DMA if not using double buffering */
474 apci3120_init_dma(dev, dmabuf);
478 static irqreturn_t apci3120_interrupt(int irq, void *d)
480 struct comedi_device *dev = d;
481 struct apci3120_private *devpriv = dev->private;
482 struct comedi_subdevice *s = dev->read_subdev;
483 struct comedi_async *async = s->async;
484 struct comedi_cmd *cmd = &async->cmd;
486 unsigned int int_amcc;
488 status = inw(dev->iobase + APCI3120_STATUS_REG);
489 int_amcc = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
491 if (!(status & APCI3120_STATUS_INT_MASK) &&
492 !(int_amcc & ANY_S593X_INT)) {
493 dev_err(dev->class_dev, "IRQ from unknown source\n");
497 outl(int_amcc | AINT_INT_MASK, devpriv->amcc + AMCC_OP_REG_INTCSR);
499 if (devpriv->ctrl & APCI3120_CTRL_EXT_TRIG)
500 apci3120_exttrig_enable(dev, false);
502 if (int_amcc & MASTER_ABORT_INT)
503 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
504 if (int_amcc & TARGET_ABORT_INT)
505 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
507 if ((status & APCI3120_STATUS_EOS_INT) &&
508 (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) {
512 for (i = 0; i < cmd->chanlist_len; i++) {
513 val = inw(dev->iobase + APCI3120_AI_FIFO_REG);
514 comedi_buf_write_samples(s, &val, 1);
517 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
518 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
521 if (status & APCI3120_STATUS_TIMER2_INT) {
524 * timer2 interrupts are not enabled in the driver
526 apci3120_clr_timer2_interrupt(dev);
529 if (status & APCI3120_STATUS_AMCC_INT) {
530 /* AMCC- Clear write complete interrupt (DMA) */
531 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
533 /* do some data transfer */
534 apci3120_interrupt_dma(dev, s);
537 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
538 async->events |= COMEDI_CB_EOA;
540 comedi_handle_events(dev, s);
545 static int apci3120_ai_cmd(struct comedi_device *dev,
546 struct comedi_subdevice *s)
548 struct apci3120_private *devpriv = dev->private;
549 struct comedi_cmd *cmd = &s->async->cmd;
550 unsigned int divisor;
552 /* set default mode bits */
553 devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
554 APCI3120_MODE_TIMER2_AS_TIMER;
556 /* AMCC- Clear write complete interrupt (DMA) */
557 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
559 devpriv->cur_dmabuf = 0;
561 /* load chanlist for command scan */
562 apci3120_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist);
564 if (cmd->start_src == TRIG_EXT)
565 apci3120_exttrig_enable(dev, true);
567 if (cmd->scan_begin_src == TRIG_TIMER) {
569 * Timer 1 is used in MODE2 (rate generator) to set the
570 * start time for each scan.
572 divisor = apci3120_ns_to_timer(dev, 1, cmd->scan_begin_arg,
574 apci3120_timer_set_mode(dev, 1, APCI3120_TIMER_MODE2);
575 apci3120_timer_write(dev, 1, divisor);
579 * Timer 0 is used in MODE2 (rate generator) to set the conversion
580 * time for each acquisition.
582 divisor = apci3120_ns_to_timer(dev, 0, cmd->convert_arg, cmd->flags);
583 apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE2);
584 apci3120_timer_write(dev, 0, divisor);
586 if (devpriv->use_dma)
587 apci3120_setup_dma(dev, s);
589 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
591 /* set mode to enable acquisition */
592 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
594 if (cmd->scan_begin_src == TRIG_TIMER)
595 apci3120_timer_enable(dev, 1, true);
596 apci3120_timer_enable(dev, 0, true);
601 static int apci3120_ai_cmdtest(struct comedi_device *dev,
602 struct comedi_subdevice *s,
603 struct comedi_cmd *cmd)
608 /* Step 1 : check if triggers are trivially valid */
610 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
611 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
612 TRIG_TIMER | TRIG_FOLLOW);
613 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
614 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
615 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
620 /* Step 2a : make sure trigger sources are unique */
622 err |= comedi_check_trigger_is_unique(cmd->start_src);
623 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
624 err |= comedi_check_trigger_is_unique(cmd->stop_src);
626 /* Step 2b : and mutually compatible */
631 /* Step 3: check if arguments are trivially valid */
633 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
635 if (cmd->scan_begin_src == TRIG_TIMER) { /* Test Delay timing */
636 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
640 /* minimum conversion time per sample is 10us */
641 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
643 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
644 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
647 if (cmd->stop_src == TRIG_COUNT)
648 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
650 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
655 /* Step 4: fix up any arguments */
657 if (cmd->scan_begin_src == TRIG_TIMER) {
658 /* scan begin must be larger than the scan time */
659 arg = cmd->convert_arg * cmd->scan_end_arg;
660 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
666 /* Step 5: check channel list if it exists */
671 static int apci3120_cancel(struct comedi_device *dev,
672 struct comedi_subdevice *s)
674 struct apci3120_private *devpriv = dev->private;
676 /* Add-On - disable DMA */
677 outw(0, devpriv->addon + 4);
679 /* Add-On - disable bus master */
680 apci3120_addon_write(dev, 0, AMCC_OP_REG_AGCSTS);
682 /* AMCC - disable bus master */
683 outl(0, devpriv->amcc + AMCC_OP_REG_MCSR);
685 /* disable all counters, ext trigger, and reset scan */
687 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
689 /* DISABLE_ALL_INTERRUPT */
691 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
693 inw(dev->iobase + APCI3120_STATUS_REG);
694 devpriv->cur_dmabuf = 0;
699 static int apci3120_ai_eoc(struct comedi_device *dev,
700 struct comedi_subdevice *s,
701 struct comedi_insn *insn,
702 unsigned long context)
706 status = inw(dev->iobase + APCI3120_STATUS_REG);
707 if ((status & APCI3120_STATUS_EOC_INT) == 0)
712 static int apci3120_ai_insn_read(struct comedi_device *dev,
713 struct comedi_subdevice *s,
714 struct comedi_insn *insn,
717 struct apci3120_private *devpriv = dev->private;
718 unsigned int divisor;
722 /* set mode for A/D conversions by software trigger with timer 0 */
723 devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
724 APCI3120_MODE_TIMER2_AS_TIMER;
725 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
727 /* load chanlist for single channel scan */
728 apci3120_set_chanlist(dev, s, 1, &insn->chanspec);
731 * Timer 0 is used in MODE4 (software triggered strobe) to set the
732 * conversion time for each acquisition. Each conversion is triggered
733 * when the divisor is written to the timer, The conversion is done
734 * when the EOC bit in the status register is '0'.
736 apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE4);
737 apci3120_timer_enable(dev, 0, true);
739 /* fixed conversion time of 10 us */
740 divisor = apci3120_ns_to_timer(dev, 0, 10000, CMDF_ROUND_NEAREST);
742 for (i = 0; i < insn->n; i++) {
743 /* trigger conversion */
744 apci3120_timer_write(dev, 0, divisor);
746 ret = comedi_timeout(dev, s, insn, apci3120_ai_eoc, 0);
750 data[i] = inw(dev->iobase + APCI3120_AI_FIFO_REG);
756 static int apci3120_ao_ready(struct comedi_device *dev,
757 struct comedi_subdevice *s,
758 struct comedi_insn *insn,
759 unsigned long context)
763 status = inw(dev->iobase + APCI3120_STATUS_REG);
764 if (status & APCI3120_STATUS_DA_READY)
769 static int apci3120_ao_insn_write(struct comedi_device *dev,
770 struct comedi_subdevice *s,
771 struct comedi_insn *insn,
774 unsigned int chan = CR_CHAN(insn->chanspec);
777 for (i = 0; i < insn->n; i++) {
778 unsigned int val = data[i];
781 ret = comedi_timeout(dev, s, insn, apci3120_ao_ready, 0);
785 outw(APCI3120_AO_MUX(chan) | APCI3120_AO_DATA(val),
786 dev->iobase + APCI3120_AO_REG(chan));
788 s->readback[chan] = val;
794 static int apci3120_di_insn_bits(struct comedi_device *dev,
795 struct comedi_subdevice *s,
796 struct comedi_insn *insn,
801 status = inw(dev->iobase + APCI3120_STATUS_REG);
802 data[1] = APCI3120_STATUS_TO_DI_BITS(status);
807 static int apci3120_do_insn_bits(struct comedi_device *dev,
808 struct comedi_subdevice *s,
809 struct comedi_insn *insn,
812 struct apci3120_private *devpriv = dev->private;
814 if (comedi_dio_update_state(s, data)) {
815 devpriv->do_bits = s->state;
816 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits),
817 dev->iobase + APCI3120_CTR0_REG);
825 static int apci3120_timer_insn_config(struct comedi_device *dev,
826 struct comedi_subdevice *s,
827 struct comedi_insn *insn,
830 struct apci3120_private *devpriv = dev->private;
831 unsigned int divisor;
834 unsigned int timer_mode;
837 case INSN_CONFIG_ARM:
838 apci3120_clr_timer2_interrupt(dev);
839 divisor = apci3120_ns_to_timer(dev, 2, data[1],
841 apci3120_timer_write(dev, 2, divisor);
842 apci3120_timer_enable(dev, 2, true);
845 case INSN_CONFIG_DISARM:
846 apci3120_timer_enable(dev, 2, false);
847 apci3120_clr_timer2_interrupt(dev);
850 case INSN_CONFIG_GET_COUNTER_STATUS:
852 data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING |
853 COMEDI_COUNTER_TERMINAL_COUNT;
855 if (devpriv->ctrl & APCI3120_CTRL_GATE(2)) {
856 data[1] |= COMEDI_COUNTER_ARMED;
857 data[1] |= COMEDI_COUNTER_COUNTING;
859 status = inw(dev->iobase + APCI3120_STATUS_REG);
860 if (status & APCI3120_STATUS_TIMER2_INT) {
861 data[1] &= ~COMEDI_COUNTER_COUNTING;
862 data[1] |= COMEDI_COUNTER_TERMINAL_COUNT;
866 case INSN_CONFIG_SET_COUNTER_MODE:
869 mode = APCI3120_MODE_TIMER2_AS_COUNTER;
870 timer_mode = APCI3120_TIMER_MODE0;
873 mode = APCI3120_MODE_TIMER2_AS_TIMER;
874 timer_mode = APCI3120_TIMER_MODE2;
877 mode = APCI3120_MODE_TIMER2_AS_TIMER;
878 timer_mode = APCI3120_TIMER_MODE4;
881 mode = APCI3120_MODE_TIMER2_AS_WDOG;
882 timer_mode = APCI3120_TIMER_MODE5;
887 apci3120_timer_enable(dev, 2, false);
888 apci3120_clr_timer2_interrupt(dev);
889 apci3120_timer_set_mode(dev, 2, timer_mode);
890 devpriv->mode &= ~APCI3120_MODE_TIMER2_AS_MASK;
891 devpriv->mode |= mode;
892 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
902 static int apci3120_timer_insn_read(struct comedi_device *dev,
903 struct comedi_subdevice *s,
904 struct comedi_insn *insn,
909 for (i = 0; i < insn->n; i++)
910 data[i] = apci3120_timer_read(dev, 2);
915 static void apci3120_dma_alloc(struct comedi_device *dev)
917 struct apci3120_private *devpriv = dev->private;
918 struct apci3120_dmabuf *dmabuf;
922 for (i = 0; i < 2; i++) {
923 dmabuf = &devpriv->dmabuf[i];
924 for (order = 2; order >= 0; order--) {
925 dmabuf->virt = dma_alloc_coherent(dev->hw_dev,
934 dmabuf->size = PAGE_SIZE << order;
937 devpriv->use_dma = 1;
939 devpriv->use_double_buffer = 1;
943 static void apci3120_dma_free(struct comedi_device *dev)
945 struct apci3120_private *devpriv = dev->private;
946 struct apci3120_dmabuf *dmabuf;
952 for (i = 0; i < 2; i++) {
953 dmabuf = &devpriv->dmabuf[i];
955 dma_free_coherent(dev->hw_dev, dmabuf->size,
956 dmabuf->virt, dmabuf->hw);
961 static void apci3120_reset(struct comedi_device *dev)
963 /* disable all interrupt sources */
964 outb(0, dev->iobase + APCI3120_MODE_REG);
966 /* disable all counters, ext trigger, and reset scan */
967 outw(0, dev->iobase + APCI3120_CTRL_REG);
969 /* clear interrupt status */
970 inw(dev->iobase + APCI3120_STATUS_REG);
973 static int apci3120_auto_attach(struct comedi_device *dev,
974 unsigned long context)
976 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
977 const struct apci3120_board *board = NULL;
978 struct apci3120_private *devpriv;
979 struct comedi_subdevice *s;
983 if (context < ARRAY_SIZE(apci3120_boardtypes))
984 board = &apci3120_boardtypes[context];
987 dev->board_ptr = board;
988 dev->board_name = board->name;
990 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
994 ret = comedi_pci_enable(dev);
997 pci_set_master(pcidev);
999 dev->iobase = pci_resource_start(pcidev, 1);
1000 devpriv->amcc = pci_resource_start(pcidev, 0);
1001 devpriv->addon = pci_resource_start(pcidev, 2);
1003 apci3120_reset(dev);
1005 if (pcidev->irq > 0) {
1006 ret = request_irq(pcidev->irq, apci3120_interrupt, IRQF_SHARED,
1007 dev->board_name, dev);
1009 dev->irq = pcidev->irq;
1011 apci3120_dma_alloc(dev);
1015 status = inw(dev->iobase + APCI3120_STATUS_REG);
1016 if (APCI3120_STATUS_TO_VERSION(status) == APCI3120_REVB ||
1017 context == BOARD_APCI3001)
1018 devpriv->osc_base = APCI3120_REVB_OSC_BASE;
1020 devpriv->osc_base = APCI3120_REVA_OSC_BASE;
1022 ret = comedi_alloc_subdevices(dev, 5);
1026 /* Analog Input subdevice */
1027 s = &dev->subdevices[0];
1028 s->type = COMEDI_SUBD_AI;
1029 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1031 s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff;
1032 s->range_table = &apci3120_ai_range;
1033 s->insn_read = apci3120_ai_insn_read;
1035 dev->read_subdev = s;
1036 s->subdev_flags |= SDF_CMD_READ;
1037 s->len_chanlist = s->n_chan;
1038 s->do_cmdtest = apci3120_ai_cmdtest;
1039 s->do_cmd = apci3120_ai_cmd;
1040 s->cancel = apci3120_cancel;
1043 /* Analog Output subdevice */
1044 s = &dev->subdevices[1];
1045 if (board->has_ao) {
1046 s->type = COMEDI_SUBD_AO;
1047 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1049 s->maxdata = 0x3fff;
1050 s->range_table = &range_bipolar10;
1051 s->insn_write = apci3120_ao_insn_write;
1053 ret = comedi_alloc_subdev_readback(s);
1057 s->type = COMEDI_SUBD_UNUSED;
1060 /* Digital Input subdevice */
1061 s = &dev->subdevices[2];
1062 s->type = COMEDI_SUBD_DI;
1063 s->subdev_flags = SDF_READABLE;
1066 s->range_table = &range_digital;
1067 s->insn_bits = apci3120_di_insn_bits;
1069 /* Digital Output subdevice */
1070 s = &dev->subdevices[3];
1071 s->type = COMEDI_SUBD_DO;
1072 s->subdev_flags = SDF_WRITABLE;
1075 s->range_table = &range_digital;
1076 s->insn_bits = apci3120_do_insn_bits;
1078 /* Timer subdevice */
1079 s = &dev->subdevices[4];
1080 s->type = COMEDI_SUBD_TIMER;
1081 s->subdev_flags = SDF_READABLE;
1083 s->maxdata = 0x00ffffff;
1084 s->insn_config = apci3120_timer_insn_config;
1085 s->insn_read = apci3120_timer_insn_read;
1090 static void apci3120_detach(struct comedi_device *dev)
1092 comedi_pci_detach(dev);
1093 apci3120_dma_free(dev);
1096 static struct comedi_driver apci3120_driver = {
1097 .driver_name = "addi_apci_3120",
1098 .module = THIS_MODULE,
1099 .auto_attach = apci3120_auto_attach,
1100 .detach = apci3120_detach,
1103 static int apci3120_pci_probe(struct pci_dev *dev,
1104 const struct pci_device_id *id)
1106 return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data);
1109 static const struct pci_device_id apci3120_pci_table[] = {
1110 { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 },
1111 { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 },
1114 MODULE_DEVICE_TABLE(pci, apci3120_pci_table);
1116 static struct pci_driver apci3120_pci_driver = {
1117 .name = "addi_apci_3120",
1118 .id_table = apci3120_pci_table,
1119 .probe = apci3120_pci_probe,
1120 .remove = comedi_pci_auto_unconfig,
1122 module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
1124 MODULE_AUTHOR("Comedi http://www.comedi.org");
1125 MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board");
1126 MODULE_LICENSE("GPL");