2 * comedi/drivers/amplc_pci224.c
3 * Driver for Amplicon PCI224 and PCI234 AO boards.
5 * Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/>
7 * COMEDI - Linux Control and Measurement Device Interface
8 * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
22 * Driver: amplc_pci224
23 * Description: Amplicon PCI224, PCI234
24 * Author: Ian Abbott <abbotti@mev.co.uk>
25 * Devices: [Amplicon] PCI224 (amplc_pci224), PCI234
26 * Updated: Thu, 31 Jul 2014 11:08:03 +0000
27 * Status: works, but see caveats
31 * - ao_insn read/write
32 * - ao_do_cmd mode with the following sources:
34 * - start_src TRIG_INT TRIG_EXT
35 * - scan_begin_src TRIG_TIMER TRIG_EXT
36 * - convert_src TRIG_NOW
37 * - scan_end_src TRIG_COUNT
38 * - stop_src TRIG_COUNT TRIG_EXT TRIG_NONE
40 * The channel list must contain at least one channel with no repeated
41 * channels. The scan end count must equal the number of channels in
44 * There is only one external trigger source so only one of start_src,
45 * scan_begin_src or stop_src may use TRIG_EXT.
47 * Configuration options:
50 * Manual configuration of PCI cards is not supported; they are configured
53 * Output range selection - PCI224:
55 * Output ranges on PCI224 are partly software-selectable and partly
56 * hardware-selectable according to jumper LK1. All channels are set
59 * - LK1 position 1-2 (factory default) corresponds to the following
62 * 0: [-10V,+10V]; 1: [-5V,+5V]; 2: [-2.5V,+2.5V], 3: [-1.25V,+1.25V],
63 * 4: [0,+10V], 5: [0,+5V], 6: [0,+2.5V], 7: [0,+1.25V]
65 * - LK1 position 2-3 corresponds to the following Comedi ranges, using
66 * an external voltage reference:
71 * Output range selection - PCI234:
73 * Output ranges on PCI234 are hardware-selectable according to jumper
74 * LK1 which affects all channels, and jumpers LK2, LK3, LK4 and LK5
75 * which affect channels 0, 1, 2 and 3 individually. LK1 chooses between
76 * an internal 5V reference and an external voltage reference (Vext).
77 * LK2/3/4/5 choose (per channel) to double the reference or not according
78 * to the following table:
80 * LK1 position LK2/3/4/5 pos Comedi range
81 * ------------- ------------- --------------
82 * 2-3 (factory) 1-2 (factory) 0: [-10V,+10V]
83 * 2-3 (factory) 2-3 1: [-5V,+5V]
84 * 1-2 1-2 (factory) 2: [-2*Vext,+2*Vext]
85 * 1-2 2-3 3: [-Vext,+Vext]
89 * 1) All channels on the PCI224 share the same range. Any change to the
90 * range as a result of insn_write or a streaming command will affect
91 * the output voltages of all channels, including those not specified
92 * by the instruction or command.
94 * 2) For the analog output command, the first scan may be triggered
95 * falsely at the start of acquisition. This occurs when the DAC scan
96 * trigger source is switched from 'none' to 'timer' (scan_begin_src =
97 * TRIG_TIMER) or 'external' (scan_begin_src == TRIG_EXT) at the start
98 * of acquisition and the trigger source is at logic level 1 at the
99 * time of the switch. This is very likely for TRIG_TIMER. For
100 * TRIG_EXT, it depends on the state of the external line and whether
101 * the CR_INVERT flag has been set. The remaining scans are triggered
105 #include <linux/module.h>
106 #include <linux/interrupt.h>
107 #include <linux/slab.h>
109 #include "../comedi_pci.h"
111 #include "comedi_8254.h"
114 * PCI224/234 i/o space 1 (PCIBAR2) registers.
116 #define PCI224_Z2_BASE 0x14 /* 82C54 counter/timer */
117 #define PCI224_ZCLK_SCE 0x1A /* Group Z Clock Configuration Register */
118 #define PCI224_ZGAT_SCE 0x1D /* Group Z Gate Configuration Register */
119 #define PCI224_INT_SCE 0x1E /* ISR Interrupt source mask register */
120 /* /Interrupt status */
123 * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
125 #define PCI224_DACDATA 0x00 /* (w-o) DAC FIFO data. */
126 #define PCI224_SOFTTRIG 0x00 /* (r-o) DAC software scan trigger. */
127 #define PCI224_DACCON 0x02 /* (r/w) DAC status/configuration. */
128 #define PCI224_FIFOSIZ 0x04 /* (w-o) FIFO size for wraparound mode. */
129 #define PCI224_DACCEN 0x06 /* (w-o) DAC channel enable register. */
134 /* (r/w) Scan trigger. */
135 #define PCI224_DACCON_TRIG(x) (((x) & 0x7) << 0)
136 #define PCI224_DACCON_TRIG_MASK PCI224_DACCON_TRIG(7)
137 #define PCI224_DACCON_TRIG_NONE PCI224_DACCON_TRIG(0) /* none */
138 #define PCI224_DACCON_TRIG_SW PCI224_DACCON_TRIG(1) /* soft trig */
139 #define PCI224_DACCON_TRIG_EXTP PCI224_DACCON_TRIG(2) /* ext + edge */
140 #define PCI224_DACCON_TRIG_EXTN PCI224_DACCON_TRIG(3) /* ext - edge */
141 #define PCI224_DACCON_TRIG_Z2CT0 PCI224_DACCON_TRIG(4) /* Z2 CT0 out */
142 #define PCI224_DACCON_TRIG_Z2CT1 PCI224_DACCON_TRIG(5) /* Z2 CT1 out */
143 #define PCI224_DACCON_TRIG_Z2CT2 PCI224_DACCON_TRIG(6) /* Z2 CT2 out */
144 /* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */
145 #define PCI224_DACCON_POLAR(x) (((x) & 0x1) << 3)
146 #define PCI224_DACCON_POLAR_MASK PCI224_DACCON_POLAR(1)
147 #define PCI224_DACCON_POLAR_UNI PCI224_DACCON_POLAR(0) /* [0,+V] */
148 #define PCI224_DACCON_POLAR_BI PCI224_DACCON_POLAR(1) /* [-V,+V] */
149 /* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */
150 #define PCI224_DACCON_VREF(x) (((x) & 0x3) << 4)
151 #define PCI224_DACCON_VREF_MASK PCI224_DACCON_VREF(3)
152 #define PCI224_DACCON_VREF_1_25 PCI224_DACCON_VREF(0) /* 1.25V */
153 #define PCI224_DACCON_VREF_2_5 PCI224_DACCON_VREF(1) /* 2.5V */
154 #define PCI224_DACCON_VREF_5 PCI224_DACCON_VREF(2) /* 5V */
155 #define PCI224_DACCON_VREF_10 PCI224_DACCON_VREF(3) /* 10V */
156 /* (r/w) Wraparound mode enable (to play back stored waveform). */
157 #define PCI224_DACCON_FIFOWRAP BIT(7)
158 /* (r/w) FIFO enable. It MUST be set! */
159 #define PCI224_DACCON_FIFOENAB BIT(8)
160 /* (r/w) FIFO interrupt trigger level (most values are not very useful). */
161 #define PCI224_DACCON_FIFOINTR(x) (((x) & 0x7) << 9)
162 #define PCI224_DACCON_FIFOINTR_MASK PCI224_DACCON_FIFOINTR(7)
163 #define PCI224_DACCON_FIFOINTR_EMPTY PCI224_DACCON_FIFOINTR(0) /* empty */
164 #define PCI224_DACCON_FIFOINTR_NEMPTY PCI224_DACCON_FIFOINTR(1) /* !empty */
165 #define PCI224_DACCON_FIFOINTR_NHALF PCI224_DACCON_FIFOINTR(2) /* !half */
166 #define PCI224_DACCON_FIFOINTR_HALF PCI224_DACCON_FIFOINTR(3) /* half */
167 #define PCI224_DACCON_FIFOINTR_NFULL PCI224_DACCON_FIFOINTR(4) /* !full */
168 #define PCI224_DACCON_FIFOINTR_FULL PCI224_DACCON_FIFOINTR(5) /* full */
169 /* (r-o) FIFO fill level. */
170 #define PCI224_DACCON_FIFOFL(x) (((x) & 0x7) << 12)
171 #define PCI224_DACCON_FIFOFL_MASK PCI224_DACCON_FIFOFL(7)
172 #define PCI224_DACCON_FIFOFL_EMPTY PCI224_DACCON_FIFOFL(1) /* 0 */
173 #define PCI224_DACCON_FIFOFL_ONETOHALF PCI224_DACCON_FIFOFL(0) /* 1-2048 */
174 #define PCI224_DACCON_FIFOFL_HALFTOFULL PCI224_DACCON_FIFOFL(4) /* 2049-4095 */
175 #define PCI224_DACCON_FIFOFL_FULL PCI224_DACCON_FIFOFL(6) /* 4096 */
176 /* (r-o) DAC busy flag. */
177 #define PCI224_DACCON_BUSY BIT(15)
178 /* (w-o) FIFO reset. */
179 #define PCI224_DACCON_FIFORESET BIT(12)
180 /* (w-o) Global reset (not sure what it does). */
181 #define PCI224_DACCON_GLOBALRESET BIT(13)
186 #define PCI224_FIFO_SIZE 4096
189 * DAC FIFO guaranteed minimum room available, depending on reported fill level.
190 * The maximum room available depends on the reported fill level and how much
193 #define PCI224_FIFO_ROOM_EMPTY PCI224_FIFO_SIZE
194 #define PCI224_FIFO_ROOM_ONETOHALF (PCI224_FIFO_SIZE / 2)
195 #define PCI224_FIFO_ROOM_HALFTOFULL 1
196 #define PCI224_FIFO_ROOM_FULL 0
199 * Counter/timer clock input configuration sources.
201 #define CLK_CLK 0 /* reserved (channel-specific clock) */
202 #define CLK_10MHZ 1 /* internal 10 MHz clock */
203 #define CLK_1MHZ 2 /* internal 1 MHz clock */
204 #define CLK_100KHZ 3 /* internal 100 kHz clock */
205 #define CLK_10KHZ 4 /* internal 10 kHz clock */
206 #define CLK_1KHZ 5 /* internal 1 kHz clock */
207 #define CLK_OUTNM1 6 /* output of channel-1 modulo total */
208 #define CLK_EXT 7 /* external clock */
209 /* Macro to construct clock input configuration register value. */
210 #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
213 * Counter/timer gate input configuration sources.
215 #define GAT_VCC 0 /* VCC (i.e. enabled) */
216 #define GAT_GND 1 /* GND (i.e. disabled) */
217 #define GAT_EXT 2 /* reserved (external gate input) */
218 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
219 /* Macro to construct gate input configuration register value. */
220 #define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
223 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234:
225 * Channel's Channel's
226 * clock input gate input
227 * Channel CLK_OUTNM1 GAT_NOUTNM2
228 * ------- ---------- -----------
229 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
230 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
231 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
235 * Interrupt enable/status bits
237 #define PCI224_INTR_EXT 0x01 /* rising edge on external input */
238 #define PCI224_INTR_DAC 0x04 /* DAC (FIFO) interrupt */
239 #define PCI224_INTR_Z2CT1 0x20 /* rising edge on Z2-CT1 output */
241 #define PCI224_INTR_EDGE_BITS (PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
242 #define PCI224_INTR_LEVEL_BITS PCI224_INTR_DACFIFO
248 /* Combine old and new bits. */
249 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
251 /* Current CPU. XXX should this be hard_smp_processor_id()? */
252 #define THISCPU smp_processor_id()
254 /* State bits for use with atomic bit operations. */
255 #define AO_CMD_STARTED 0
262 * The ranges for PCI224.
264 * These are partly hardware-selectable by jumper LK1 and partly
265 * software-selectable.
267 * All channels share the same hardware range.
269 static const struct comedi_lrange range_pci224 = {
271 /* jumper LK1 in position 1-2 (factory default) */
280 /* jumper LK1 in position 2-3 */
281 RANGE_ext(-1, 1), /* bipolar [-Vext,+Vext] */
282 RANGE_ext(0, 1), /* unipolar [0,+Vext] */
286 static const unsigned short hwrange_pci224[10] = {
287 /* jumper LK1 in position 1-2 (factory default) */
288 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10,
289 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5,
290 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5,
291 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25,
292 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10,
293 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5,
294 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5,
295 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25,
296 /* jumper LK1 in position 2-3 */
297 PCI224_DACCON_POLAR_BI,
298 PCI224_DACCON_POLAR_UNI,
301 /* Used to check all channels set to the same range on PCI224. */
302 static const unsigned char range_check_pci224[10] = {
303 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
307 * The ranges for PCI234.
309 * These are all hardware-selectable by jumper LK1 affecting all channels,
310 * and jumpers LK2, LK3, LK4 and LK5 affecting channels 0, 1, 2 and 3
313 static const struct comedi_lrange range_pci234 = {
315 /* LK1: 1-2 (fact def), LK2/3/4/5: 2-3 (fac def) */
317 /* LK1: 1-2 (fact def), LK2/3/4/5: 1-2 */
319 /* LK1: 2-3, LK2/3/4/5: 2-3 (fac def) */
320 RANGE_ext(-2, 2), /* bipolar [-2*Vext,+2*Vext] */
321 /* LK1: 2-3, LK2/3/4/5: 1-2 */
322 RANGE_ext(-1, 1), /* bipolar [-Vext,+Vext] */
326 /* N.B. PCI234 ignores the polarity bit, but software uses it. */
327 static const unsigned short hwrange_pci234[4] = {
328 PCI224_DACCON_POLAR_BI,
329 PCI224_DACCON_POLAR_BI,
330 PCI224_DACCON_POLAR_BI,
331 PCI224_DACCON_POLAR_BI,
334 /* Used to check all channels use same LK1 setting on PCI234. */
335 static const unsigned char range_check_pci234[4] = {
340 * Board descriptions.
343 enum pci224_model { pci224_model, pci234_model };
345 struct pci224_board {
347 unsigned int ao_chans;
348 unsigned int ao_bits;
349 const struct comedi_lrange *ao_range;
350 const unsigned short *ao_hwrange;
351 const unsigned char *ao_range_check;
354 static const struct pci224_board pci224_boards[] = {
359 .ao_range = &range_pci224,
360 .ao_hwrange = &hwrange_pci224[0],
361 .ao_range_check = &range_check_pci224[0],
367 .ao_range = &range_pci234,
368 .ao_hwrange = &hwrange_pci234[0],
369 .ao_range_check = &range_check_pci234[0],
373 struct pci224_private {
374 unsigned long iobase1;
376 spinlock_t ao_spinlock; /* spinlock for AO command handling */
377 unsigned short *ao_scan_vals;
378 unsigned char *ao_scan_order;
381 unsigned short daccon;
382 unsigned short ao_enab; /* max 16 channels so 'short' will do */
383 unsigned char intsce;
387 * Called from the 'insn_write' function to perform a single write.
390 pci224_ao_set_data(struct comedi_device *dev, int chan, int range,
393 const struct pci224_board *board = dev->board_ptr;
394 struct pci224_private *devpriv = dev->private;
395 unsigned short mangled;
397 /* Enable the channel. */
398 outw(1 << chan, dev->iobase + PCI224_DACCEN);
399 /* Set range and reset FIFO. */
400 devpriv->daccon = COMBINE(devpriv->daccon, board->ao_hwrange[range],
401 PCI224_DACCON_POLAR_MASK |
402 PCI224_DACCON_VREF_MASK);
403 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
404 dev->iobase + PCI224_DACCON);
406 * Mangle the data. The hardware expects:
407 * - bipolar: 16-bit 2's complement
408 * - unipolar: 16-bit unsigned
410 mangled = (unsigned short)data << (16 - board->ao_bits);
411 if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
412 PCI224_DACCON_POLAR_BI) {
415 /* Write mangled data to the FIFO. */
416 outw(mangled, dev->iobase + PCI224_DACDATA);
417 /* Trigger the conversion. */
418 inw(dev->iobase + PCI224_SOFTTRIG);
421 static int pci224_ao_insn_write(struct comedi_device *dev,
422 struct comedi_subdevice *s,
423 struct comedi_insn *insn,
426 unsigned int chan = CR_CHAN(insn->chanspec);
427 unsigned int range = CR_RANGE(insn->chanspec);
428 unsigned int val = s->readback[chan];
431 for (i = 0; i < insn->n; i++) {
433 pci224_ao_set_data(dev, chan, range, val);
435 s->readback[chan] = val;
441 * Kills a command running on the AO subdevice.
443 static void pci224_ao_stop(struct comedi_device *dev,
444 struct comedi_subdevice *s)
446 struct pci224_private *devpriv = dev->private;
449 if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
452 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
453 /* Kill the interrupts. */
455 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
457 * Interrupt routine may or may not be running. We may or may not
458 * have been called from the interrupt routine (directly or
459 * indirectly via a comedi_events() callback routine). It's highly
460 * unlikely that we've been called from some other interrupt routine
461 * but who knows what strange things coders get up to!
463 * If the interrupt routine is currently running, wait for it to
464 * finish, unless we appear to have been called via the interrupt
467 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
468 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
469 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
471 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
472 /* Reconfigure DAC for insn_write usage. */
473 outw(0, dev->iobase + PCI224_DACCEN); /* Disable channels. */
475 COMBINE(devpriv->daccon,
476 PCI224_DACCON_TRIG_SW | PCI224_DACCON_FIFOINTR_EMPTY,
477 PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
478 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
479 dev->iobase + PCI224_DACCON);
483 * Handles start of acquisition for the AO subdevice.
485 static void pci224_ao_start(struct comedi_device *dev,
486 struct comedi_subdevice *s)
488 struct pci224_private *devpriv = dev->private;
489 struct comedi_cmd *cmd = &s->async->cmd;
492 set_bit(AO_CMD_STARTED, &devpriv->state);
494 /* Enable interrupts. */
495 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
496 if (cmd->stop_src == TRIG_EXT)
497 devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
499 devpriv->intsce = PCI224_INTR_DAC;
501 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
502 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
506 * Handles interrupts from the DAC FIFO.
508 static void pci224_ao_handle_fifo(struct comedi_device *dev,
509 struct comedi_subdevice *s)
511 struct pci224_private *devpriv = dev->private;
512 struct comedi_cmd *cmd = &s->async->cmd;
513 unsigned int num_scans = comedi_nscans_left(s, 0);
515 unsigned short dacstat;
518 /* Determine how much room is in the FIFO (in samples). */
519 dacstat = inw(dev->iobase + PCI224_DACCON);
520 switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
521 case PCI224_DACCON_FIFOFL_EMPTY:
522 room = PCI224_FIFO_ROOM_EMPTY;
523 if (cmd->stop_src == TRIG_COUNT &&
524 s->async->scans_done >= cmd->stop_arg) {
525 /* FIFO empty at end of counted acquisition. */
526 s->async->events |= COMEDI_CB_EOA;
527 comedi_handle_events(dev, s);
531 case PCI224_DACCON_FIFOFL_ONETOHALF:
532 room = PCI224_FIFO_ROOM_ONETOHALF;
534 case PCI224_DACCON_FIFOFL_HALFTOFULL:
535 room = PCI224_FIFO_ROOM_HALFTOFULL;
538 room = PCI224_FIFO_ROOM_FULL;
541 if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
542 /* FIFO is less than half-full. */
543 if (num_scans == 0) {
544 /* Nothing left to put in the FIFO. */
545 dev_err(dev->class_dev, "AO buffer underrun\n");
546 s->async->events |= COMEDI_CB_OVERFLOW;
549 /* Determine how many new scans can be put in the FIFO. */
550 room /= cmd->chanlist_len;
552 /* Determine how many scans to process. */
553 if (num_scans > room)
557 for (n = 0; n < num_scans; n++) {
558 comedi_buf_read_samples(s, &devpriv->ao_scan_vals[0],
560 for (i = 0; i < cmd->chanlist_len; i++) {
561 outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
562 dev->iobase + PCI224_DACDATA);
565 if (cmd->stop_src == TRIG_COUNT &&
566 s->async->scans_done >= cmd->stop_arg) {
568 * Change FIFO interrupt trigger level to wait
569 * until FIFO is empty.
571 devpriv->daccon = COMBINE(devpriv->daccon,
572 PCI224_DACCON_FIFOINTR_EMPTY,
573 PCI224_DACCON_FIFOINTR_MASK);
574 outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
576 if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
577 PCI224_DACCON_TRIG_NONE) {
581 * This is the initial DAC FIFO interrupt at the
582 * start of the acquisition. The DAC's scan trigger
583 * has been set to 'none' up until now.
585 * Now that data has been written to the FIFO, the
586 * DAC's scan trigger source can be set to the
589 * BUG: The first scan will be triggered immediately
590 * if the scan trigger source is at logic level 1.
592 if (cmd->scan_begin_src == TRIG_TIMER) {
593 trig = PCI224_DACCON_TRIG_Z2CT0;
595 /* cmd->scan_begin_src == TRIG_EXT */
596 if (cmd->scan_begin_arg & CR_INVERT)
597 trig = PCI224_DACCON_TRIG_EXTN;
599 trig = PCI224_DACCON_TRIG_EXTP;
602 COMBINE(devpriv->daccon, trig, PCI224_DACCON_TRIG_MASK);
603 outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
606 comedi_handle_events(dev, s);
609 static int pci224_ao_inttrig_start(struct comedi_device *dev,
610 struct comedi_subdevice *s,
611 unsigned int trig_num)
613 struct comedi_cmd *cmd = &s->async->cmd;
615 if (trig_num != cmd->start_arg)
618 s->async->inttrig = NULL;
619 pci224_ao_start(dev, s);
624 static int pci224_ao_check_chanlist(struct comedi_device *dev,
625 struct comedi_subdevice *s,
626 struct comedi_cmd *cmd)
628 const struct pci224_board *board = dev->board_ptr;
629 unsigned int range_check_0;
630 unsigned int chan_mask = 0;
633 range_check_0 = board->ao_range_check[CR_RANGE(cmd->chanlist[0])];
634 for (i = 0; i < cmd->chanlist_len; i++) {
635 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
637 if (chan_mask & (1 << chan)) {
638 dev_dbg(dev->class_dev,
639 "%s: entries in chanlist must contain no duplicate channels\n",
643 chan_mask |= 1 << chan;
645 if (board->ao_range_check[CR_RANGE(cmd->chanlist[i])] !=
647 dev_dbg(dev->class_dev,
648 "%s: entries in chanlist have incompatible ranges\n",
657 #define MAX_SCAN_PERIOD 0xFFFFFFFFU
658 #define MIN_SCAN_PERIOD 2500
659 #define CONVERT_PERIOD 625
662 * 'do_cmdtest' function for AO subdevice.
665 pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
666 struct comedi_cmd *cmd)
671 /* Step 1 : check if triggers are trivially valid */
673 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
674 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
675 TRIG_EXT | TRIG_TIMER);
676 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
677 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
678 err |= comedi_check_trigger_src(&cmd->stop_src,
679 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
684 /* Step 2a : make sure trigger sources are unique */
686 err |= comedi_check_trigger_is_unique(cmd->start_src);
687 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
688 err |= comedi_check_trigger_is_unique(cmd->stop_src);
690 /* Step 2b : and mutually compatible */
693 * There's only one external trigger signal (which makes these
694 * tests easier). Only one thing can use it.
697 if (cmd->start_src & TRIG_EXT)
699 if (cmd->scan_begin_src & TRIG_EXT)
701 if (cmd->stop_src & TRIG_EXT)
709 /* Step 3: check if arguments are trivially valid */
711 switch (cmd->start_src) {
713 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
716 /* Force to external trigger 0. */
717 if (cmd->start_arg & ~CR_FLAGS_MASK) {
719 COMBINE(cmd->start_arg, 0, ~CR_FLAGS_MASK);
722 /* The only flag allowed is CR_EDGE, which is ignored. */
723 if (cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) {
724 cmd->start_arg = COMBINE(cmd->start_arg, 0,
725 CR_FLAGS_MASK & ~CR_EDGE);
731 switch (cmd->scan_begin_src) {
733 err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
736 arg = cmd->chanlist_len * CONVERT_PERIOD;
737 if (arg < MIN_SCAN_PERIOD)
738 arg = MIN_SCAN_PERIOD;
739 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
742 /* Force to external trigger 0. */
743 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
744 cmd->scan_begin_arg =
745 COMBINE(cmd->scan_begin_arg, 0, ~CR_FLAGS_MASK);
748 /* Only allow flags CR_EDGE and CR_INVERT. Ignore CR_EDGE. */
749 if (cmd->scan_begin_arg & CR_FLAGS_MASK &
750 ~(CR_EDGE | CR_INVERT)) {
751 cmd->scan_begin_arg =
752 COMBINE(cmd->scan_begin_arg, 0,
753 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
759 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
760 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
763 switch (cmd->stop_src) {
765 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
768 /* Force to external trigger 0. */
769 if (cmd->stop_arg & ~CR_FLAGS_MASK) {
771 COMBINE(cmd->stop_arg, 0, ~CR_FLAGS_MASK);
774 /* The only flag allowed is CR_EDGE, which is ignored. */
775 if (cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) {
777 COMBINE(cmd->stop_arg, 0, CR_FLAGS_MASK & ~CR_EDGE);
781 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
788 /* Step 4: fix up any arguments. */
790 if (cmd->scan_begin_src == TRIG_TIMER) {
791 arg = cmd->scan_begin_arg;
792 /* Use two timers. */
793 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
794 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
800 /* Step 5: check channel list if it exists */
801 if (cmd->chanlist && cmd->chanlist_len > 0)
802 err |= pci224_ao_check_chanlist(dev, s, cmd);
810 static void pci224_ao_start_pacer(struct comedi_device *dev,
811 struct comedi_subdevice *s)
813 struct pci224_private *devpriv = dev->private;
816 * The output of timer Z2-0 will be used as the scan trigger
819 /* Make sure Z2-0 is gated on. */
820 outb(GAT_CONFIG(0, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
821 /* Cascading with Z2-2. */
822 /* Make sure Z2-2 is gated on. */
823 outb(GAT_CONFIG(2, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
824 /* Z2-2 needs 10 MHz clock. */
825 outb(CLK_CONFIG(2, CLK_10MHZ), devpriv->iobase1 + PCI224_ZCLK_SCE);
826 /* Z2-0 is clocked from Z2-2's output. */
827 outb(CLK_CONFIG(0, CLK_OUTNM1), devpriv->iobase1 + PCI224_ZCLK_SCE);
829 comedi_8254_pacer_enable(dev->pacer, 2, 0, false);
832 static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
834 const struct pci224_board *board = dev->board_ptr;
835 struct pci224_private *devpriv = dev->private;
836 struct comedi_cmd *cmd = &s->async->cmd;
843 /* Cannot handle null/empty chanlist. */
844 if (!cmd->chanlist || cmd->chanlist_len == 0)
847 /* Determine which channels are enabled and their load order. */
848 devpriv->ao_enab = 0;
850 for (i = 0; i < cmd->chanlist_len; i++) {
851 ch = CR_CHAN(cmd->chanlist[i]);
852 devpriv->ao_enab |= 1U << ch;
854 for (j = 0; j < cmd->chanlist_len; j++) {
855 if (CR_CHAN(cmd->chanlist[j]) < ch)
858 devpriv->ao_scan_order[rank] = i;
861 /* Set enabled channels. */
862 outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
864 /* Determine range and polarity. All channels the same. */
865 range = CR_RANGE(cmd->chanlist[0]);
868 * Set DAC range and polarity.
869 * Set DAC scan trigger source to 'none'.
870 * Set DAC FIFO interrupt trigger level to 'not half full'.
873 * N.B. DAC FIFO interrupts are currently disabled.
876 COMBINE(devpriv->daccon,
877 board->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE |
878 PCI224_DACCON_FIFOINTR_NHALF,
879 PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK |
880 PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
881 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
882 dev->iobase + PCI224_DACCON);
884 if (cmd->scan_begin_src == TRIG_TIMER) {
885 comedi_8254_update_divisors(dev->pacer);
886 pci224_ao_start_pacer(dev, s);
889 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
890 if (cmd->start_src == TRIG_INT) {
891 s->async->inttrig = pci224_ao_inttrig_start;
892 } else { /* TRIG_EXT */
893 /* Enable external interrupt trigger to start acquisition. */
894 devpriv->intsce |= PCI224_INTR_EXT;
895 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
897 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
903 * 'cancel' function for AO subdevice.
905 static int pci224_ao_cancel(struct comedi_device *dev,
906 struct comedi_subdevice *s)
908 pci224_ao_stop(dev, s);
913 * 'munge' data for AO command.
916 pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
917 void *data, unsigned int num_bytes, unsigned int chan_index)
919 const struct pci224_board *board = dev->board_ptr;
920 struct comedi_cmd *cmd = &s->async->cmd;
921 unsigned short *array = data;
922 unsigned int length = num_bytes / sizeof(*array);
927 /* The hardware expects 16-bit numbers. */
928 shift = 16 - board->ao_bits;
929 /* Channels will be all bipolar or all unipolar. */
930 if ((board->ao_hwrange[CR_RANGE(cmd->chanlist[0])] &
931 PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
938 /* Munge the data. */
939 for (i = 0; i < length; i++)
940 array[i] = (array[i] << shift) - offset;
946 static irqreturn_t pci224_interrupt(int irq, void *d)
948 struct comedi_device *dev = d;
949 struct pci224_private *devpriv = dev->private;
950 struct comedi_subdevice *s = dev->write_subdev;
951 struct comedi_cmd *cmd;
952 unsigned char intstat, valid_intstat;
953 unsigned char curenab;
957 intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
960 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
961 valid_intstat = devpriv->intsce & intstat;
962 /* Temporarily disable interrupt sources. */
963 curenab = devpriv->intsce & ~intstat;
964 outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
965 devpriv->intr_running = 1;
966 devpriv->intr_cpuid = THISCPU;
967 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
969 cmd = &s->async->cmd;
970 if (valid_intstat & PCI224_INTR_EXT) {
971 devpriv->intsce &= ~PCI224_INTR_EXT;
972 if (cmd->start_src == TRIG_EXT)
973 pci224_ao_start(dev, s);
974 else if (cmd->stop_src == TRIG_EXT)
975 pci224_ao_stop(dev, s);
977 if (valid_intstat & PCI224_INTR_DAC)
978 pci224_ao_handle_fifo(dev, s);
980 /* Reenable interrupt sources. */
981 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
982 if (curenab != devpriv->intsce) {
983 outb(devpriv->intsce,
984 devpriv->iobase1 + PCI224_INT_SCE);
986 devpriv->intr_running = 0;
987 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
989 return IRQ_RETVAL(retval);
993 pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
995 struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
996 const struct pci224_board *board = NULL;
997 struct pci224_private *devpriv;
998 struct comedi_subdevice *s;
1002 if (context_model < ARRAY_SIZE(pci224_boards))
1003 board = &pci224_boards[context_model];
1004 if (!board || !board->name) {
1005 dev_err(dev->class_dev,
1006 "amplc_pci224: BUG! cannot determine board type!\n");
1009 dev->board_ptr = board;
1010 dev->board_name = board->name;
1012 dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n",
1013 pci_name(pci_dev), dev->board_name);
1015 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1019 ret = comedi_pci_enable(dev);
1023 spin_lock_init(&devpriv->ao_spinlock);
1025 devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1026 dev->iobase = pci_resource_start(pci_dev, 3);
1029 /* Allocate buffer to hold values for AO channel scan. */
1030 devpriv->ao_scan_vals = kmalloc_array(board->ao_chans,
1031 sizeof(devpriv->ao_scan_vals[0]),
1033 if (!devpriv->ao_scan_vals)
1036 /* Allocate buffer to hold AO channel scan order. */
1037 devpriv->ao_scan_order =
1038 kmalloc_array(board->ao_chans,
1039 sizeof(devpriv->ao_scan_order[0]),
1041 if (!devpriv->ao_scan_order)
1044 /* Disable interrupt sources. */
1045 devpriv->intsce = 0;
1046 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1048 /* Initialize the DAC hardware. */
1049 outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1050 outw(0, dev->iobase + PCI224_DACCEN);
1051 outw(0, dev->iobase + PCI224_FIFOSIZ);
1052 devpriv->daccon = PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1053 PCI224_DACCON_FIFOENAB | PCI224_DACCON_FIFOINTR_EMPTY;
1054 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1055 dev->iobase + PCI224_DACCON);
1057 dev->pacer = comedi_8254_init(devpriv->iobase1 + PCI224_Z2_BASE,
1058 I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
1062 ret = comedi_alloc_subdevices(dev, 1);
1066 s = &dev->subdevices[0];
1067 /* Analog output subdevice. */
1068 s->type = COMEDI_SUBD_AO;
1069 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1070 s->n_chan = board->ao_chans;
1071 s->maxdata = (1 << board->ao_bits) - 1;
1072 s->range_table = board->ao_range;
1073 s->insn_write = pci224_ao_insn_write;
1074 s->len_chanlist = s->n_chan;
1075 dev->write_subdev = s;
1076 s->do_cmd = pci224_ao_cmd;
1077 s->do_cmdtest = pci224_ao_cmdtest;
1078 s->cancel = pci224_ao_cancel;
1079 s->munge = pci224_ao_munge;
1081 ret = comedi_alloc_subdev_readback(s);
1086 ret = request_irq(irq, pci224_interrupt, IRQF_SHARED,
1087 dev->board_name, dev);
1089 dev_err(dev->class_dev,
1090 "error! unable to allocate irq %u\n", irq);
1099 static void pci224_detach(struct comedi_device *dev)
1101 struct pci224_private *devpriv = dev->private;
1103 comedi_pci_detach(dev);
1105 kfree(devpriv->ao_scan_vals);
1106 kfree(devpriv->ao_scan_order);
1110 static struct comedi_driver amplc_pci224_driver = {
1111 .driver_name = "amplc_pci224",
1112 .module = THIS_MODULE,
1113 .detach = pci224_detach,
1114 .auto_attach = pci224_auto_attach,
1115 .board_name = &pci224_boards[0].name,
1116 .offset = sizeof(struct pci224_board),
1117 .num_names = ARRAY_SIZE(pci224_boards),
1120 static int amplc_pci224_pci_probe(struct pci_dev *dev,
1121 const struct pci_device_id *id)
1123 return comedi_pci_auto_config(dev, &lc_pci224_driver,
1127 static const struct pci_device_id amplc_pci224_pci_table[] = {
1128 { PCI_VDEVICE(AMPLICON, 0x0007), pci224_model },
1129 { PCI_VDEVICE(AMPLICON, 0x0008), pci234_model },
1132 MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table);
1134 static struct pci_driver amplc_pci224_pci_driver = {
1135 .name = "amplc_pci224",
1136 .id_table = amplc_pci224_pci_table,
1137 .probe = amplc_pci224_pci_probe,
1138 .remove = comedi_pci_auto_unconfig,
1140 module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
1142 MODULE_AUTHOR("Comedi http://www.comedi.org");
1143 MODULE_DESCRIPTION("Comedi driver for Amplicon PCI224 and PCI234 AO boards");
1144 MODULE_LICENSE("GPL");