Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

Linux/drivers/staging/comedi/drivers/amplc_pci224.c

  1 /*
  2  * comedi/drivers/amplc_pci224.c
  3  * Driver for Amplicon PCI224 and PCI234 AO boards.
  4  *
  5  * Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/>
  6  *
  7  * COMEDI - Linux Control and Measurement Device Interface
  8  * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
  9  *
 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.
 14  *
 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.
 19  */
 20 
 21 /*
 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
 28  *
 29  * Supports:
 30  *
 31  *   - ao_insn read/write
 32  *   - ao_do_cmd mode with the following sources:
 33  *
 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
 39  *
 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
 42  *     the channel list.
 43  *
 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.
 46  *
 47  * Configuration options:
 48  *   none
 49  *
 50  * Manual configuration of PCI cards is not supported; they are configured
 51  * automatically.
 52  *
 53  * Output range selection - PCI224:
 54  *
 55  *   Output ranges on PCI224 are partly software-selectable and partly
 56  *   hardware-selectable according to jumper LK1.  All channels are set
 57  *   to the same range:
 58  *
 59  *   - LK1 position 1-2 (factory default) corresponds to the following
 60  *     comedi ranges:
 61  *
 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]
 64  *
 65  *   - LK1 position 2-3 corresponds to the following Comedi ranges, using
 66  *     an external voltage reference:
 67  *
 68  *       0: [-Vext,+Vext],
 69  *       1: [0,+Vext]
 70  *
 71  * Output range selection - PCI234:
 72  *
 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:
 79  *
 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]
 86  *
 87  * Caveats:
 88  *
 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.
 93  *
 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
102  *      correctly.
103  */
104 
105 #include <linux/module.h>
106 #include <linux/pci.h>
107 #include <linux/interrupt.h>
108 #include <linux/slab.h>
109 
110 #include "../comedidev.h"
111 
112 #include "comedi_fc.h"
113 #include "8253.h"
114 
115 /*
116  * PCI224/234 i/o space 1 (PCIBAR2) registers.
117  */
118 #define PCI224_Z2_CT0   0x14    /* 82C54 counter/timer 0 */
119 #define PCI224_Z2_CT1   0x15    /* 82C54 counter/timer 1 */
120 #define PCI224_Z2_CT2   0x16    /* 82C54 counter/timer 2 */
121 #define PCI224_Z2_CTC   0x17    /* 82C54 counter/timer control word */
122 #define PCI224_ZCLK_SCE 0x1A    /* Group Z Clock Configuration Register */
123 #define PCI224_ZGAT_SCE 0x1D    /* Group Z Gate Configuration Register */
124 #define PCI224_INT_SCE  0x1E    /* ISR Interrupt source mask register */
125                                 /* /Interrupt status */
126 
127 /*
128  * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
129  */
130 #define PCI224_DACDATA  0x00    /* (w-o) DAC FIFO data. */
131 #define PCI224_SOFTTRIG 0x00    /* (r-o) DAC software scan trigger. */
132 #define PCI224_DACCON   0x02    /* (r/w) DAC status/configuration. */
133 #define PCI224_FIFOSIZ  0x04    /* (w-o) FIFO size for wraparound mode. */
134 #define PCI224_DACCEN   0x06    /* (w-o) DAC channel enable register. */
135 
136 /*
137  * DACCON values.
138  */
139 /* (r/w) Scan trigger. */
140 #define PCI224_DACCON_TRIG_MASK         (7 << 0)
141 #define PCI224_DACCON_TRIG_NONE         (0 << 0)        /* none */
142 #define PCI224_DACCON_TRIG_SW           (1 << 0)        /* software trig */
143 #define PCI224_DACCON_TRIG_EXTP         (2 << 0)        /* ext +ve edge */
144 #define PCI224_DACCON_TRIG_EXTN         (3 << 0)        /* ext -ve edge */
145 #define PCI224_DACCON_TRIG_Z2CT0        (4 << 0)        /* Z2 CT0 out */
146 #define PCI224_DACCON_TRIG_Z2CT1        (5 << 0)        /* Z2 CT1 out */
147 #define PCI224_DACCON_TRIG_Z2CT2        (6 << 0)        /* Z2 CT2 out */
148 /* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */
149 #define PCI224_DACCON_POLAR_MASK        (1 << 3)
150 #define PCI224_DACCON_POLAR_UNI         (0 << 3)        /* range [0,Vref] */
151 #define PCI224_DACCON_POLAR_BI          (1 << 3)        /* range [-Vref,Vref] */
152 /* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */
153 #define PCI224_DACCON_VREF_MASK         (3 << 4)
154 #define PCI224_DACCON_VREF_1_25         (0 << 4)        /* Vref = 1.25V */
155 #define PCI224_DACCON_VREF_2_5          (1 << 4)        /* Vref = 2.5V */
156 #define PCI224_DACCON_VREF_5            (2 << 4)        /* Vref = 5V */
157 #define PCI224_DACCON_VREF_10           (3 << 4)        /* Vref = 10V */
158 /* (r/w) Wraparound mode enable (to play back stored waveform). */
159 #define PCI224_DACCON_FIFOWRAP          (1 << 7)
160 /* (r/w) FIFO enable.  It MUST be set! */
161 #define PCI224_DACCON_FIFOENAB          (1 << 8)
162 /* (r/w) FIFO interrupt trigger level (most values are not very useful). */
163 #define PCI224_DACCON_FIFOINTR_MASK     (7 << 9)
164 #define PCI224_DACCON_FIFOINTR_EMPTY    (0 << 9)        /* when empty */
165 #define PCI224_DACCON_FIFOINTR_NEMPTY   (1 << 9)        /* when not empty */
166 #define PCI224_DACCON_FIFOINTR_NHALF    (2 << 9)        /* when not half full */
167 #define PCI224_DACCON_FIFOINTR_HALF     (3 << 9)        /* when half full */
168 #define PCI224_DACCON_FIFOINTR_NFULL    (4 << 9)        /* when not full */
169 #define PCI224_DACCON_FIFOINTR_FULL     (5 << 9)        /* when full */
170 /* (r-o) FIFO fill level. */
171 #define PCI224_DACCON_FIFOFL_MASK       (7 << 12)
172 #define PCI224_DACCON_FIFOFL_EMPTY      (1 << 12)       /* 0 */
173 #define PCI224_DACCON_FIFOFL_ONETOHALF  (0 << 12)       /* [1,2048] */
174 #define PCI224_DACCON_FIFOFL_HALFTOFULL (4 << 12)       /* [2049,4095] */
175 #define PCI224_DACCON_FIFOFL_FULL       (6 << 12)       /* 4096 */
176 /* (r-o) DAC busy flag. */
177 #define PCI224_DACCON_BUSY              (1 << 15)
178 /* (w-o) FIFO reset. */
179 #define PCI224_DACCON_FIFORESET         (1 << 12)
180 /* (w-o) Global reset (not sure what it does). */
181 #define PCI224_DACCON_GLOBALRESET       (1 << 13)
182 
183 /*
184  * DAC FIFO size.
185  */
186 #define PCI224_FIFO_SIZE        4096
187 
188 /*
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
191  * has been written!
192  */
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
197 
198 /*
199  * Counter/timer clock input configuration sources.
200  */
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))
211 
212 /*
213  * Counter/timer gate input configuration sources.
214  */
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))
221 
222 /*
223  * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234:
224  *
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
232  */
233 
234 /*
235  * Interrupt enable/status bits
236  */
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 */
240 
241 #define PCI224_INTR_EDGE_BITS   (PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
242 #define PCI224_INTR_LEVEL_BITS  PCI224_INTR_DACFIFO
243 
244 /*
245  * Handy macros.
246  */
247 
248 /* Combine old and new bits. */
249 #define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
250 
251 /* Current CPU.  XXX should this be hard_smp_processor_id()? */
252 #define THISCPU         smp_processor_id()
253 
254 /* State bits for use with atomic bit operations. */
255 #define AO_CMD_STARTED  0
256 
257 /*
258  * Range tables.
259  */
260 
261 /*
262  * The ranges for PCI224.
263  *
264  * These are partly hardware-selectable by jumper LK1 and partly
265  * software-selectable.
266  *
267  * All channels share the same hardware range.
268  */
269 static const struct comedi_lrange range_pci224 = {
270         10, {
271                 /* jumper LK1 in position 1-2 (factory default) */
272                 BIP_RANGE(10),
273                 BIP_RANGE(5),
274                 BIP_RANGE(2.5),
275                 BIP_RANGE(1.25),
276                 UNI_RANGE(10),
277                 UNI_RANGE(5),
278                 UNI_RANGE(2.5),
279                 UNI_RANGE(1.25),
280                 /* jumper LK1 in position 2-3 */
281                 RANGE_ext(-1, 1),       /* bipolar [-Vext,+Vext] */
282                 RANGE_ext(0, 1),        /* unipolar [0,+Vext] */
283         }
284 };
285 
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,
299 };
300 
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,
304 };
305 
306 /*
307  * The ranges for PCI234.
308  *
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
311  * individually.
312  */
313 static const struct comedi_lrange range_pci234 = {
314         4, {
315                 /* LK1: 1-2 (fact def), LK2/3/4/5: 2-3 (fac def) */
316                 BIP_RANGE(10),
317                 /* LK1: 1-2 (fact def), LK2/3/4/5: 1-2 */
318                 BIP_RANGE(5),
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] */
323         }
324 };
325 
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,
332 };
333 
334 /* Used to check all channels use same LK1 setting on PCI234. */
335 static const unsigned char range_check_pci234[4] = {
336         0, 0, 1, 1,
337 };
338 
339 /*
340  * Board descriptions.
341  */
342 
343 enum pci224_model { pci224_model, pci234_model };
344 
345 struct pci224_board {
346         const char *name;
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;
352 };
353 
354 static const struct pci224_board pci224_boards[] = {
355         [pci224_model] = {
356                 .name           = "pci224",
357                 .ao_chans       = 16,
358                 .ao_bits        = 12,
359                 .ao_range       = &range_pci224,
360                 .ao_hwrange     = &hwrange_pci224[0],
361                 .ao_range_check = &range_check_pci224[0],
362         },
363         [pci234_model] = {
364                 .name           = "pci234",
365                 .ao_chans       = 4,
366                 .ao_bits        = 16,
367                 .ao_range       = &range_pci234,
368                 .ao_hwrange     = &hwrange_pci234[0],
369                 .ao_range_check = &range_check_pci234[0],
370         },
371 };
372 
373 struct pci224_private {
374         unsigned long iobase1;
375         unsigned long state;
376         spinlock_t ao_spinlock; /* spinlock for AO command handling */
377         unsigned short *ao_scan_vals;
378         unsigned char *ao_scan_order;
379         int intr_cpuid;
380         short intr_running;
381         unsigned short daccon;
382         unsigned int cached_div1;
383         unsigned int cached_div2;
384         unsigned int ao_stop_count;
385         unsigned short ao_enab; /* max 16 channels so 'short' will do */
386         unsigned char intsce;
387 };
388 
389 /*
390  * Called from the 'insn_write' function to perform a single write.
391  */
392 static void
393 pci224_ao_set_data(struct comedi_device *dev, int chan, int range,
394                    unsigned int data)
395 {
396         const struct pci224_board *thisboard = dev->board_ptr;
397         struct pci224_private *devpriv = dev->private;
398         unsigned short mangled;
399 
400         /* Enable the channel. */
401         outw(1 << chan, dev->iobase + PCI224_DACCEN);
402         /* Set range and reset FIFO. */
403         devpriv->daccon = COMBINE(devpriv->daccon, thisboard->ao_hwrange[range],
404                                   PCI224_DACCON_POLAR_MASK |
405                                   PCI224_DACCON_VREF_MASK);
406         outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
407              dev->iobase + PCI224_DACCON);
408         /*
409          * Mangle the data.  The hardware expects:
410          * - bipolar: 16-bit 2's complement
411          * - unipolar: 16-bit unsigned
412          */
413         mangled = (unsigned short)data << (16 - thisboard->ao_bits);
414         if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
415             PCI224_DACCON_POLAR_BI) {
416                 mangled ^= 0x8000;
417         }
418         /* Write mangled data to the FIFO. */
419         outw(mangled, dev->iobase + PCI224_DACDATA);
420         /* Trigger the conversion. */
421         inw(dev->iobase + PCI224_SOFTTRIG);
422 }
423 
424 static int pci224_ao_insn_write(struct comedi_device *dev,
425                                 struct comedi_subdevice *s,
426                                 struct comedi_insn *insn,
427                                 unsigned int *data)
428 {
429         unsigned int chan = CR_CHAN(insn->chanspec);
430         unsigned int range = CR_RANGE(insn->chanspec);
431         unsigned int val = s->readback[chan];
432         int i;
433 
434         for (i = 0; i < insn->n; i++) {
435                 val = data[i];
436                 pci224_ao_set_data(dev, chan, range, val);
437         }
438         s->readback[chan] = val;
439 
440         return insn->n;
441 }
442 
443 /*
444  * Kills a command running on the AO subdevice.
445  */
446 static void pci224_ao_stop(struct comedi_device *dev,
447                            struct comedi_subdevice *s)
448 {
449         struct pci224_private *devpriv = dev->private;
450         unsigned long flags;
451 
452         if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
453                 return;
454 
455 
456         spin_lock_irqsave(&devpriv->ao_spinlock, flags);
457         /* Kill the interrupts. */
458         devpriv->intsce = 0;
459         outb(0, devpriv->iobase1 + PCI224_INT_SCE);
460         /*
461          * Interrupt routine may or may not be running.  We may or may not
462          * have been called from the interrupt routine (directly or
463          * indirectly via a comedi_events() callback routine).  It's highly
464          * unlikely that we've been called from some other interrupt routine
465          * but who knows what strange things coders get up to!
466          *
467          * If the interrupt routine is currently running, wait for it to
468          * finish, unless we appear to have been called via the interrupt
469          * routine.
470          */
471         while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
472                 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
473                 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
474         }
475         spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
476         /* Reconfigure DAC for insn_write usage. */
477         outw(0, dev->iobase + PCI224_DACCEN);   /* Disable channels. */
478         devpriv->daccon =
479              COMBINE(devpriv->daccon,
480                      PCI224_DACCON_TRIG_SW | PCI224_DACCON_FIFOINTR_EMPTY,
481                      PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
482         outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
483              dev->iobase + PCI224_DACCON);
484 }
485 
486 /*
487  * Handles start of acquisition for the AO subdevice.
488  */
489 static void pci224_ao_start(struct comedi_device *dev,
490                             struct comedi_subdevice *s)
491 {
492         struct pci224_private *devpriv = dev->private;
493         struct comedi_cmd *cmd = &s->async->cmd;
494         unsigned long flags;
495 
496         set_bit(AO_CMD_STARTED, &devpriv->state);
497 
498         /* Enable interrupts. */
499         spin_lock_irqsave(&devpriv->ao_spinlock, flags);
500         if (cmd->stop_src == TRIG_EXT)
501                 devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
502         else
503                 devpriv->intsce = PCI224_INTR_DAC;
504 
505         outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
506         spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
507 }
508 
509 /*
510  * Handles interrupts from the DAC FIFO.
511  */
512 static void pci224_ao_handle_fifo(struct comedi_device *dev,
513                                   struct comedi_subdevice *s)
514 {
515         struct pci224_private *devpriv = dev->private;
516         struct comedi_cmd *cmd = &s->async->cmd;
517         unsigned int bytes_per_scan = cfc_bytes_per_scan(s);
518         unsigned int num_scans;
519         unsigned int room;
520         unsigned short dacstat;
521         unsigned int i, n;
522 
523         /* Determine number of scans available in buffer. */
524         num_scans = comedi_buf_read_n_available(s) / bytes_per_scan;
525         if (cmd->stop_src == TRIG_COUNT) {
526                 /* Fixed number of scans. */
527                 if (num_scans > devpriv->ao_stop_count)
528                         num_scans = devpriv->ao_stop_count;
529         }
530 
531         /* Determine how much room is in the FIFO (in samples). */
532         dacstat = inw(dev->iobase + PCI224_DACCON);
533         switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
534         case PCI224_DACCON_FIFOFL_EMPTY:
535                 room = PCI224_FIFO_ROOM_EMPTY;
536                 if (cmd->stop_src == TRIG_COUNT &&
537                     devpriv->ao_stop_count == 0) {
538                         /* FIFO empty at end of counted acquisition. */
539                         s->async->events |= COMEDI_CB_EOA;
540                         cfc_handle_events(dev, s);
541                         return;
542                 }
543                 break;
544         case PCI224_DACCON_FIFOFL_ONETOHALF:
545                 room = PCI224_FIFO_ROOM_ONETOHALF;
546                 break;
547         case PCI224_DACCON_FIFOFL_HALFTOFULL:
548                 room = PCI224_FIFO_ROOM_HALFTOFULL;
549                 break;
550         default:
551                 room = PCI224_FIFO_ROOM_FULL;
552                 break;
553         }
554         if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
555                 /* FIFO is less than half-full. */
556                 if (num_scans == 0) {
557                         /* Nothing left to put in the FIFO. */
558                         dev_err(dev->class_dev, "AO buffer underrun\n");
559                         s->async->events |= COMEDI_CB_OVERFLOW;
560                 }
561         }
562         /* Determine how many new scans can be put in the FIFO. */
563         room /= cmd->chanlist_len;
564 
565         /* Determine how many scans to process. */
566         if (num_scans > room)
567                 num_scans = room;
568 
569         /* Process scans. */
570         for (n = 0; n < num_scans; n++) {
571                 cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0],
572                                            bytes_per_scan);
573                 for (i = 0; i < cmd->chanlist_len; i++) {
574                         outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
575                              dev->iobase + PCI224_DACDATA);
576                 }
577         }
578         if (cmd->stop_src == TRIG_COUNT) {
579                 devpriv->ao_stop_count -= num_scans;
580                 if (devpriv->ao_stop_count == 0) {
581                         /*
582                          * Change FIFO interrupt trigger level to wait
583                          * until FIFO is empty.
584                          */
585                         devpriv->daccon = COMBINE(devpriv->daccon,
586                                                   PCI224_DACCON_FIFOINTR_EMPTY,
587                                                   PCI224_DACCON_FIFOINTR_MASK);
588                         outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
589                 }
590         }
591         if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
592             PCI224_DACCON_TRIG_NONE) {
593                 unsigned short trig;
594 
595                 /*
596                  * This is the initial DAC FIFO interrupt at the
597                  * start of the acquisition.  The DAC's scan trigger
598                  * has been set to 'none' up until now.
599                  *
600                  * Now that data has been written to the FIFO, the
601                  * DAC's scan trigger source can be set to the
602                  * correct value.
603                  *
604                  * BUG: The first scan will be triggered immediately
605                  * if the scan trigger source is at logic level 1.
606                  */
607                 if (cmd->scan_begin_src == TRIG_TIMER) {
608                         trig = PCI224_DACCON_TRIG_Z2CT0;
609                 } else {
610                         /* cmd->scan_begin_src == TRIG_EXT */
611                         if (cmd->scan_begin_arg & CR_INVERT)
612                                 trig = PCI224_DACCON_TRIG_EXTN;
613                         else
614                                 trig = PCI224_DACCON_TRIG_EXTP;
615                 }
616                 devpriv->daccon =
617                     COMBINE(devpriv->daccon, trig, PCI224_DACCON_TRIG_MASK);
618                 outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
619         }
620 
621         cfc_handle_events(dev, s);
622 }
623 
624 static int pci224_ao_inttrig_start(struct comedi_device *dev,
625                                    struct comedi_subdevice *s,
626                                    unsigned int trig_num)
627 {
628         struct comedi_cmd *cmd = &s->async->cmd;
629 
630         if (trig_num != cmd->start_arg)
631                 return -EINVAL;
632 
633         s->async->inttrig = NULL;
634         pci224_ao_start(dev, s);
635 
636         return 1;
637 }
638 
639 static int pci224_ao_check_chanlist(struct comedi_device *dev,
640                                     struct comedi_subdevice *s,
641                                     struct comedi_cmd *cmd)
642 {
643         const struct pci224_board *thisboard = dev->board_ptr;
644         unsigned int range_check_0;
645         unsigned int chan_mask = 0;
646         int i;
647 
648         range_check_0 = thisboard->ao_range_check[CR_RANGE(cmd->chanlist[0])];
649         for (i = 0; i < cmd->chanlist_len; i++) {
650                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
651 
652                 if (chan_mask & (1 << chan)) {
653                         dev_dbg(dev->class_dev,
654                                 "%s: entries in chanlist must contain no duplicate channels\n",
655                                 __func__);
656                         return -EINVAL;
657                 }
658                 chan_mask |= 1 << chan;
659 
660                 if (thisboard->ao_range_check[CR_RANGE(cmd->chanlist[i])] !=
661                     range_check_0) {
662                         dev_dbg(dev->class_dev,
663                                 "%s: entries in chanlist have incompatible ranges\n",
664                                 __func__);
665                         return -EINVAL;
666                 }
667         }
668 
669         return 0;
670 }
671 
672 #define MAX_SCAN_PERIOD         0xFFFFFFFFU
673 #define MIN_SCAN_PERIOD         2500
674 #define CONVERT_PERIOD          625
675 
676 /*
677  * 'do_cmdtest' function for AO subdevice.
678  */
679 static int
680 pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
681                   struct comedi_cmd *cmd)
682 {
683         struct pci224_private *devpriv = dev->private;
684         int err = 0;
685         unsigned int arg;
686 
687         /* Step 1 : check if triggers are trivially valid */
688 
689         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
690         err |= cfc_check_trigger_src(&cmd->scan_begin_src,
691                                      TRIG_EXT | TRIG_TIMER);
692         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
693         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
694         err |= cfc_check_trigger_src(&cmd->stop_src,
695                                      TRIG_COUNT | TRIG_EXT | TRIG_NONE);
696 
697         if (err)
698                 return 1;
699 
700         /* Step 2a : make sure trigger sources are unique */
701 
702         err |= cfc_check_trigger_is_unique(cmd->start_src);
703         err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
704         err |= cfc_check_trigger_is_unique(cmd->stop_src);
705 
706         /* Step 2b : and mutually compatible */
707 
708         /*
709          * There's only one external trigger signal (which makes these
710          * tests easier).  Only one thing can use it.
711          */
712         arg = 0;
713         if (cmd->start_src & TRIG_EXT)
714                 arg++;
715         if (cmd->scan_begin_src & TRIG_EXT)
716                 arg++;
717         if (cmd->stop_src & TRIG_EXT)
718                 arg++;
719         if (arg > 1)
720                 err |= -EINVAL;
721 
722         if (err)
723                 return 2;
724 
725         /* Step 3: check if arguments are trivially valid */
726 
727         switch (cmd->start_src) {
728         case TRIG_INT:
729                 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
730                 break;
731         case TRIG_EXT:
732                 /* Force to external trigger 0. */
733                 if (cmd->start_arg & ~CR_FLAGS_MASK) {
734                         cmd->start_arg =
735                             COMBINE(cmd->start_arg, 0, ~CR_FLAGS_MASK);
736                         err |= -EINVAL;
737                 }
738                 /* The only flag allowed is CR_EDGE, which is ignored. */
739                 if (cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) {
740                         cmd->start_arg = COMBINE(cmd->start_arg, 0,
741                                                  CR_FLAGS_MASK & ~CR_EDGE);
742                         err |= -EINVAL;
743                 }
744                 break;
745         }
746 
747         switch (cmd->scan_begin_src) {
748         case TRIG_TIMER:
749                 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
750                                                  MAX_SCAN_PERIOD);
751 
752                 arg = cmd->chanlist_len * CONVERT_PERIOD;
753                 if (arg < MIN_SCAN_PERIOD)
754                         arg = MIN_SCAN_PERIOD;
755                 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
756                 break;
757         case TRIG_EXT:
758                 /* Force to external trigger 0. */
759                 if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
760                         cmd->scan_begin_arg =
761                             COMBINE(cmd->scan_begin_arg, 0, ~CR_FLAGS_MASK);
762                         err |= -EINVAL;
763                 }
764                 /* Only allow flags CR_EDGE and CR_INVERT.  Ignore CR_EDGE. */
765                 if (cmd->scan_begin_arg & CR_FLAGS_MASK &
766                     ~(CR_EDGE | CR_INVERT)) {
767                         cmd->scan_begin_arg =
768                             COMBINE(cmd->scan_begin_arg, 0,
769                                     CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
770                         err |= -EINVAL;
771                 }
772                 break;
773         }
774 
775         err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
776         err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
777 
778         switch (cmd->stop_src) {
779         case TRIG_COUNT:
780                 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
781                 break;
782         case TRIG_EXT:
783                 /* Force to external trigger 0. */
784                 if (cmd->stop_arg & ~CR_FLAGS_MASK) {
785                         cmd->stop_arg =
786                             COMBINE(cmd->stop_arg, 0, ~CR_FLAGS_MASK);
787                         err |= -EINVAL;
788                 }
789                 /* The only flag allowed is CR_EDGE, which is ignored. */
790                 if (cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) {
791                         cmd->stop_arg =
792                             COMBINE(cmd->stop_arg, 0, CR_FLAGS_MASK & ~CR_EDGE);
793                 }
794                 break;
795         case TRIG_NONE:
796                 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
797                 break;
798         }
799 
800         if (err)
801                 return 3;
802 
803         /* Step 4: fix up any arguments. */
804 
805         if (cmd->scan_begin_src == TRIG_TIMER) {
806                 arg = cmd->scan_begin_arg;
807                 /* Use two timers. */
808                 i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
809                                           &devpriv->cached_div1,
810                                           &devpriv->cached_div2,
811                                           &arg, cmd->flags);
812                 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
813         }
814 
815         if (err)
816                 return 4;
817 
818         /* Step 5: check channel list if it exists */
819         if (cmd->chanlist && cmd->chanlist_len > 0)
820                 err |= pci224_ao_check_chanlist(dev, s, cmd);
821 
822         if (err)
823                 return 5;
824 
825         return 0;
826 }
827 
828 static void pci224_ao_start_pacer(struct comedi_device *dev,
829                                   struct comedi_subdevice *s)
830 {
831         struct pci224_private *devpriv = dev->private;
832         unsigned long timer_base = devpriv->iobase1 + PCI224_Z2_CT0;
833 
834         /*
835          * The output of timer Z2-0 will be used as the scan trigger
836          * source.
837          */
838         /* Make sure Z2-0 is gated on.  */
839         outb(GAT_CONFIG(0, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
840         /* Cascading with Z2-2. */
841         /* Make sure Z2-2 is gated on.  */
842         outb(GAT_CONFIG(2, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
843         /* Z2-2 needs 10 MHz clock. */
844         outb(CLK_CONFIG(2, CLK_10MHZ), devpriv->iobase1 + PCI224_ZCLK_SCE);
845         /* Load Z2-2 mode (2) and counter (div1). */
846         i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
847         i8254_write(timer_base, 0, 2, devpriv->cached_div1);
848         /* Z2-0 is clocked from Z2-2's output. */
849         outb(CLK_CONFIG(0, CLK_OUTNM1), devpriv->iobase1 + PCI224_ZCLK_SCE);
850         /* Load Z2-0 mode (2) and counter (div2). */
851         i8254_set_mode(timer_base, 0, 0, I8254_MODE2 | I8254_BINARY);
852         i8254_write(timer_base, 0, 0, devpriv->cached_div2);
853 }
854 
855 static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
856 {
857         const struct pci224_board *thisboard = dev->board_ptr;
858         struct pci224_private *devpriv = dev->private;
859         struct comedi_cmd *cmd = &s->async->cmd;
860         int range;
861         unsigned int i, j;
862         unsigned int ch;
863         unsigned int rank;
864         unsigned long flags;
865 
866         /* Cannot handle null/empty chanlist. */
867         if (cmd->chanlist == NULL || cmd->chanlist_len == 0)
868                 return -EINVAL;
869 
870 
871         /* Determine which channels are enabled and their load order.  */
872         devpriv->ao_enab = 0;
873 
874         for (i = 0; i < cmd->chanlist_len; i++) {
875                 ch = CR_CHAN(cmd->chanlist[i]);
876                 devpriv->ao_enab |= 1U << ch;
877                 rank = 0;
878                 for (j = 0; j < cmd->chanlist_len; j++) {
879                         if (CR_CHAN(cmd->chanlist[j]) < ch)
880                                 rank++;
881                 }
882                 devpriv->ao_scan_order[rank] = i;
883         }
884 
885         /* Set enabled channels. */
886         outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
887 
888         /* Determine range and polarity.  All channels the same.  */
889         range = CR_RANGE(cmd->chanlist[0]);
890 
891         /*
892          * Set DAC range and polarity.
893          * Set DAC scan trigger source to 'none'.
894          * Set DAC FIFO interrupt trigger level to 'not half full'.
895          * Reset DAC FIFO.
896          *
897          * N.B. DAC FIFO interrupts are currently disabled.
898          */
899         devpriv->daccon =
900             COMBINE(devpriv->daccon,
901                     thisboard->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE |
902                     PCI224_DACCON_FIFOINTR_NHALF,
903                     PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK |
904                     PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
905         outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
906              dev->iobase + PCI224_DACCON);
907 
908         if (cmd->scan_begin_src == TRIG_TIMER)
909                 pci224_ao_start_pacer(dev, s);
910 
911         /*
912          * Sort out end of acquisition.
913          */
914         if (cmd->stop_src == TRIG_COUNT)
915                 devpriv->ao_stop_count = cmd->stop_arg;
916         else    /* TRIG_EXT | TRIG_NONE */
917                 devpriv->ao_stop_count = 0;
918 
919         spin_lock_irqsave(&devpriv->ao_spinlock, flags);
920         if (cmd->start_src == TRIG_INT) {
921                 s->async->inttrig = pci224_ao_inttrig_start;
922         } else {        /* TRIG_EXT */
923                 /* Enable external interrupt trigger to start acquisition. */
924                 devpriv->intsce |= PCI224_INTR_EXT;
925                 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
926         }
927         spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
928 
929         return 0;
930 }
931 
932 /*
933  * 'cancel' function for AO subdevice.
934  */
935 static int pci224_ao_cancel(struct comedi_device *dev,
936                             struct comedi_subdevice *s)
937 {
938         pci224_ao_stop(dev, s);
939         return 0;
940 }
941 
942 /*
943  * 'munge' data for AO command.
944  */
945 static void
946 pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
947                 void *data, unsigned int num_bytes, unsigned int chan_index)
948 {
949         const struct pci224_board *thisboard = dev->board_ptr;
950         struct comedi_cmd *cmd = &s->async->cmd;
951         unsigned short *array = data;
952         unsigned int length = num_bytes / sizeof(*array);
953         unsigned int offset;
954         unsigned int shift;
955         unsigned int i;
956 
957         /* The hardware expects 16-bit numbers. */
958         shift = 16 - thisboard->ao_bits;
959         /* Channels will be all bipolar or all unipolar. */
960         if ((thisboard->ao_hwrange[CR_RANGE(cmd->chanlist[0])] &
961              PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
962                 /* Unipolar */
963                 offset = 0;
964         } else {
965                 /* Bipolar */
966                 offset = 32768;
967         }
968         /* Munge the data. */
969         for (i = 0; i < length; i++)
970                 array[i] = (array[i] << shift) - offset;
971 }
972 
973 /*
974  * Interrupt handler.
975  */
976 static irqreturn_t pci224_interrupt(int irq, void *d)
977 {
978         struct comedi_device *dev = d;
979         struct pci224_private *devpriv = dev->private;
980         struct comedi_subdevice *s = dev->write_subdev;
981         struct comedi_cmd *cmd;
982         unsigned char intstat, valid_intstat;
983         unsigned char curenab;
984         int retval = 0;
985         unsigned long flags;
986 
987         intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
988         if (intstat) {
989                 retval = 1;
990                 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
991                 valid_intstat = devpriv->intsce & intstat;
992                 /* Temporarily disable interrupt sources. */
993                 curenab = devpriv->intsce & ~intstat;
994                 outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
995                 devpriv->intr_running = 1;
996                 devpriv->intr_cpuid = THISCPU;
997                 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
998                 if (valid_intstat) {
999                         cmd = &s->async->cmd;
1000                         if (valid_intstat & PCI224_INTR_EXT) {
1001                                 devpriv->intsce &= ~PCI224_INTR_EXT;
1002                                 if (cmd->start_src == TRIG_EXT)
1003                                         pci224_ao_start(dev, s);
1004                                 else if (cmd->stop_src == TRIG_EXT)
1005                                         pci224_ao_stop(dev, s);
1006                         }
1007                         if (valid_intstat & PCI224_INTR_DAC)
1008                                 pci224_ao_handle_fifo(dev, s);
1009                 }
1010                 /* Reenable interrupt sources. */
1011                 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1012                 if (curenab != devpriv->intsce) {
1013                         outb(devpriv->intsce,
1014                              devpriv->iobase1 + PCI224_INT_SCE);
1015                 }
1016                 devpriv->intr_running = 0;
1017                 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1018         }
1019         return IRQ_RETVAL(retval);
1020 }
1021 
1022 static int
1023 pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
1024 {
1025         struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
1026         const struct pci224_board *thisboard = NULL;
1027         struct pci224_private *devpriv;
1028         struct comedi_subdevice *s;
1029         unsigned int irq;
1030         int ret;
1031 
1032         if (context_model < ARRAY_SIZE(pci224_boards))
1033                 thisboard = &pci224_boards[context_model];
1034         if (!thisboard || !thisboard->name) {
1035                 dev_err(dev->class_dev,
1036                         "amplc_pci224: BUG! cannot determine board type!\n");
1037                 return -EINVAL;
1038         }
1039         dev->board_ptr = thisboard;
1040         dev->board_name = thisboard->name;
1041 
1042         dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n",
1043                  pci_name(pci_dev), dev->board_name);
1044 
1045         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1046         if (!devpriv)
1047                 return -ENOMEM;
1048 
1049         ret = comedi_pci_enable(dev);
1050         if (ret)
1051                 return ret;
1052 
1053         spin_lock_init(&devpriv->ao_spinlock);
1054 
1055         devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1056         dev->iobase = pci_resource_start(pci_dev, 3);
1057         irq = pci_dev->irq;
1058 
1059         /* Allocate buffer to hold values for AO channel scan. */
1060         devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) *
1061                                         thisboard->ao_chans, GFP_KERNEL);
1062         if (!devpriv->ao_scan_vals)
1063                 return -ENOMEM;
1064 
1065 
1066         /* Allocate buffer to hold AO channel scan order. */
1067         devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) *
1068                                          thisboard->ao_chans, GFP_KERNEL);
1069         if (!devpriv->ao_scan_order)
1070                 return -ENOMEM;
1071 
1072 
1073         /* Disable interrupt sources. */
1074         devpriv->intsce = 0;
1075         outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1076 
1077         /* Initialize the DAC hardware. */
1078         outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1079         outw(0, dev->iobase + PCI224_DACCEN);
1080         outw(0, dev->iobase + PCI224_FIFOSIZ);
1081         devpriv->daccon = PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1082                           PCI224_DACCON_FIFOENAB | PCI224_DACCON_FIFOINTR_EMPTY;
1083         outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1084              dev->iobase + PCI224_DACCON);
1085 
1086         ret = comedi_alloc_subdevices(dev, 1);
1087         if (ret)
1088                 return ret;
1089 
1090         s = &dev->subdevices[0];
1091         /* Analog output subdevice. */
1092         s->type = COMEDI_SUBD_AO;
1093         s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1094         s->n_chan = thisboard->ao_chans;
1095         s->maxdata = (1 << thisboard->ao_bits) - 1;
1096         s->range_table = thisboard->ao_range;
1097         s->insn_write = pci224_ao_insn_write;
1098         s->insn_read = comedi_readback_insn_read;
1099         s->len_chanlist = s->n_chan;
1100         dev->write_subdev = s;
1101         s->do_cmd = pci224_ao_cmd;
1102         s->do_cmdtest = pci224_ao_cmdtest;
1103         s->cancel = pci224_ao_cancel;
1104         s->munge = pci224_ao_munge;
1105 
1106         ret = comedi_alloc_subdev_readback(s);
1107         if (ret)
1108                 return ret;
1109 
1110         if (irq) {
1111                 ret = request_irq(irq, pci224_interrupt, IRQF_SHARED,
1112                                   dev->board_name, dev);
1113                 if (ret < 0) {
1114                         dev_err(dev->class_dev,
1115                                 "error! unable to allocate irq %u\n", irq);
1116                         return ret;
1117                 }
1118                 dev->irq = irq;
1119         }
1120 
1121         return 0;
1122 }
1123 
1124 static void pci224_detach(struct comedi_device *dev)
1125 {
1126         struct pci224_private *devpriv = dev->private;
1127 
1128         comedi_pci_detach(dev);
1129         if (devpriv) {
1130                 kfree(devpriv->ao_scan_vals);
1131                 kfree(devpriv->ao_scan_order);
1132         }
1133 }
1134 
1135 static struct comedi_driver amplc_pci224_driver = {
1136         .driver_name    = "amplc_pci224",
1137         .module         = THIS_MODULE,
1138         .detach         = pci224_detach,
1139         .auto_attach    = pci224_auto_attach,
1140         .board_name     = &pci224_boards[0].name,
1141         .offset         = sizeof(struct pci224_board),
1142         .num_names      = ARRAY_SIZE(pci224_boards),
1143 };
1144 
1145 static int amplc_pci224_pci_probe(struct pci_dev *dev,
1146                                   const struct pci_device_id *id)
1147 {
1148         return comedi_pci_auto_config(dev, &amplc_pci224_driver,
1149                                       id->driver_data);
1150 }
1151 
1152 static const struct pci_device_id amplc_pci224_pci_table[] = {
1153         { PCI_VDEVICE(AMPLICON, 0x0007), pci224_model },
1154         { PCI_VDEVICE(AMPLICON, 0x0008), pci234_model },
1155         { 0 }
1156 };
1157 MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table);
1158 
1159 static struct pci_driver amplc_pci224_pci_driver = {
1160         .name           = "amplc_pci224",
1161         .id_table       = amplc_pci224_pci_table,
1162         .probe          = amplc_pci224_pci_probe,
1163         .remove         = comedi_pci_auto_unconfig,
1164 };
1165 module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
1166 
1167 MODULE_AUTHOR("Comedi http://www.comedi.org");
1168 MODULE_DESCRIPTION("Comedi driver for Amplicon PCI224 and PCI234 AO boards");
1169 MODULE_LICENSE("GPL");
1170 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us