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.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 Driver: amplc_pci224.o
27 Description: Amplicon PCI224, PCI234
28 Author: Ian Abbott <abbotti@mev.co.uk>
29 Devices: [Amplicon] PCI224 (pci224), PCI234 (pci234)
30 Updated: Thu, 24 Feb 2005 12:29:26 +0000
31 Status: works, but see caveats
36 - ao_do_cmd mode with the following sources:
38 - start_src TRIG_INT TRIG_EXT
39 - scan_begin_src TRIG_TIMER TRIG_EXT
40 - convert_src TRIG_NOW
41 - scan_end_src TRIG_COUNT
42 - stop_src TRIG_COUNT TRIG_EXT TRIG_NONE
44 The channel list must contain at least one channel with no repeated
45 channels. The scan end count must equal the number of channels in
48 There is only one external trigger source so only one of start_src,
49 scan_begin_src or stop_src may use TRIG_EXT.
51 Configuration options - PCI224:
52 [0] - PCI bus of device (optional).
53 [1] - PCI slot of device (optional).
54 If bus/slot is not specified, the first available PCI device
56 [2] - Select available ranges according to jumper LK1. All channels
57 are set to the same range:
58 0=Jumper position 1-2 (factory default), 4 software-selectable
59 internal voltage references, giving 4 bipolar and 4 unipolar
61 [-10V,+10V], [-5V,+5V], [-2.5V,+2.5V], [-1.25V,+1.25V],
62 [0,+10V], [0,+5V], [0,+2.5V], [0,1.25V].
63 1=Jumper position 2-3, 1 external voltage reference, giving
64 1 bipolar and 1 unipolar range:
65 [-Vext,+Vext], [0,+Vext].
67 Configuration options - PCI234:
68 [0] - PCI bus of device (optional).
69 [1] - PCI slot of device (optional).
70 If bus/slot is not specified, the first available PCI device
72 [2] - Select internal or external voltage reference according to
73 jumper LK1. This affects all channels:
74 0=Jumper position 1-2 (factory default), Vref=5V internal.
75 1=Jumper position 2-3, Vref=Vext external.
76 [3] - Select channel 0 range according to jumper LK2:
77 0=Jumper position 2-3 (factory default), range [-2*Vref,+2*Vref]
78 (10V bipolar when options[2]=0).
79 1=Jumper position 1-2, range [-Vref,+Vref]
80 (5V bipolar when options[2]=0).
81 [4] - Select channel 1 range according to jumper LK3: cf. options[3].
82 [5] - Select channel 2 range according to jumper LK4: cf. options[3].
83 [6] - Select channel 3 range according to jumper LK5: cf. options[3].
85 Passing a zero for an option is the same as leaving it unspecified.
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/comedidev.h>
107 #include <linux/pci.h>
109 #include "comedi_fc.h"
112 #define DRIVER_NAME "amplc_pci224"
117 /* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
118 #define PCI_DEVICE_ID_AMPLICON_PCI224 0x0007
119 #define PCI_DEVICE_ID_AMPLICON_PCI234 0x0008
122 * PCI224/234 i/o space 1 (PCIBAR2) registers.
124 #define PCI224_IO1_SIZE 0x20 /* Size of i/o space 1 (8-bit registers) */
125 #define PCI224_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
126 #define PCI224_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
127 #define PCI224_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
128 #define PCI224_Z2_CTC 0x17 /* 82C54 counter/timer control word */
129 #define PCI224_ZCLK_SCE 0x1A /* Group Z Clock Configuration Register */
130 #define PCI224_ZGAT_SCE 0x1D /* Group Z Gate Configuration Register */
131 #define PCI224_INT_SCE 0x1E /* ISR Interrupt source mask register/Interrupt status */
134 * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
136 #define PCI224_IO2_SIZE 0x10 /* Size of i/o space 2 (16-bit registers). */
137 #define PCI224_DACDATA 0x00 /* (w-o) DAC FIFO data. */
138 #define PCI224_SOFTTRIG 0x00 /* (r-o) DAC software scan trigger. */
139 #define PCI224_DACCON 0x02 /* (r/w) DAC status/configuration. */
140 #define PCI224_FIFOSIZ 0x04 /* (w-o) FIFO size for wraparound mode. */
141 #define PCI224_DACCEN 0x06 /* (w-o) DAC channel enable register. */
146 /* (r/w) Scan trigger. */
147 #define PCI224_DACCON_TRIG_MASK (7 << 0)
148 #define PCI224_DACCON_TRIG_NONE (0 << 0) /* none */
149 #define PCI224_DACCON_TRIG_SW (1 << 0) /* software trig */
150 #define PCI224_DACCON_TRIG_EXTP (2 << 0) /* ext +ve edge */
151 #define PCI224_DACCON_TRIG_EXTN (3 << 0) /* ext -ve edge */
152 #define PCI224_DACCON_TRIG_Z2CT0 (4 << 0) /* Z2 CT0 out */
153 #define PCI224_DACCON_TRIG_Z2CT1 (5 << 0) /* Z2 CT1 out */
154 #define PCI224_DACCON_TRIG_Z2CT2 (6 << 0) /* Z2 CT2 out */
155 /* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */
156 #define PCI224_DACCON_POLAR_MASK (1 << 3)
157 #define PCI224_DACCON_POLAR_UNI (0 << 3) /* range [0,Vref] */
158 #define PCI224_DACCON_POLAR_BI (1 << 3) /* range [-Vref,+Vref]*/
159 /* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */
160 #define PCI224_DACCON_VREF_MASK (3 << 4)
161 #define PCI224_DACCON_VREF_1_25 (0 << 4) /* Vref = 1.25V */
162 #define PCI224_DACCON_VREF_2_5 (1 << 4) /* Vref = 2.5V */
163 #define PCI224_DACCON_VREF_5 (2 << 4) /* Vref = 5V */
164 #define PCI224_DACCON_VREF_10 (3 << 4) /* Vref = 10V */
165 /* (r/w) Wraparound mode enable (to play back stored waveform). */
166 #define PCI224_DACCON_FIFOWRAP (1 << 7)
167 /* (r/w) FIFO enable. It MUST be set! */
168 #define PCI224_DACCON_FIFOENAB (1 << 8)
169 /* (r/w) FIFO interrupt trigger level (most values are not very useful). */
170 #define PCI224_DACCON_FIFOINTR_MASK (7 << 9)
171 #define PCI224_DACCON_FIFOINTR_EMPTY (0 << 9) /* when empty */
172 #define PCI224_DACCON_FIFOINTR_NEMPTY (1 << 9) /* when not empty */
173 #define PCI224_DACCON_FIFOINTR_NHALF (2 << 9) /* when not half full */
174 #define PCI224_DACCON_FIFOINTR_HALF (3 << 9) /* when half full */
175 #define PCI224_DACCON_FIFOINTR_NFULL (4 << 9) /* when not full */
176 #define PCI224_DACCON_FIFOINTR_FULL (5 << 9) /* when full */
177 /* (r-o) FIFO fill level. */
178 #define PCI224_DACCON_FIFOFL_MASK (7 << 12)
179 #define PCI224_DACCON_FIFOFL_EMPTY (1 << 12) /* 0 */
180 #define PCI224_DACCON_FIFOFL_ONETOHALF (0 << 12) /* [1,2048] */
181 #define PCI224_DACCON_FIFOFL_HALFTOFULL (4 << 12) /* [2049,4095] */
182 #define PCI224_DACCON_FIFOFL_FULL (6 << 12) /* 4096 */
183 /* (r-o) DAC busy flag. */
184 #define PCI224_DACCON_BUSY (1 << 15)
185 /* (w-o) FIFO reset. */
186 #define PCI224_DACCON_FIFORESET (1 << 12)
187 /* (w-o) Global reset (not sure what it does). */
188 #define PCI224_DACCON_GLOBALRESET (1 << 13)
193 #define PCI224_FIFO_SIZE 4096
196 * DAC FIFO guaranteed minimum room available, depending on reported fill level.
197 * The maximum room available depends on the reported fill level and how much
200 #define PCI224_FIFO_ROOM_EMPTY PCI224_FIFO_SIZE
201 #define PCI224_FIFO_ROOM_ONETOHALF (PCI224_FIFO_SIZE / 2)
202 #define PCI224_FIFO_ROOM_HALFTOFULL 1
203 #define PCI224_FIFO_ROOM_FULL 0
206 * Counter/timer clock input configuration sources.
208 #define CLK_CLK 0 /* reserved (channel-specific clock) */
209 #define CLK_10MHZ 1 /* internal 10 MHz clock */
210 #define CLK_1MHZ 2 /* internal 1 MHz clock */
211 #define CLK_100KHZ 3 /* internal 100 kHz clock */
212 #define CLK_10KHZ 4 /* internal 10 kHz clock */
213 #define CLK_1KHZ 5 /* internal 1 kHz clock */
214 #define CLK_OUTNM1 6 /* output of channel-1 modulo total */
215 #define CLK_EXT 7 /* external clock */
216 /* Macro to construct clock input configuration register value. */
217 #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
218 /* Timebases in ns. */
219 #define TIMEBASE_10MHZ 100
220 #define TIMEBASE_1MHZ 1000
221 #define TIMEBASE_100KHZ 10000
222 #define TIMEBASE_10KHZ 100000
223 #define TIMEBASE_1KHZ 1000000
226 * Counter/timer gate input configuration sources.
228 #define GAT_VCC 0 /* VCC (i.e. enabled) */
229 #define GAT_GND 1 /* GND (i.e. disabled) */
230 #define GAT_EXT 2 /* reserved (external gate input) */
231 #define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */
232 /* Macro to construct gate input configuration register value. */
233 #define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
236 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234:
238 * Channel's Channel's
239 * clock input gate input
240 * Channel CLK_OUTNM1 GAT_NOUTNM2
241 * ------- ---------- -----------
242 * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT
243 * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT
244 * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT
248 * Interrupt enable/status bits
250 #define PCI224_INTR_EXT 0x01 /* rising edge on external input */
251 #define PCI224_INTR_DAC 0x04 /* DAC (FIFO) interrupt */
252 #define PCI224_INTR_Z2CT1 0x20 /* rising edge on Z2-CT1 output */
254 #define PCI224_INTR_EDGE_BITS (PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
255 #define PCI224_INTR_LEVEL_BITS PCI224_INTR_DACFIFO
261 /* Combine old and new bits. */
262 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
264 /* A generic null function pointer value. */
267 /* Current CPU. XXX should this be hard_smp_processor_id()? */
268 #define THISCPU smp_processor_id()
274 /* The software selectable internal ranges for PCI224 (option[2] == 0). */
275 static const comedi_lrange range_pci224_internal = {
289 static const unsigned short hwrange_pci224_internal[8] = {
290 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10,
291 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5,
292 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5,
293 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25,
294 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10,
295 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5,
296 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5,
297 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25,
300 /* The software selectable external ranges for PCI224 (option[2] == 1). */
301 static const comedi_lrange range_pci224_external = {
304 RANGE_ext(-1, 1), /* bipolar [-Vref,+Vref] */
305 RANGE_ext(0, 1), /* unipolar [0,+Vref] */
309 static const unsigned short hwrange_pci224_external[2] = {
310 PCI224_DACCON_POLAR_BI,
311 PCI224_DACCON_POLAR_UNI,
314 /* The hardware selectable Vref*2 external range for PCI234
315 * (option[2] == 1, option[3+n] == 0). */
316 static const comedi_lrange range_pci234_ext2 = {
323 /* The hardware selectable Vref external range for PCI234
324 * (option[2] == 1, option[3+n] == 1). */
325 static const comedi_lrange range_pci234_ext = {
332 /* This serves for all the PCI234 ranges. */
333 static const unsigned short hwrange_pci234[1] = {
334 PCI224_DACCON_POLAR_BI, /* bipolar - hardware ignores it! */
339 * Board descriptions.
342 enum pci224_model { pci224_model, pci234_model };
344 typedef struct pci224_board_struct {
346 enum pci224_model model;
347 unsigned int ao_chans;
348 unsigned int ao_bits;
351 static const pci224_board pci224_boards[] = {
370 static struct pci_device_id pci224_pci_table[] __devinitdata = {
371 { PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224,
372 PCI_ANY_ID, PCI_ANY_ID, 0, 0, pci224_model },
373 { PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234,
374 PCI_ANY_ID, PCI_ANY_ID, 0, 0, pci234_model },
377 MODULE_DEVICE_TABLE(pci, pci224_pci_table);
380 * Useful for shorthand access to the particular board structure
382 #define thisboard ((pci224_board *)dev->board_ptr)
384 /* this structure is for data unique to this hardware driver. If
385 several hardware drivers keep similar information in this structure,
386 feel free to suggest moving the variable to the comedi_device struct. */
388 struct pci_dev *pci_dev; /* PCI device */
389 const unsigned short *hwrange;
390 unsigned long iobase1;
391 spinlock_t ao_spinlock;
392 lsampl_t *ao_readback;
393 sampl_t *ao_scan_vals;
394 unsigned char *ao_scan_order;
397 short ao_cmd_running;
398 unsigned short daccon;
399 unsigned int cached_div1;
400 unsigned int cached_div2;
401 unsigned int ao_stop_count;
402 short ao_stop_continuous;
403 unsigned short ao_enab; /* max 16 channels so 'short' will do */
404 unsigned char intsce;
407 #define devpriv ((pci224_private *)dev->private)
410 * The comedi_driver structure tells the Comedi core module
411 * which functions to call to configure/deconfigure (attach/detach)
412 * the board, and also about the kernel module that contains
415 static int pci224_attach(comedi_device *dev,comedi_devconfig *it);
416 static int pci224_detach(comedi_device *dev);
417 static comedi_driver driver_amplc_pci224 = {
418 driver_name: DRIVER_NAME,
420 attach: pci224_attach,
421 detach: pci224_detach,
422 board_name: &pci224_boards[0].name,
423 offset: sizeof(pci224_board),
424 num_names: sizeof(pci224_boards) / sizeof(pci224_board),
426 COMEDI_INITCLEANUP(driver_amplc_pci224);
429 * Called from the 'insn_write' function to perform a single write.
432 pci224_ao_set_data(comedi_device *dev, int chan, int range, lsampl_t data)
434 unsigned short mangled;
436 /* Store unmangled data for readback. */
437 devpriv->ao_readback[chan] = data;
438 /* Enable the channel. */
439 outw(1 << chan, dev->iobase + PCI224_DACCEN);
440 /* Set range and reset FIFO. */
441 devpriv->daccon = COMBINE(devpriv->daccon, devpriv->hwrange[range],
442 (PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK));
443 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
444 dev->iobase + PCI224_DACCON);
446 * Mangle the data. The hardware expects:
447 * - bipolar: 16-bit 2's complement
448 * - unipolar: 16-bit unsigned
450 mangled = (unsigned short)data << (16 - thisboard->ao_bits);
451 if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
452 PCI224_DACCON_POLAR_BI) {
455 /* Write mangled data to the FIFO. */
456 outw(mangled, dev->iobase + PCI224_DACDATA);
457 /* Trigger the conversion. */
458 inw(dev->iobase + PCI224_SOFTTRIG);
462 * 'insn_write' function for AO subdevice.
465 pci224_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
466 comedi_insn *insn, lsampl_t *data)
472 /* Unpack channel and range. */
473 chan = CR_CHAN(insn->chanspec);
474 range = CR_RANGE(insn->chanspec);
476 if (devpriv->ao_cmd_running) {
479 /* Writing a list of values to an AO channel is probably not
480 * very useful, but that's how the interface is defined. */
481 for (i = 0; i < insn->n; i++) {
482 pci224_ao_set_data(dev, chan, range, data[i]);
490 * 'insn_read' function for AO subdevice.
492 * N.B. The value read will not be valid if the DAC channel has
493 * never been written successfully since the device was attached
494 * or since the channel has been used by an AO streaming write
498 pci224_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
499 comedi_insn *insn, lsampl_t *data)
504 chan = CR_CHAN(insn->chanspec);
506 for (i = 0; i < insn->n; i++) {
507 data[i] = devpriv->ao_readback[chan];
514 * Just a wrapper for the inline function 'i8253_cascade_ns_to_timer'.
517 pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2,
518 unsigned int *nanosec, int round_mode)
520 i8253_cascade_ns_to_timer(osc_base, d1, d2, nanosec, round_mode);
524 * Kills a command running on the AO subdevice.
527 pci224_ao_stop(comedi_device *dev, comedi_subdevice *s)
531 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
532 /* Turn off the internal trigger. */
533 s->async->inttrig = NULLFUNC;
534 /* Kill the interrupts. */
536 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
538 * Interrupt routine may or may not be running. We may or may not
539 * have been called from the interrupt routine (directly or
540 * indirectly via a comedi_events() callback routine). It's highly
541 * unlikely that we've been called from some other interrupt routine
542 * but who knows what strange things coders get up to!
544 * If the interrupt routine is currently running, wait for it to
545 * finish, unless we appear to have been called via the interrupt
548 while (devpriv->intr_running &&
549 devpriv->intr_cpuid != THISCPU) {
550 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
551 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
553 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
554 /* Reconfigure DAC for insn_write usage. */
555 outw(0, dev->iobase + PCI224_DACCEN); /* Disable channels. */
556 devpriv->daccon = COMBINE(devpriv->daccon,
557 PCI224_DACCON_TRIG_SW | PCI224_DACCON_FIFOINTR_EMPTY,
558 PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
559 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
560 dev->iobase + PCI224_DACCON);
561 /* No longer running AO command. */
562 devpriv->ao_cmd_running = 0;
566 * Handles start of acquisition for the AO subdevice.
569 pci224_ao_start(comedi_device *dev, comedi_subdevice *s)
571 comedi_cmd *cmd = &s->async->cmd;
574 if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) {
575 /* An empty acquisition! */
576 pci224_ao_stop(dev, s);
577 s->async->events |= COMEDI_CB_EOA;
578 comedi_event(dev, s, s->async->events);
580 /* Enable interrupts. */
581 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
582 if (cmd->stop_src == TRIG_EXT) {
583 devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
585 devpriv->intsce = PCI224_INTR_DAC;
587 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
588 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
593 * Handles interrupts from the DAC FIFO.
596 pci224_ao_handle_fifo(comedi_device *dev, comedi_subdevice *s)
598 comedi_cmd *cmd = &s->async->cmd;
599 unsigned int num_scans;
601 unsigned short dacstat;
603 unsigned int bytes_per_scan;
605 if (cmd->chanlist_len) {
606 bytes_per_scan = cmd->chanlist_len * sizeof(sampl_t);
608 /* Shouldn't get here! */
609 bytes_per_scan = sizeof(sampl_t);
611 /* Determine number of scans available in buffer. */
612 num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan;
613 if (!devpriv->ao_stop_continuous) {
614 /* Fixed number of scans. */
615 if (num_scans > devpriv->ao_stop_count) {
616 num_scans = devpriv->ao_stop_count;
620 /* Determine how much room is in the FIFO (in samples). */
621 dacstat = inw(dev->iobase + PCI224_DACCON);
622 switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
623 case PCI224_DACCON_FIFOFL_EMPTY:
624 room = PCI224_FIFO_ROOM_EMPTY;
625 if (!devpriv->ao_stop_continuous &&
626 devpriv->ao_stop_count == 0) {
627 /* FIFO empty at end of counted acquisition. */
628 pci224_ao_stop(dev, s);
629 s->async->events |= COMEDI_CB_EOA;
632 case PCI224_DACCON_FIFOFL_ONETOHALF:
633 room = PCI224_FIFO_ROOM_ONETOHALF;
635 case PCI224_DACCON_FIFOFL_HALFTOFULL:
636 room = PCI224_FIFO_ROOM_HALFTOFULL;
639 room = PCI224_FIFO_ROOM_FULL;
642 if (devpriv->ao_cmd_running) {
643 if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
644 /* FIFO is less than half-full. */
645 if (num_scans == 0) {
646 /* Nothing left to put in the FIFO. */
647 pci224_ao_stop(dev, s);
648 s->async->events |= COMEDI_CB_OVERFLOW;
649 rt_printk(KERN_ERR "comedi%d: "
650 "AO buffer underrun\n",
654 /* Determine how many new scans can be put in the FIFO. */
655 if (cmd->chanlist_len) {
656 room /= cmd->chanlist_len;
658 /* Determine how many scans to process. */
659 if (num_scans > room) {
663 for (n = 0; n < num_scans; n++) {
664 cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0],
666 for (i = 0; i < cmd->chanlist_len; i++) {
667 outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
668 dev->iobase + PCI224_DACDATA);
671 if (!devpriv->ao_stop_continuous) {
672 devpriv->ao_stop_count -= num_scans;
673 if (devpriv->ao_stop_count == 0) {
675 * Change FIFO interrupt trigger level to wait
676 * until FIFO is empty.
678 devpriv->daccon = COMBINE(devpriv->daccon,
679 PCI224_DACCON_FIFOINTR_EMPTY,
680 PCI224_DACCON_FIFOINTR_MASK);
681 outw(devpriv->daccon,
682 dev->iobase + PCI224_DACCON);
685 if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
686 PCI224_DACCON_TRIG_NONE) {
690 * This is the initial DAC FIFO interrupt at the
691 * start of the acquisition. The DAC's scan trigger
692 * has been set to 'none' up until now.
694 * Now that data has been written to the FIFO, the
695 * DAC's scan trigger source can be set to the
698 * BUG: The first scan will be triggered immediately
699 * if the scan trigger source is at logic level 1.
701 if (cmd->scan_begin_src == TRIG_TIMER) {
702 trig = PCI224_DACCON_TRIG_Z2CT0;
704 /* cmd->scan_begin_src == TRIG_EXT */
705 if (cmd->scan_begin_arg & CR_INVERT) {
706 trig = PCI224_DACCON_TRIG_EXTN;
708 trig = PCI224_DACCON_TRIG_EXTP;
711 devpriv->daccon = COMBINE(devpriv->daccon, trig,
712 PCI224_DACCON_TRIG_MASK);
713 outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
716 if (s->async->events) {
717 comedi_event(dev, s, s->async->events);
722 * Internal trigger function to start acquisition on AO subdevice.
725 pci224_ao_inttrig_start(comedi_device *dev, comedi_subdevice *s,
726 unsigned int trignum)
730 if (trignum != 0) return -EINVAL;
732 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
733 if (s->async->inttrig) {
734 s->async->inttrig = NULLFUNC;
735 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
736 if (devpriv->ao_cmd_running) {
737 pci224_ao_start(dev, s);
740 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
746 #define MAX_SCAN_PERIOD 0xFFFFFFFFU
747 #define MIN_SCAN_PERIOD 2500
748 #define CONVERT_PERIOD 625
751 * 'do_cmdtest' function for AO subdevice.
754 pci224_ao_cmdtest(comedi_device *dev, comedi_subdevice *s, comedi_cmd *cmd)
759 /* Step 1: make sure trigger sources are trivially valid. */
761 tmp = cmd->start_src;
762 cmd->start_src &= TRIG_INT | TRIG_EXT;
763 if (!cmd->start_src || tmp != cmd->start_src) err++;
765 tmp = cmd->scan_begin_src;
766 cmd->scan_begin_src &= TRIG_EXT | TRIG_TIMER;
767 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) err++;
769 tmp = cmd->convert_src;
770 cmd->convert_src &= TRIG_NOW;
771 if (!cmd->convert_src || tmp != cmd->convert_src) err++;
773 tmp = cmd->scan_end_src;
774 cmd->scan_end_src &= TRIG_COUNT;
775 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) err++;
778 cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
779 if (!cmd->stop_src || tmp != cmd->stop_src) err++;
783 /* Step 2: make sure trigger sources are unique and mutually
786 /* these tests are true if more than one _src bit is set */
787 if ((cmd->start_src & (cmd->start_src - 1)) != 0) err++;
788 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) err++;
789 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) err++;
790 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) err++;
791 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) err++;
793 /* There's only one external trigger signal (which makes these
794 * tests easier). Only one thing can use it. */
796 if (cmd->start_src & TRIG_EXT) tmp++;
797 if (cmd->scan_begin_src & TRIG_EXT) tmp++;
798 if (cmd->stop_src & TRIG_EXT) tmp++;
803 /* Step 3: make sure arguments are trivially compatible. */
805 switch (cmd->start_src) {
807 if (cmd->start_arg != 0) {
813 /* Force to external trigger 0. */
814 if ((cmd->start_arg & ~CR_FLAGS_MASK) != 0) {
815 cmd->start_arg = COMBINE(cmd->start_arg, 0,
819 /* The only flag allowed is CR_EDGE, which is ignored. */
820 if ((cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
821 cmd->start_arg = COMBINE(cmd->start_arg, 0,
822 CR_FLAGS_MASK & ~CR_EDGE);
827 switch (cmd->scan_begin_src) {
829 if (cmd->scan_begin_arg > MAX_SCAN_PERIOD) {
830 cmd->scan_begin_arg = MAX_SCAN_PERIOD;
833 tmp = cmd->chanlist_len * CONVERT_PERIOD;
834 if (tmp < MIN_SCAN_PERIOD) {
835 tmp = MIN_SCAN_PERIOD;
837 if (cmd->scan_begin_arg < tmp) {
838 cmd->scan_begin_arg = tmp;
843 /* Force to external trigger 0. */
844 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
845 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
849 /* Only allow flags CR_EDGE and CR_INVERT. Ignore CR_EDGE. */
850 if ((cmd->scan_begin_arg & CR_FLAGS_MASK &
851 ~(CR_EDGE | CR_INVERT)) != 0) {
852 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
853 CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
858 /* cmd->convert_src == TRIG_NOW */
859 if (cmd->convert_arg != 0) {
860 cmd->convert_arg = 0;
864 /* cmd->scan_end_arg == TRIG_COUNT */
865 if (cmd->scan_end_arg != cmd->chanlist_len) {
866 cmd->scan_end_arg = cmd->chanlist_len;
870 switch (cmd->stop_src) {
872 /* Any count allowed. */
875 /* Force to external trigger 0. */
876 if ((cmd->stop_arg & ~CR_FLAGS_MASK) != 0) {
877 cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
881 /* The only flag allowed is CR_EDGE, which is ignored. */
882 if ((cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
883 cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
884 CR_FLAGS_MASK & ~CR_EDGE);
888 if (cmd->stop_arg != 0) {
897 /* Step 4: fix up any arguments. */
899 if (cmd->scan_begin_src == TRIG_TIMER) {
900 unsigned int div1, div2, round;
901 int round_mode = cmd->flags & TRIG_ROUND_MASK;
903 tmp = cmd->scan_begin_arg;
904 /* Check whether to use a single timer. */
905 switch (round_mode) {
906 case TRIG_ROUND_NEAREST:
908 round = TIMEBASE_10MHZ / 2;
910 case TRIG_ROUND_DOWN:
914 round = TIMEBASE_10MHZ - 1;
917 /* Be careful to avoid overflow! */
918 div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
919 div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
921 if (div2 <= 0x10000) {
922 /* A single timer will suffice. */
923 if (div2 < 2) div2 = 2;
924 cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ;
925 if (cmd->scan_begin_arg < div2 ||
926 cmd->scan_begin_arg < TIMEBASE_10MHZ) {
928 cmd->scan_begin_arg = MAX_SCAN_PERIOD;
931 /* Use two timers. */
932 div1 = devpriv->cached_div1;
933 div2 = devpriv->cached_div2;
934 pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
935 &cmd->scan_begin_arg, round_mode);
936 devpriv->cached_div1 = div1;
937 devpriv->cached_div2 = div2;
939 if (tmp != cmd->scan_begin_arg) {
946 /* Step 5: check channel list. */
948 if (cmd->chanlist && cmd->chanlist_len > 0) {
950 enum { range_err = 1, dupchan_err = 2, };
956 * Check all channels have the same range index. Don't care
957 * about analogue reference, as we can't configure it.
959 * Check the list has no duplicate channels.
961 range = CR_RANGE(cmd->chanlist[0]);
964 for (n = 0; n < cmd->chanlist_len; n++) {
965 ch = CR_CHAN(cmd->chanlist[n]);
966 if (tmp & (1U << ch)) {
967 errors |= dupchan_err;
970 if (CR_RANGE(cmd->chanlist[n]) != range) {
975 if (errors & dupchan_err) {
976 comedi_error(dev, "entries in chanlist must "
977 "contain no duplicate "
980 if (errors & range_err) {
981 comedi_error(dev, "entries in chanlist must "
982 "all have the same range "
988 /* cmd->chanlist == NULL || cmd->chanlist_len == 0 */
998 * 'do_cmd' function for AO subdevice.
1001 pci224_ao_cmd(comedi_device *dev, comedi_subdevice *s)
1003 comedi_cmd *cmd = &s->async->cmd;
1008 unsigned long flags;
1010 /* Cannot handle null/empty chanlist. */
1011 if (cmd->chanlist == NULL || cmd->chanlist_len == 0) {
1015 devpriv->ao_cmd_running = 1;
1017 /* Determine which channels are enabled and their load order. */
1018 devpriv->ao_enab = 0;
1020 for (i = 0; i < cmd->chanlist_len; i++) {
1021 ch = CR_CHAN(cmd->chanlist[i]);
1022 devpriv->ao_enab |= 1U << ch;
1024 for (j = 0; j < cmd->chanlist_len; j++) {
1025 if (CR_CHAN(cmd->chanlist[j]) < ch) {
1029 devpriv->ao_scan_order[rank] = i;
1032 /* Set enabled channels. */
1033 outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
1035 /* Determine range and polarity. All channels the same. */
1036 range = CR_RANGE(cmd->chanlist[0]);
1039 * Set DAC range and polarity.
1040 * Set DAC scan trigger source to 'none'.
1041 * Set DAC FIFO interrupt trigger level to 'not half full'.
1044 * N.B. DAC FIFO interrupts are currently disabled.
1046 devpriv->daccon = COMBINE(devpriv->daccon,
1047 (devpriv->hwrange[range] | PCI224_DACCON_TRIG_NONE |
1048 PCI224_DACCON_FIFOINTR_NHALF),
1049 (PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK |
1050 PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK));
1051 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1052 dev->iobase + PCI224_DACCON);
1054 if (cmd->scan_begin_src == TRIG_TIMER) {
1055 unsigned int div1, div2, round;
1056 unsigned int ns = cmd->scan_begin_arg;
1057 int round_mode = cmd->flags & TRIG_ROUND_MASK;
1059 /* Check whether to use a single timer. */
1060 switch (round_mode) {
1061 case TRIG_ROUND_NEAREST:
1063 round = TIMEBASE_10MHZ / 2;
1065 case TRIG_ROUND_DOWN:
1069 round = TIMEBASE_10MHZ - 1;
1072 /* Be careful to avoid overflow! */
1073 div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
1074 div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
1076 if (div2 <= 0x10000) {
1077 /* A single timer will suffice. */
1078 if (div2 < 2) div2 = 2;
1080 div1 = 1; /* Flag that single timer to be used. */
1082 /* Use two timers. */
1083 div1 = devpriv->cached_div1;
1084 div2 = devpriv->cached_div2;
1085 pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
1090 * The output of timer Z2-0 will be used as the scan trigger
1093 /* Make sure Z2-0 is gated on. */
1094 outb(GAT_CONFIG(0, GAT_VCC),
1095 devpriv->iobase1 + PCI224_ZGAT_SCE);
1097 /* Not cascading. Z2-0 needs 10 MHz clock. */
1098 outb(CLK_CONFIG(0, CLK_10MHZ),
1099 devpriv->iobase1 + PCI224_ZCLK_SCE);
1101 /* Cascading with Z2-2. */
1102 /* Make sure Z2-2 is gated on. */
1103 outb(GAT_CONFIG(2, GAT_VCC),
1104 devpriv->iobase1 + PCI224_ZGAT_SCE);
1105 /* Z2-2 needs 10 MHz clock. */
1106 outb(CLK_CONFIG(2, CLK_10MHZ),
1107 devpriv->iobase1 + PCI224_ZCLK_SCE);
1108 /* Load Z2-2 mode (2) and counter (div1). */
1109 i8254_load(devpriv->iobase1 + PCI224_Z2_CT0,
1111 /* Z2-0 is clocked from Z2-2's output. */
1112 outb(CLK_CONFIG(0, CLK_OUTNM1),
1113 devpriv->iobase1 + PCI224_ZCLK_SCE);
1115 /* Load Z2-0 mode (2) and counter (div2). */
1116 i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, div2, 2);
1120 * Sort out end of acquisition.
1122 switch (cmd->stop_src) {
1124 /* Fixed number of scans. */
1125 devpriv->ao_stop_continuous = 0;
1126 devpriv->ao_stop_count = cmd->stop_arg;
1129 /* Continuous scans. */
1130 devpriv->ao_stop_continuous = 1;
1131 devpriv->ao_stop_count = 0;
1136 * Sort out start of acquisition.
1138 switch (cmd->start_src) {
1140 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1141 s->async->inttrig = &pci224_ao_inttrig_start;
1142 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1145 /* Enable external interrupt trigger to start acquisition. */
1146 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1147 devpriv->intsce |= PCI224_INTR_EXT;
1148 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
1149 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1157 * 'cancel' function for AO subdevice.
1160 pci224_ao_cancel(comedi_device *dev, comedi_subdevice *s)
1162 if (devpriv->ao_cmd_running) {
1163 pci224_ao_stop(dev, s);
1169 * 'munge' data for AO command.
1172 pci224_ao_munge(comedi_device *dev, comedi_subdevice *s, void *data,
1173 unsigned int num_bytes, unsigned int chan_index)
1175 comedi_async *async = s->async;
1176 sampl_t *array = data;
1177 unsigned int length = num_bytes / sizeof(*array);
1178 unsigned int offset;
1182 /* The hardware expects 16-bit numbers. */
1183 shift = 16 - thisboard->ao_bits;
1184 /* Channels will be all bipolar or all unipolar. */
1185 if ((devpriv->hwrange[CR_RANGE(async->cmd.chanlist[0])] &
1186 PCI224_DACCON_POLAR_MASK) ==
1187 PCI224_DACCON_POLAR_UNI) {
1194 /* Munge the data. */
1195 for (i = 0; i < length; i++) {
1196 array[i] = (array[i] << shift) - offset;
1201 * Interrupt handler.
1204 pci224_interrupt(int irq, void *d PT_REGS_ARG)
1206 comedi_device *dev = d;
1207 comedi_subdevice *s = &dev->subdevices[0];
1209 unsigned char intstat, valid_intstat;
1210 unsigned char curenab;
1212 unsigned long flags;
1214 intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
1217 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1218 valid_intstat = devpriv->intsce & intstat;
1219 /* Temporarily disable interrupt sources. */
1220 curenab = devpriv->intsce & ~intstat;
1221 outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
1222 devpriv->intr_running = 1;
1223 devpriv->intr_cpuid = THISCPU;
1224 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1225 if (s->async && devpriv->ao_cmd_running) {
1226 cmd = &s->async->cmd;
1227 if (valid_intstat & PCI224_INTR_EXT) {
1228 devpriv->intsce &= ~PCI224_INTR_EXT;
1229 if (cmd->start_src == TRIG_EXT) {
1230 pci224_ao_start(dev, s);
1231 } else if (cmd->stop_src == TRIG_EXT) {
1232 pci224_ao_stop(dev, s);
1235 if (valid_intstat & PCI224_INTR_DAC) {
1236 pci224_ao_handle_fifo(dev, s);
1239 /* Reenable interrupt sources. */
1240 comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1241 if (curenab != devpriv->intsce) {
1242 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
1244 devpriv->intr_running = 0;
1245 comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1247 return IRQ_RETVAL(retval);
1251 * This function looks for a PCI device matching the requested board name,
1255 pci224_find_pci(comedi_device *dev, int bus, int slot,
1256 struct pci_dev **pci_dev_p)
1258 struct pci_dev *pci_dev = NULL;
1259 struct pci_device_id *pci_id;
1263 /* Look for PCI table entry for this model. */
1264 for (pci_id = pci224_pci_table; pci_id->vendor != 0; pci_id++) {
1265 if (pci_id->driver_data == thisboard->model)
1268 if (pci_id->vendor == 0) {
1269 printk(KERN_ERR "comedi%d: %s: BUG! "
1270 "cannot determine board type!\n",
1271 dev->minor, DRIVER_NAME);
1275 /* Look for matching PCI device. */
1276 for(pci_dev = pci_get_device(pci_id->vendor, pci_id->device, NULL);
1278 pci_dev = pci_get_device(pci_id->vendor,
1279 pci_id->device, pci_dev)) {
1280 /* If bus/slot specified, check them. */
1282 if (bus != pci_dev->bus->number
1283 || slot != PCI_SLOT(pci_dev->devfn))
1287 if (pci_id->subvendor != PCI_ANY_ID) {
1288 if (pci_dev->subsystem_vendor != pci_id->subvendor)
1291 if (pci_id->subdevice != PCI_ANY_ID) {
1292 if (pci_dev->subsystem_device != pci_id->subdevice)
1296 if (((pci_dev->class ^ pci_id->class) & pci_id->class_mask) != 0)
1299 /* Found a match. */
1300 *pci_dev_p = pci_dev;
1303 /* No match found. */
1305 printk(KERN_ERR "comedi%d: error! "
1306 "no %s found at pci %02x:%02x!\n",
1307 dev->minor, thisboard->name,
1310 printk(KERN_ERR "comedi%d: error! no %s found!\n",
1311 dev->minor, thisboard->name);
1317 * Attach is called by the Comedi core to configure the driver
1318 * for a particular board. If you specified a board_name array
1319 * in the driver structure, dev->board_ptr contains that
1323 pci224_attach(comedi_device *dev,comedi_devconfig *it)
1325 comedi_subdevice *s;
1326 struct pci_dev *pci_dev;
1328 int bus = 0, slot = 0;
1332 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1335 bus = it->options[0];
1336 slot = it->options[1];
1337 if ((ret=alloc_private(dev,sizeof(pci224_private))) < 0) {
1338 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1342 if ((ret=pci224_find_pci(dev, bus, slot, &pci_dev)) < 0)
1344 devpriv->pci_dev = pci_dev;
1346 if ((ret=pci_enable_device(pci_dev)) < 0) {
1347 printk(KERN_ERR "comedi%d: error! cannot enable PCI device!\n",
1351 if (pci_request_regions(pci_dev, DRIVER_NAME)) {
1352 printk(KERN_ERR "comedi%d: error! cannot allocate PCI regions!\n",
1356 spin_lock_init(&devpriv->ao_spinlock);
1358 devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1359 dev->iobase = pci_resource_start(pci_dev, 3);
1362 /* Allocate readback buffer for AO channels. */
1363 devpriv->ao_readback = kmalloc(sizeof(devpriv->ao_readback[0]) *
1364 thisboard->ao_chans, GFP_KERNEL);
1365 if (!devpriv->ao_readback) {
1369 /* Allocate buffer to hold values for AO channel scan. */
1370 devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) *
1371 thisboard->ao_chans, GFP_KERNEL);
1372 if (!devpriv->ao_scan_vals) {
1376 /* Allocate buffer to hold AO channel scan order. */
1377 devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) *
1378 thisboard->ao_chans, GFP_KERNEL);
1379 if (!devpriv->ao_scan_order) {
1383 /* Disable interrupt sources. */
1384 devpriv->intsce = 0;
1385 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1387 /* Initialize the DAC hardware. */
1388 outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1389 outw(0, dev->iobase + PCI224_DACCEN);
1390 outw(0, dev->iobase + PCI224_FIFOSIZ);
1391 devpriv->daccon = (PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1392 PCI224_DACCON_FIFOENAB | PCI224_DACCON_FIFOINTR_EMPTY);
1393 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1394 dev->iobase + PCI224_DACCON);
1396 /* Allocate subdevices. There is only one! */
1397 if ((ret=alloc_subdevices(dev, 1)) < 0) {
1398 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1403 s = dev->subdevices + 0;
1404 /* Analog output subdevice. */
1405 s->type = COMEDI_SUBD_AO;
1406 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1407 s->n_chan = thisboard->ao_chans;
1408 s->maxdata = (1 << thisboard->ao_bits) - 1;
1409 s->insn_write = &pci224_ao_insn_write;
1410 s->insn_read = &pci224_ao_insn_read;
1411 s->len_chanlist = s->n_chan;
1413 dev->write_subdev = s;
1414 s->do_cmd = &pci224_ao_cmd;
1415 s->do_cmdtest = &pci224_ao_cmdtest;
1416 s->cancel = &pci224_ao_cancel;
1417 s->munge = &pci224_ao_munge;
1419 /* Sort out channel range options. */
1420 if (thisboard->model == pci234_model) {
1421 /* PCI234 range options. */
1422 const comedi_lrange **range_table_list;
1424 s->range_table_list = range_table_list = kmalloc(
1425 sizeof(comedi_lrange *) * s->n_chan,
1427 if (!s->range_table_list) {
1430 for (n = 2; n < 3 + s->n_chan; n++) {
1431 if (it->options[n] < 0 || it->options[n] > 1) {
1432 printk(KERN_WARNING "comedi%d: %s: warning! "
1433 "bad options[%u]=%d\n",
1434 dev->minor, DRIVER_NAME, n,
1438 for (n = 0; n < s->n_chan; n++) {
1439 if (n < COMEDI_NDEVCONFOPTS - 3 &&
1440 it->options[3+n] == 1) {
1441 if (it->options[2] == 1) {
1442 range_table_list[n] =
1445 range_table_list[n] =
1449 if (it->options[2] == 1) {
1450 range_table_list[n] =
1453 range_table_list[n] =
1458 devpriv->hwrange = hwrange_pci234;
1460 /* PCI224 range options. */
1461 if (it->options[2] == 1) {
1462 s->range_table = &range_pci224_external;
1463 devpriv->hwrange = hwrange_pci224_external;
1465 if (it->options[2] != 0) {
1466 printk(KERN_WARNING "comedi%d: %s: warning! "
1467 "bad options[2]=%d\n",
1468 dev->minor, DRIVER_NAME,
1471 s->range_table = &range_pci224_internal;
1472 devpriv->hwrange = hwrange_pci224_internal;
1476 dev->board_name = thisboard->name;
1479 ret = comedi_request_irq(irq, pci224_interrupt, IRQF_SHARED,
1482 printk(KERN_ERR "comedi%d: error! "
1483 "unable to allocate irq %u\n",
1491 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1492 printk("(pci %s) ", pci_name(pci_dev));
1494 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1496 printk("(no irq) ");
1499 printk("attached\n");
1505 * _detach is called to deconfigure a device. It should deallocate
1507 * This function is also called when _attach() fails, so it should be
1508 * careful not to release resources that were not necessarily
1509 * allocated by _attach(). dev->private and dev->subdevices are
1510 * deallocated automatically by the core.
1513 pci224_detach(comedi_device *dev)
1515 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, DRIVER_NAME);
1518 comedi_free_irq(dev->irq, dev);
1520 if (dev->subdevices) {
1521 comedi_subdevice *s;
1523 s = dev->subdevices + 0;
1525 if (s->range_table_list) {
1526 kfree(s->range_table_list);
1530 if (devpriv->ao_readback) {
1531 kfree(devpriv->ao_readback);
1533 if (devpriv->ao_scan_vals) {
1534 kfree(devpriv->ao_scan_vals);
1536 if (devpriv->ao_scan_order) {
1537 kfree(devpriv->ao_scan_order);
1539 if (devpriv->pci_dev) {
1542 pci_release_regions(devpriv->pci_dev);
1543 pci_disable_device(devpriv->pci_dev);
1545 pci_dev_put(devpriv->pci_dev);
1548 if (dev->board_name) {
1549 printk(KERN_INFO "comedi%d: %s removed\n",
1550 dev->minor, dev->board_name);