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